chrisant996 / clink

Bash's powerful command line editing in cmd.exe
https://chrisant996.github.io/clink/
GNU General Public License v3.0
3.46k stars 135 forks source link

Run readline bindable command manually #205

Closed bmix closed 2 years ago

bmix commented 2 years ago

I know, that the readline bindable command 'clink-popup-complete' exists, but I would like to invoke this manually, like

clink readline clink-popup-complete

(or something like that).

Would that be possible?

Great documentation, btw. (and overall great project ;-) !

Thank you!

chrisant996 commented 2 years ago

Can you explain why? What is the bigger thing you are trying to do?

bmix commented 2 years ago

Sure. There is no bigger thing. I just wanted to be able to list all installed command-line completions, use clink-reload and clink-show-help. But it's not a major issue. Thinking about it, it may even need some major work on your part, which I do not want to burden you with, so I'm totally fine if you want to close it.

chrisant996 commented 2 years ago

I mean that I don't understand what you mean by "invoke this manually".

What is accomplished by running clink readline clink-popup-complete? There would be no input line, so what would it be expected to complete? And what would be expected to be done with the results?

bmix commented 2 years ago

Oh, I see what you mean! Seems I have misunderstood the result of clink-popup-complete: I thought it would list all installed completion scripts, not the matching completions, that result from executing them, when text is already written on the console line (I thought, that would already be covered by readline).

With "invoking manually" I meant to type

clink readline clink-popup-complete (or similar) on the command line and get the result, that would stem from execution of the keyboard shortcut, that the command has been bound to. So, instead of hitting the shortcut, I would simply write out the name of the key-binding and get the result. Since I thought, that I could get a list of all installed completion-scripts, this way, I desired to use some of the binding-commands by writing them out, rather than creating more and more complex shortcut configurations for seldom used stuff. But I understand now, that I misunderstood the actual result of this key-binding ;-)

pukkandan commented 2 years ago

I think the request makes sense. I've also had situations where I wish I could run a command without binding a key to it. I often find myself assigning some random keybindings just so the functions are accessible from clink-popup-complete (or now in luafunc:fzf_complete from https://github.com/chrisant996/clink-fzf)

While for some commands like clink-popup-complete, it is not obvious what should happen when running it manually, there are other functions like possible-completions and custom lua scripts where it is obvious.

For functions that interact with the input line, one idea could be to allow passing initial input as a argument (clink run clink-popup-complete input) and simply print out the completion when something is selected. I don't know how difficult this would be to implement though

chrisant996 commented 2 years ago

@bmix wrote: Seems I have misunderstood the result of clink-popup-complete: I thought it would list all installed completion scripts, not the matching completions, that result from executing them, when text is already written on the console line (I thought, that would already be covered by readline).

Oh, I think you mean this:

That's something that would make sense to add to the clink-diagnostics command, which is by default bound to Ctrl+X,Ctrl+Z. It already lists registered event handlers.

By the way, Readline does not know about any of the completion scripts. Readline only knows how to generate filename completions. All other kinds of completions are things that bash or Clink or Lua scripts or etc are providing as application extensions. Readline asks the host application to give it a list of possible completions. If the app tells Readline "no you do it instead", then Readline collects filename completions.

@bmix wrote: With "invoking manually" I meant to type

clink readline clink-popup-complete (or similar) on the command line and get the result, that would stem from execution of the keyboard shortcut, that the command has been bound to. So, instead of hitting the shortcut, I would simply write out the name of the key-binding and get the result. Since I thought, that I could get a list of all installed completion-scripts, this way, I desired to use some of the binding-commands by writing them out, rather than creating more and more complex shortcut configurations for seldom used stuff. But I understand now, that I misunderstood the actual result of this key-binding ;-)

The desire makes sense. It's not possible, as stated.

Please describe a goal, rather than an implementation. Saying "I want to run any key binding command as though it were a stand-alone program" sort of makes sense for a few key binding commands. But for most of them it make no sense whatsoever. What does it mean to run the forward-char key binding command outside of Clink? So, what are the goals? What are the specific commands you want to be able to run, and why? What inputs should they take, and what outputs should they produce?

Anyway, here are some of the problems with the suggested implementation:

  1. There is no way to know "installed" completion scripts, there is only a way to know what match generators have been registered so far.
  2. There is no way to know in advance whether a script file will register any match generators. And a script can delay registering them until some action happens (one example of many could be a key binding that toggles a mode and registers additional match generators).
  3. If you run clink something then that starts a completely separate instance of clink, which knows nothing at all about what's happening inside the instance of clink that launched it. The reason clink history and clink set and clink info appear as though they do is because there are hidden environment variables that specify the profile path and the session number, which are enough to find the profile and history file and settings file. But they are reading information from the file system, they are not reporting information from the running instance of clink.
  4. The clink-popup-complete command does the following: takes the current typed input line, looks up an argmatcher based on the first word, parses the typed input line to figure out which match generators (plural!) to invoke, collects all the matches, shows them in an interactive popup window, and then inserts the selected match into the input line. If you run it as a stand-alone program, then there is no input line. So neither the inputs nor the outputs make any sense. You are really asking for some kind of unspecified input/output system that makes use of the same match generators, but everything else about it is a totally different implementation.

So the request as stated (run a command to show what is installed, or even running in memory) is not possible.

@pukkandan wrote: I think the request makes sense. I've also had situations where I wish I could run a command without binding a key to it.

Which commands? It is nonsensical to run forward-char or clink-paste or clink-reset-line or most of the available commands by typing them out as though they were separate programs. There is no input line to use as input, and there is no input line to insert/delete text from. It's sort of like saying "I really like the protection of car seat belts, and I want that protection while I go for a walk -- please make it so I can detach the seat belt from car and wear it while walking". The words of the request make perfect sense, but the concept behind the request makes no sense.

@pukkandan wrote: I often find myself assigning some random keybindings just so the functions are accessible from clink-popup-complete (or now in luafunc:fzf_complete from https://github.com/chrisant996/clink-fzf)

But that's not what clink-popup-complete does. Are you thinking of clink-popup-show-help?

@pukkandan wrote: While for some commands like clink-popup-complete, it is not obvious what should happen when running it manually, there are other functions like possible-completions and custom lua scripts where it is obvious.

Telling me it is obvious does not help me understand what you expect.

Here is how I interpret the request: You want me to write a new implementation of Clink that does not actually have an interactive input line, and instead fakes an empty one. You want to run any Readline command as though it is a separate program, and use a blank line as the input text. You want popup windows to show up, and you want output to be printed to the screen, and maybe even redirected to a file. You want commands like clink-paste to insert text into the fake input line, but you do not want the fake input line to be displayed. There are some specific commands you care about, but you don't want to list them. There are probably a bunch of commands you don't actually care about, but you want me to figure out all the hard parts and basically read your mind.

Unfortunately, my psychic powers are weak 😉 and in this particular case I need you to be more specific about what you want.

@pukkandan wrote: For functions that interact with the input line, one idea could be to allow passing initial input as a argument (clink run clink-popup-complete input) and simply print out the completion when something is selected. I don't know how difficult this would be to implement though

But why? Why do you want to type clink run --command="possible-completions" --input="git checkout " instead of simply typing git checkoutAlt+= for example?

I don't implement suggestions unless I understand the bigger picture scenario. And this one doesn't make any sense to me yet.

chrisant996 commented 2 years ago

@bmix wrote: Seems I have misunderstood the result of clink-popup-complete: I thought it would list all installed completion scripts, not the matching completions, that result from executing them, when text is already written on the console line (I thought, that would already be covered by readline).

v1.2.48 lists the registered match generators in the clink-diagnostics command, bound by default to Ctrl+X,Ctrl+Z. That should address the specific example that was originally raised.

@pukkandan wrote: For functions that interact with the input line, one idea could be to allow passing initial input as a argument (clink run clink-popup-complete input) and simply print out the completion when something is selected. I don't know how difficult this would be to implement though

But why? Why do you want to type clink run --command="possible-completions" --input="git checkout " instead of simply typing git checkoutAlt+= for example?

^ This is still the big question, for me. I'm very curious to know more.

chrisant996 commented 2 years ago

Feel free to answer the preceding questions, and reopen at that time.

Thanks!

pukkandan commented 2 years ago

Sorry, I meant to reply, but it skipped my mind.

Similar to OP, I also misunderstood the complexities involved in implementing something like this. Especially the fact that a new clink instance cannot fully communicate with the injected instance severly limits what commands can be reasonably expected to be invoked separately

But that's not what clink-popup-complete does. Are you thinking of clink-popup-show-help?

Yes, you are right. I was indeed thinking of clink-popup-show-help. On a related note, I noticed that you added ability to list unbound commands in popup-help. I haven't tested it out yet, but thanks for that! I should be able to drop a lot of useless key-bindings thanks to that

But why? Why do you want to type clink run --command="possible-completions" --input="git checkout " instead of simply typing git checkoutAlt+= for example?

The idea is (mostly) not to run this manually, but to allow external scripts to leverage clink/readline by reading/piping its output - similar to complete --do-complete in UNIX (but more powerful, since clink can do much more than complete). But I understand clink is primarily meant to be used injected into cmd and that this is not necessarily within scope of the project. So I won't ask you to re-open the issue. It's not a "I must have that feature to use this app" type of request, and more like a "It would be cool if this program could do that too" :D. Honestly, if I were in your shoes, I am not sure I would entertain such a request either

PS: Totally unrelated; how do u type the key names like that? eg in Alt+=

chrisant996 commented 2 years ago

I noticed that you added ability to list unbound commands in popup-help. I haven't tested it out yet, but thanks for that! I should be able to drop a lot of useless key-bindings thanks to that

Yup! You could even make a function that gets the full list of bindings, then removes a bunch that you know you'll never care about, and show the remaining ones in a popup list. Here is the source code for the internal Lua function that implements the clink-popup-show-help command. You can use that as the basis for a new function (e.g. to filter out commands you'll never care about) to invoke via a luafunc: key binding.

But why? Why do you want to type clink run --command="possible-completions" --input="git checkout " instead of simply typing git checkoutAlt+= for example?

The idea is (mostly) not to run this manually, but to allow external scripts to leverage clink/readline by reading/piping its output - similar to complete --do-complete in UNIX (but more powerful, since clink can do much more than complete).

How? For what? Why do external shell scripts want to get a list of how Clink would offer completions?

In bash/zsh/fish, that is useful because that command is how the shell fetches completions, so you must use that command to give completions to the shell. But in Clink, it's not useful because Clink fetches completions via Lua scripts, and has no need for an analogous complete command.

If there is a compelling purpose that would be fulfilled by a clink complete command, then I would consider it. It's a lot of work, and so far I don't know what would use it, or how, or why -- so I can't design the inputs and outputs because I have no idea yet what this idea would be for. 🙃

Also, in the original request it's unclear whether the request is to be able to invoke any and all Readline commands, or only 3 specific ones, or also some other commands. It makes a very large difference for how to implement it, and how much work it would be, so more specific information is necessary before any work could be considered or begun.

PS: Totally unrelated; how do u type the key names like that? eg in Alt+=

HTML "kbd" tags.

Typing this while composing: <kbd>Alt</kbd>+<kbd>=</kbd> Produces this when viewing: Alt+=