Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make selecting a key from a clojure hashmap a cider function. #3231

Closed
drewverlee opened this issue Jul 31, 2022 · 5 comments
Closed

make selecting a key from a clojure hashmap a cider function. #3231

drewverlee opened this issue Jul 31, 2022 · 5 comments

Comments

@drewverlee
Copy link

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:

  1. issue a command to load the list of keys
(-> {:color "blue" :location "X"}
    [*:color
     :location ])
  1. then tab down one
(-> {:color "blue" :location "X"}
      [:color
      *:location])
  1. 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!

@vemv
Copy link
Member

vemv commented Aug 1, 2022

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 keys on 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

@drewverlee
Copy link
Author

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?

@vemv
Copy link
Member

vemv commented Aug 1, 2022

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.

@drewverlee
Copy link
Author

@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?

@vemv
Copy link
Member

vemv commented Sep 10, 2022

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 src and test changes
  • 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 if foo is offered (along the other completions that will also be provided)
    • Once you have verified that foo is returned, you can refine your implementation by re-evaluating it

Hope it helps!

@vemv vemv closed this as completed Jul 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants