How to implement command autocomplete in myshell? - shell

I am making my own shell in C. I know one can use the readline library to make use of autocompletion of paths using TAB, but it can only be used for autocompletion of paths but not commands.
For example, if I write clea and press the TAB key, it does not make it clear, nor does it give suggestions for any similar commands on pressing TAB twice. How to do it?

Your shell also needs to implement a PATH variable, which is a list of directories to search for non-builtin commands. For instance, if PATH has the value /usr/bin:/bin, then your completion function would complete cle to clear if either /usr/bin/clear or /bin/clear exists.

Related

Can I press enter twice to execute a command?

I'm using ZSH and I'm wondering if it's possible to map [enter, enter] to execute a command. Specifically, I'd like to move to my home directory when I press enter twice without typing any other text.
I don't want to make someone go through the trouble of writing me a script, but if any of y'all could point me in the right direction (zsh script/applescript/whatever it should be) and tell me if this is possible I'd really appreciate it!
I use iTerm2 on OSX, and zsh is my primary shell. Let me know if you need any more information!
Have a look at preexec in the section SPECIAL FUNCTIONS of the zsh manpage. If you define a function by this name, for instance in your .zshrc, and you have the history mechanism enabled (as is common in interactive shells), this function receives as argument the command line you have entered. If you just typed enter, the command will be the null string. You can catch this and then do whatever you want - for instance doing a chdir.

Setting multiple values for Vim command -complete attribute

I am trying to enable command completion for a custom command that I am setting up for a plugin in the following manner:
command! -complete=shellcmd -nargs=* EScratch call s:ShellScratch(<f-args>)
I would like to enable complete options for shellcmd and file. However it seems that the complete attribute would only take 1 option.
To give a bit more context as to what I am trying to achieve: I am working on a plugin to create a simple scratch buffer. I would like to be able to run a shell command from the command mode and copy the output to the scratch buffer. I have been able to achieve all this but it would be much more productive to have auto completion similar to shell. The complete script can be viewed here https://github.com/ifthikhan/vimscratch/blob/master/plugin/vimscratch.vim. Any pointers will be highly appreciated.
Unfortunately, you can't. If you really need this, you have to either
define two separate commands, e.g. :ScratchShell and :ScratchFile, with the corresponding completions, or
use a -complete=custom[list] and provide your own complete function, where you have to re-implement both sources yourself. Filename completion actually is quite easily done with glob(); I'm not so sure about shell commands.

How to quickly scroll to the latest / end of command history in bash?

Lots of times I'll use Ctrl-R for reverse search and mistype some letter. Bash jumps up hundreds of lines and I'm in the middle of commands I was using a week ago.
Is there a shortcut for jumping back down to the lastest commands I had typed?
Edit: after testing it out on a CentOS server and Mac OS X, it looks like this only happening on OS X.
I've struggled with this same issue.
You can solve this by aborting with ctrl-c. Whether you're in the middle of a reverse search or scrolling through history with the arrows, aborting returns you to a prompt with the history scroll just after the last command.
UPDATE
Here's a nice trick I just learned. Bash and many other programs use Readline under the hood for command-line interpretation. Key bindings for Readline can be configured in a .inputrc file or with the bind command. The bindings can make use of a few functions provided by Readline. For example, I use Bash in vi mode but I still like to use Emacs-style ctrl-A so I have this line in my .bashrc file:
bind '\C-a:beginning-of-line'
To list all the available Readline functions:
bind -l
Among the functions is end-of-history. The function does like its name suggests. The difference between this approach and just using the abort command is that this keeps you on the same prompt.
If using libreadline, Alt-> (or Meta->). More info on Readline shortcuts or search for Commands for Manipulating the History in the man page.
On Mac, try command + .
It works for me.
I was trying alt+. and alt+shift+. , neither works for me. And then found command + . actually works
Maybe not exactly what you want, but you can fix your mistyped character(s) by using backspace when you're in the CTRL-r (reverse-i-search) mode.
You may wan to try "suggest box"-like history HSTR. It reads the bash history and allows quick navigation and filtering - you can see the context of similar history entries. Once you select a history entry it can be edited on the command line.
In Zsh with emacs binding set the actual default key sequence is ^[> binded to end-of-buffer-or-history command rather than command-. suggested above (or end-of-history depending on effect you want to achieve)
Cmd-. produces in Apple Terminal the similar or the same key sequence as Ctrl-C, which can be confirmed by running something useless and long, e.g. find . >/dev/null 2>&1 and pressing one and then other keys on keyboard.
Ctrl-C forces input to be ended and reset. and history scroll is just a side effect for it.

Shell script to grab selected text and alter it?

How can I make a shell script that will know where the caret is and grab selected text, so I can wrap the text in something? For example, this is a script from a Textmate bundle:
<${1:p}>$TM_SELECTED_TEXT</${1/\s.*//}>
It grabs the text and wraps it in open/close HTML tags. And it is variable so the second tag is mirrored as you type the first.
I want to make a script like this but outside of Textmate so I can use it in TextEXpander.
Does this make sense ? :)
$TM_SELECTED_TEXT is not an environment variable provided to scripts running outside of TextMate -- it is a variable that is set by TextMate and provided to scripts that are run as part of its snippet system. It is not even provided to the Shell bundles "Run Script" command.
What you want to do may be doable through other shell facilities (e.g., sed) so the functionality can be replicated by a shell script -- it depends on your usage scenario.

How many ways can I get Bash alias completion on a partial substring?

Question: I have a question that is apparently not answered by this already-asked Bash completion question on Stack Overflow. The question is, how to get Bash alias completion (for any alias) on a partial substring.
Example:
For example, assume I have the following aliases:
open.alicehome="cd /usr/home/alice"
open.bakerhome="cd /usr/home/baker"
open.charliehome="cd /usr/home/charlie"
gohomenow="shutdown -now"
I would like to lazily just type "baker{{TAB}}" to invoke the second alias.
I would like to lazily just type "home{{TAB}}" to get a list of all of the above aliases that I can then choose from with the keyboard (optimal) or choose by typing an unambiguous substring that distinguishes among the three options (less than optimal).
.. OR ..
I would like to lazily just type "home" and then repeatedly press {{TAB}} until the specific alias I want shows up, then press {{ENTER}} to execute it.
Feel free to be creative:
If you have a way to do this, even if it requires resorting to extreme guru hackery, please feel free to share it and feel free to explain your guru hackery to the level of a five-year-old who will have to try to implement your idea for himself.
Links to existing web-pages or RTFMs are welcome.
If you really want to change bash's tab behavior,
# ~/.inputrc
# The default binding for [Tab] is ``complete'', which is what we're used to.
# ``menu-complete'' gives you irssi-like behavior: cycle through completions.
"\t": menu-complete
This is documented in The GNU Readline Library # Letting Readline Type For You.
You can generate the matches for a specified substring with compgen -c -X'!*substring*'
To include this in bash autocompletion you can create a .bash_completion file in your home directory containing something like this:
_comp() {
local cur
cur=${COMP_WORDS[$COMP_CWORD]}
COMPREPLY=( $( compgen -c -X '!*'$cur'*' ) )
}
complete -F _comp $nospace eval
This match function will run when you press <TAB> on the arguments to the eval command. I haven't found a way to include a new matching function for the first command search in bash, I've only found documentation on how to add custom completions for a specific command, like eval above.
But I'm a bit skeptical to how useful this is... There is no easy way to select which match you want from the list.
Probably you can achieve what you want with custom bash_completion settings, but I'm not going to do the job for you, ok? :-)
If you don't know what I'm talking about, see here and here for details. By the way, I would find very annoying this
I would like to lazily just type
"home" and then repeatedly press
{{TAB}} until the specific alias I
want shows up, then press {{ENTER}} to
execute it.
which I think is the M$ style of "completion" (are you coming for DOS/windows environment?)

Resources