Refreshing Bash prompt after invocation of a readline bound command - bash

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

Related

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

modifying the bash prompt on mac

On my bash prompt, I would like to see just the name of the current directory followed by "$" in different colours.
So I used this code but when I have a long typed command, I see the cursor in different place than where the typing is taking place. How can this "hard to describe" problem be fixed? Thanks
PS1='\[\e[0;36m\]\W\[\e[m\]\[\e[1;31m\]\$\[\e[m\]'
Use a carriage-return after outputting the current directory, I've done this for years and it works a treat, something like:
if [ "$PS1" ]; then
PS1="\[\e[0;36m\]\W\n\[\e[m\]\[\e[1;31m\]\$\[\e[m\]"
fi
You always have your current directory (no matter how long) on top of your $ prompt.
I put other info up there as well like username, machine name and exact time and date. I colour them differently so they really stand out. Helps if you have multiple sessions going on, on different machines with or without root(!) privileges (have to be root when deploying a complete rebuild). And has saved the day many times when I need to know when I did something or other (ok, it's when that task ended - but still helps).
But most of all, it's great to know your current directory by simply looking at your command line prompt :) )
Don't know how other people work efficiently without it!

How to test that `clear` command is working correctly in BASH?

Now i try find the way to prove that a clear command is working correctly on my own REPL
Example
$ cd ~
$ pwd
/home/user
$ echo "hello"
hello
then type clear
$
but sometime some unexpected behavior is occurred after using a clear command
e.g.
[one blank line here]
$
A one blank line after using clear command is undesirable behavior and I hope this kind of bug can be detected automatically via a unit test. If you have any idea to prove that clear command is working correctly please purpose.
There is no easy way to do this. "clear" sends a sequence of bytes that tells the terminal to clear its screen. Different terminals use different sequences. There is a table called "termcap" (terminal capabilities) that lists the difference sequences for different types of terminals. The environment variable "TERM" should be set to the type of terminal you are using.
TERM is usually set to "xterm", "xterm-color", "vt100", or related value. On my Mac OS X Terminal it is set to "xterm-256color".
TERM should be set automatically for you. If your OS is set up properly you shouldn't have to set it yourself. However in the old days you had to set it manually. Therefore you'll find a lot of old .profile/.bashrc/.cshrc files that set it. Check to see if that is happening and remove that (comment it out) to see what is automatically set.
Your question boils down to "how can I tell if my TERM variable is set right?" and the answer is: You can't. You could do things like clear the screen then ask the user if they saw their screen clear. However, if programs did that on start-up, it would be very annoying.

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

Worth switching to zsh for casual use? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 11 years ago.
Improve this question
The default shell in Mac OS X is bash, which I'm generally happy to be using. I just take it for granted. It would be really nice if it auto-completed more stuff, though, and I've heard good things about zsh in this regard. But I don't really have the inclination to spend hours fiddling with settings to improve my command line usage by a tiny amount, since my life on the command line isn't that bad.
(As I understand it, bash can also be configured to auto-complete more cleverly. It's the configuring I'm not all that keen on.)
Will switching to zsh, even in a small number cases, make my life easier? Or is it only a better shell if you put in the time to learn why it's better? (Examples would be nice, too :) )
#Rodney Amato
&
#Vulcan Eager
give two good reasons to respectively stick to bash and switch to zsh. Looks like I'll have to investigate both! Oh well :)
Is there anyone with an opinion from both sides of the argument?
Personally, I love zsh.
Generally, you probably won't notice the difference between it and bash, until you want to quickly do things like recursive globbing:
**/*.c for example.
Or use suffix aliases to associate specific progs with different suffixes, so that you can "execute" them directly. The below alias lets you "run" a C source file at the prompt by simply typing ./my_program.c – which will work exactly as if you typed vim ./my_program.c. (Sort of the equivalent to double clicking on the icon of a file.)
alias -s c=vim
Or print the names of files modified today:
print *(e:age today now:)
You can probably do all of these things in bash, but my experience with zsh is that if there's something I want to do, I can probably find it in zsh-lovers.
I also find the book 'From Bash to Z-Shell' really useful.
Playing with the mind bogglingly large number of options is good fun too!
For casual use you are probably better off sticking with bash and just installing bash completion.
Installing it is pretty easy, grab the bash-completion-20060301.tar.gz from http://www.caliban.org/bash/index.shtml#completion and extract it with
tar -xzvf bash-completion-20060301.tar.gz
then copy the bash_completion/bash_completion file to /etc with
sudo cp bash_completion/bash_completion /etc
which will prompt you for your password. You probably will want to make a /etc/bash_completion.d directory for any additional completion scripts (for instance I have the git completion script in there).
Once this is done the last step is to make sure the .bash_profile file in your home directory has
if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
in it to load the completion file when you login.
To test it just open a new terminal, and try completing on cvs and it should show you the cvs options in the list of completions.
Switch to zsh. You will have access to:
zmv: You can do: zmv '(*).mp3' '$1.wma' for thousands of files.
zcalc: Extremely comfortable calculator, better than bc.
zparseopts: One-liner for parsing arbitrary complex options given to your script.
autopushd: You can always do popd after cd to change back to your previous directory.
Floating point support. It is needed from time to time.
Hashes support. Sometimes they are just a key feature.
If all you want to use ZSH for is better completion, the configuration is pretty easy. Place this in your ~/.zshrc:
autoload -U zutil # [1]
autoload -U compinit # [2]
autoload -U complist # [3]
compinit
However, it's worth checking out all the other great features of the ZSH. The above example will give you a pretty plain prompt with good completion. If you don't want to fiddle with configurations, but want to see what ZSH can do for you, Google for "zshrc" and you will get some ready to use configurations to get started.
[1]: http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#The-zsh_002fzutil-Module
[2]: http://zsh.sourceforge.net/Doc/Release/Completion-System.html#Initialization
[3]: http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#The-zsh_002fcomplist-Module
zsh has a console gui configuration thing. You can set it up pretty quickly and easily without having to fiddle with configuration files. I don't think you will need much time to set it up, probably 10 seconds with just using defaults, so go ahead and try it out.
Staale is talking about a wizard like program (CUI) which autoruns the first time you run zsh. Just answer some questions, view/change the defaults and its configured for you.
IBM developerWorks has great resources on zsh.
I have not used very advanced features and so far I have not come across serious differences which should hamper someone coming from bash.
Some examples:
!?pattern<Tab> will autocomplete to
the last command in history matching
pattern. Very useful.
You can configure a prompt on the
RHS. One use is to keep a fixed
width prompt on the left hand side
so all commands line up nicely while
displaying the pwd (or anything of
variable width) as the right hand
side prompt.
You can redirect input from multiple files (yet to try this): cat < file1 < file2 < file3

Resources