make selecting a key from a clojure hashmap a cider function.
I'm suggesting a feature to make selecting a key from a Clojure hashmap slightly easier by having a shortcut in cider to call clojure.core/keys and produce a list that the user can select from. The current way I do this is just like that, by printing the result of calling keys on the map like so:
(-> {:color "blue" :location "X"}
keys)
=> (:color :location)
then copying and pasting that key over the call to keys, like so.
(-> {:color "blue" :location "X"}
:location)
=> "X"
then deleting the printed keys.
This works fine, but I think this is a common enough task that having a shortcut would be nice. In the code below the vector would be an emacs list that contains the key choices and the "*" is the cursor that can go up and down. When the cursor is on a value, you could select that key, and it gets replaced. Here are roughly the steps I imagine:
- issue a command to load the list of keys
(-> {:color "blue" :location "X"}
[*:color
:location ])
- then tab down one
(-> {:color "blue" :location "X"}
[:color
*:location])
- then select one and have it inserted into the clojure code
(-> {:color "blue" :location "X"}
:location)
The first pass of this feature could generate the key list by evaluating the map. From there it might be worth considering trying to pull from other sources like the spec registry or all identifiable keys in the project.
If this idea seems sound, I'll work to submit the pull request with the functionality. If not, let me know why.
Thanks!
This sounds to me like a feature to be implemented in https://github.com/alexander-yakushev/compliment (which cider-nrepl and cider.el use):
- If the completion context is a hashmap, invoke
keyson it and offer those keys as completions.
Compliment is extensible by design (via defsource), so you might have succeed in crafting an early POC without forking anything.
Not super sure if Compliment, by default, does eval the completion context (which is side-effectful). https://github.com/clojure-emacs/clj-suitable which is part of CIDER uses a side-effectful approach to defsource (limited to ClojureScript).
eval has its tradeoffs, but probably it can work here (in the same way that eval powers many CIDER features).
LMK how this sounds.
Cheers - V
Are you suggesting using compliment functionality instead of something like emacs "completing-read" to offer key choices to the user? Cider would still be responsible for evaluating the Clojure map to get the keys right?
A normal stack for tab completions (just like the completions you get for defn/var/class names) would be cider, company-mode, cider-nrepl, Compliment.
I'm indicating that the standard place to offer a new kind of completion would be said stack - that way we leverage lots of existing code and avoid reinventing UIs.
Cider would still be responsible for evaluating the Clojure map to get the keys right?
Cider passes a "completion context" to cider-nrepl. That is forwarded to Compliment.
@vemv do you have any idea how to iteratively test extending the compliment library? As in, if I correctly create a custom compliment defsource . How do I test that it works? How would i see the effect in emacs directly?
do you have any idea how to iteratively test extending the compliment library?
There are a couple things you can do:
- write vanilla unit tests. See Compliment's suite for inspiration
- The 'iteration' part would be that, of course, you can run tests from CIDER / the repl, so you can quickly iterate between
srcandtestchanges
- The 'iteration' part would be that, of course, you can run tests from CIDER / the repl, so you can quickly iterate between
- Set up your Compliment
defsource, and see it working in CIDER- e.g. make it at first always return
foo, then trigger completion in CIDER, and check iffoois offered (along the other completions that will also be provided) - Once you have verified that
foois returned, you can refine your implementation by re-evaluating it
- e.g. make it at first always return
Hope it helps!