Can I press enter twice to execute a command? - shell

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.

Related

Refreshing Bash prompt after invocation of a readline bound command

My shell is GNU Bash 4.3.11, and I currently have M-h bound to cd .. by calling the builtin
bind -x '"\eh": "cd .."'
This gives me a nifty way to navigate up the directory tree, as I can repeatedly hit M-h instead of the incredibly time-consuming cd ... It has the downside, however, either of not resetting my $PS1 or of not redrawing my prompt, so I lose the context of my current working directory until I enter a new command.
One alternative I'm aware of is to put a macro like
"\eh": "\C-a\C-kcd ..\C-m"
in my .inputrc directly. This, however, has the downside of not only losing the context of any existing command I'm typing in (which I think can probably be worked around) but also of printing out cd .. (which I don't think can be).
My desired behavior is to be able to be in a directory ~/one/two with prompt ~/one/two$; hit M-h; and then be in ~/one and have the prompt be ~/one$, ideally keeping any command I had initially. How can I achieve this?
Figured this out.
# maintain state
bind -x '"\200": TEMP_LINE=$READLINE_LINE; TEMP_POINT=$READLINE_POINT'
bind -x '"\201": READLINE_LINE=$TEMP_LINE; READLINE_POINT=$TEMP_POINT; unset TEMP_POINT; unset TEMP_LINE'
# "cd .." use case.
bind -x '"\206": "cd .."'
bind '"\eh":"\200\C-a\C-k\206\C-m\201"'
I'm quite late to that party - and came here looking for that answer also. First of all: As you were the only one providing information on this: thanks for not letting it come to this: https://xkcd.com/979/ ;) instead you pointed me to the on corner in that fractal that seems to hold a solution.
This approach, in my opinion backed up by hours of trying, is the only one where you can a) replace content on the line, and b) execute bash code. Let me offer up some more suggestions to a specific problem:
If you are trying to have it both ways: insert something on the command line, or executing code, things can get very tricky. for both, there exist bindings, and I let the reader figure out things with help bind. But in the case you e.g. have FZF produce some directory as output, and you'd either cd to it, or have it pasted into your command -- depending on the keystroke done in FZF -- things will get near impossible. you'll face either the not-updated-promt problem, or not be able to execute the cd command in the top shell (where it has effect).
Your solution would be a multiplexing -x binding, inspecting the output for "macros" (get extracted and eval'd) or the default pass-through (manipulating READLINE_LINE/POINT).
Because the solution has some enormity, and the audience may be limited (closed answer...), I'll leave it at a haphazard gist where I pasted my code which works now. To make up for the brevity and uncommented-ness, I welcome any questions in comment or elsewhere. Hope someone may be pointed in the right direction.
- The code related to this question starts in function bindInsertEvalWithMacrosVi
- It is designed for Vi keybindings but the same principles apply for normal readline mode
- It depends on some \C-x\C-... combinations to do redrawing in places that are not related to this post.
https://gist.github.com/simlei/032470cfcd23641987f97a96749128d7

ksh - Display Current Mode

Is there any way to have ksh display the current typing mode at the bottom of the window like vim; like "Insert", "Command", "Visual", etc? Unfortunately, I am having a lot of trouble remembering which mode I'm in and find the shell unintuitive (at least until I get used to all the commands). I consistantly hit the wrong key in command mode and have difficulty figuring out how to get back to proper typing (sometimes it lets me type but not delete part of the line and I don't know why).
I am required to use ksh for work and am heavily restricted in what I can download and install, but I need to figure this out. Hopefully there is something I can do with a profile or script along these lines to help ease the transistion. Also, this is HP-Unix, in case that affects anything.
This set -o alone command will show if emacs is defined to on
$ set -o|grep emacs
emacs on

How to implement command autocomplete in myshell?

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.

How to search backwards in emacs shell?

I love emacs shells, but there is a confusing thing for people used to use the gnome shell (like me). The backwards search does not work the same way. C-r searches in the buffer, not in the command history, and M-r searches in the command history but when pressed twice toggles between direct and regexp search, i.e. does not search for the previous match in the command history. So, how to do that?
Edit: The shell I was looking when I wrote this is what you get with M-x shell, I didn't know there were other shells in emacs. See e.g. https://plus.google.com/112537550357635435516/posts/Wgpk2mH6hQh
Type M-r , search for something, and then press C-r to repeat the same search in the command history.
Press M-r, then write something, then press C-r as many times as needed.

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.

Resources