How to make fish shell delete words like bash does - bash

I'm giving a second try to the fish shell. One thing that really annoys me is the "new" behaviour of Ctrl+w shortcut.
Consider following situation:
$ vim ~/.config/fish/config.fish
...having the cursor at the end of the line.
When you press Ctrl+w, following happens:
in bash: ~/.config/fish/config.fish is deleted
in fish: only config.fish is deleted
How can I make fish delete words that are separated by spaces only?

"\cw" (in fish's notation) is bound to "backward-kill-path-component" (which bind \cw will tell you).
If you wish, you can bind it to something else, including input functions like "backward-kill-word" or any fish script - bind \cw backward-kill-word or bind \cw "commandline -rt ''" (which will remove the entire current token) or bind \cw backward-kill-bigword. See the bind documentation or bind --help for more information.
The difference between "word" and "bigword" here is that "word" will only go to the next non-word-character, which can be a "." or "/" or "-", among others, while "bigword" will truly go to the next whitespace character.
Note that the "bigword" functions have only been introduced in fish 2.3.0.
You can try these incantations in an interactive shell. If you decide to make it permanent, you'll need to add them to a function called fish_user_key_bindings.

Related

Bash prompt changes when using arrow keys sometimes

When I use my terminal (iTerm 2 Mac) with my PS1 set to "\[\e[38;5;117m\W \e[39;38;5;104m\$\e[39;0m\] " and I use the arrow keys to go through my bash history it sometimes changes my prompt from ~ $ to just the first character of it and whatever command I'm looking at. For example, going to rvim .bashrc from randomDir $ ls. This problem also persists in the default terminal app.
\W and \$ should not go inside the \[...\], since bash will know how much space each takes up on the terminal.
PS1="\[\e[38;5;117m\]\W \[\e[39;38;5;104m\]\$\[\e[39;0m\] "
Only the characters that make up the ANSI escape sequence (which only instruct the terminal to change colors, without displaying a single additional character) are enclosed in \[...\].
Putting them inside \[...\] tells bash to ignore their contribution to the length of the prompt, leading to incorrect redraws.

macos: Bash shows commands instead files

Bash on my macOS shows all (probably) commands from $PATH when I double-TAB instead of files and folders. Same when I can use TAB once - it does not work at all. Commands like CD works fine.
I have no idea where the problem is - $PATH seems normal to me:
/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
~/.profile is this:
export PATH=/usr/local/php5/bin:$PATH
export PATH="$HOME/.yarn/bin:$PATH"
~/.bash_profile has only this:
export PATH="/usr/local/sbin:$PATH"
Same behavior under PhpStorm's terminal. So I believe, the problem is somewhere deeper.
Can you help, please?
Command-line completion in Bash is achieved through readline, a well-known utility library used by many GNU and other Open Source products.
Basic completion is using the {TAB} key, and the actual completion depends on context. If the text does not start with a special character then commands are listed if they match, only if commands don't match are filenames listed.
If completion can be achieved, enough characters are supplied to make the completion unique, then it will be done, otherwise a second {TAB} will give a list of possibilities.
From man bash (Completing):
Bash attempts completion treating the text as a variable (if the text
begins with $), username (if the text begins with ~), hostname
(if the text begins with #), or command (including aliases and
functions) in turn. If none of these produces a match, filename
completion is attempted.

Insert current path in bash command line

To run a program in bash, I normally use relative paths because it's faster to type; for example, something like
me#host:~/dir/appX$ ./manage.py runserver
The command will then be stored in the history. To recall the command from history (CTRL+R normally), I need to be on the same path as when I ran it, making the recall function less useful.
One solution is to insert the full path the first time, but it takes a lot of writing.
me#host:~/dir/appX$ /home/me/dir/appX/manage.py runserver
Is there a way (preferably built in) to insert the current path in the command line?
Or maybe a better solution (should work on bash)?
You can do this in bash using Tilde Expansion. You need two tilde expansion related features, just showing the relevant parts from man bash below:
Tilde Expansion
If the tilde-prefix is a `~+', the value of the shell variable PWD
replaces the tilde-prefix.
tilde-expand (M-&)
Perform tilde expansion on the current word.
As it says, you can type ~+ to get the current path. And then to expand it you need to type M-&. So the key sequence ~+M-& is all you need.
I found it a little difficult pressing all these keys, so I created a key binding for this. Add a line like below in your ~/.inputrc file:
"\C-a":"~+\e&"
With this I can now type ctrl+a on my keyboard to get the current path on the command line.
PS: It's possible that ctrl+a is already bound to something else (perhaps beginning of line) in which case it might be better to use another key combination. Use bind -p to check current bindings.

What in PS1 is causing my Terminal.app commands to get stuck on the screen?

When cycling through statements entered to the console, I occasionally find that the text I entered isn't refreshed and the prompt is moved to the right.
My original, intended prompt: http://cl.ly/image/04080N260L1V.
What happens after hitting the Up and Down arrows about a dozen times: http://cl.ly/image/1n3S2K31340R.
In case the screenshots aren't clear, the underlined text (in this case, "vim ~/.bas") is getting "added" to the prompt. I can't delete it out. However, if I delete as much as I can, clearing any text after the prompt, and hit Enter, I'm greeted with my clean, original prompt again: http://cl.ly/image/2O1h1Z2y0n2I.
Here's what ~/.bash_profile contains:
# Simpler bash prompt in Terminal.app
promptColor="\e[1;34m"
endColor="\e[m"
#export PS1='\e[0;36m\w$ \e[0m'
export PS1="$promptColor\w$ $endColor"
# Syntax highlighting for commands like `ls` and such
alias ls="ls -G"
# PATH ammendment to put Homebrew-installed apps in front of system-provided ones
homebrew=/usr/local/bin:/usr/local/sbin:/usr/local/share/npm/bin
export PATH=$homebrew:$PATH
I've narrowed the culprit down to the PS1 variable. (You can see I've tried this a few different ways.) Based on what I've read, I'm using the color codes correctly.
Any help would be fantastic. Thanks.
This is a FAQ. In order for Bash to be able to compute the display length of the prompt correctly, any non-printing sequences such as color codes need to be inside a \[...\] sequence.
I think you want:
promptColor='\e[1;34m'
endColor='\e[m'
export PS1="$promptColor"'\w$ '"$endColor"
(Notice all the subtle changes from double to single-quotes)
The problem is that bash is doing expansion on the following when they need to be interpreted explicitly:
\e[1;34m
\w$
\e[m
Single-quotes and double-quotes mean different things in shell: Strong Quoting vs. Weak Quoting.
I would also just copy and paste the lines with escaped characters and modify them (note that they aren't the same as literal representations)

vi highlights bash scripting uppercase or lowercase as error

My vi has been wonderful in highlighting errors in my bash scripts. However, one thing that I notice is when I use the bash extension for all upppercase or all lowercase, vi highlights the characters as an error. Is there a solution for this?
#!/bin/bash
mystr="Abc"
echo ${mystr,,} # Works, but vi highlights ,, as in error
% ./test.sh
abc
%
VIM syntax highlighting is done via a Syntax file. Go into VIM and type in :echo $VIMRUNTIME. This will tell you the VIMRUNTIME directory. In that directory, there's a directory called syntax. Inside that are the syntax definitions. There's a file called sh.vim that contains the definitions for BASH, Kornshell, and Bourne shell.
Take a look around line #400 of the file, you'll see something like this:
" Special ${parameter OPERATOR word} handling: {{{1
" sh ksh bash : ${parameter:-word} word is default value
" sh ksh bash : ${parameter:=word} assign word as default value
" sh ksh bash : ${parameter:?word} display word if parameter is null
" sh ksh bash : ${parameter:+word} use word if parameter is not null, otherwise nothing
" ksh bash : ${parameter#pattern} remove small left pattern
" ksh bash : ${parameter##pattern} remove large left pattern
" ksh bash : ${parameter%pattern} remove small right pattern
" ksh bash : ${parameter%%pattern} remove large right pattern
It is in THIS section that defines the patterns and whether they're legal or not. You'll need to define a region that looks like this:
if exists("b:is_bash")
Here be dragons
endif
Actually, I see one farther down on line #423 in the latest version of the sh.vim file, so you don't have to define your own.
Now, all you have to do is replace the Here be dragons section with something that defines the syntax you want to show as not an error. I don't know enough of the VIM syntax to tell you. However, it doesn't look all that complicated. Backup the old sh.vim and have some fun. Believe it or not, it's all documented right in VIM. I've modified the syntax files for Perl and Python without too many issues.
you can also go to https://vim.svn.sourceforge.net/svnroot/vim/vim7/runtime/syntax/ and see if there's a new sh.vim file that might include the syntax fix you need.
You can also report the problem to the VIM project and let them know about the issue. They're pretty good about fixing things like this, and then you can go download the latest fix at the Subversion URL above.

Resources