Dynamic abbrev expand for the shell - linux

Is there a function on one of the linux shells like the emacs dabbrev-expand?

First to give a definition:
M-xdescribe-functionEnterdabbrev-expandEnter
...
Expands to the most recent, preceding word for which this is a prefix.
Given that bash seems to be most heavily influenced by Emacs, looking there first reveals a few possibilities:
man bash(1), readline section
dynamic-complete-history (M-TAB)
Attempt completion on the text before point, comparing the text
against lines from the history list for possible completion matches.
dabbrev-expand
Attempt menu completion on the text before point, comparing the text
against lines from the history list for possible completion matches.
By default (or my system at least), M-/ is already bound to complete-filename:
$ bind -l | grep /
"\e/": complete-filename
You could re-bind it by putting
"\e/": dabbrev-expand
in your ~/.inputrc or /etc/inputrc.
Note that it only seems to complete the first word (the command), and only from history, not from the current command line as far as I can tell.
In zsh, I can't see anything in the man page that does this, but it should be possible to make it happen by figuring out the appropriate compctl command (Google mirror).

Related

tmux pin to avoid scrolling

Often when I run a command that writes to stdout, and that command fails, I have to scroll up (using uncomfortable key-bindings) looking for the place where I pressed Enter, to see what the first error was (out of hundreds others, across many screens of text). This is both annoying and time-consuming. I wish there was a feature which allowed me to pin my current terminal to the place where I am now, then start the command, see only the first lines of the output (as many as fits below my cursor) and let the rest of the output be written but not displayed. In other words I would like a feature to allow me automatically scroll up to the place where I gave the command, to see the first lines of the output (where usually the origin of the failure is displayed).
I searched for it but I didn't find it. Do you know if such feature exists? Or have an idea how to implement it with some tricks or workarounds?
If you have a unique shell prompt you could bind a key to jump between shell prompts, for example something like this will make C-b S jump to the previous shell prompt then S subsequent ones:
bind S copy-mode \; send -X search-backward 'nicholas#myhost:'
bind -Tcopy-mode S send -X search-backward 'nicholas#myhost:'
Or similarly you could search for error strings if they have a recognisable prefix. If you install the tmux 3.1 release candidate, you can search for regular expressions.
Alternatively, you could use capture-pane to load the entire history into an editor with key bindings you prefer, for example:
$ tmux capturep -S- -E- -p|vim -
Or pipe to grep or whatever. Note you will need to use a temporary file for this to work with emacs.
Or try to get into the habit of teeing commands with lots of output to a file to start with.

vim: Run multiple commands based off of one :global command

Apologies if this has been posted already, for I cannot find an answer, even on the vim wiki.
Is there a way I can run multiple commands in vim command-line mode off of a single :g search?
For example,
:%g/foo/ s/bar/\=#a/g | exe "norm /cat\<enter>\"ayiw"
Which (for what I intend it to do) should, on every line matching foo, replace bar with the contents of register a, and then find the next iteration of cat (even if it is many lines ahead), and put the surrounding word into register a.
Instead, this specific syntax completes the subsitution command using the current contents of the initial a register, and then executes the normal mode command on a single line (after the substitution has been completed).
This example is not my specific use-case but shows one instance where this functionality is useful. I realize I could put it all into a single exe, i.e., %g/foo/exe "norm :s/bar/\\=#a/g\<enter>/cat\<enter>\"ayiw", but I would like to do it the first way, as I feel it is more flexible.
I would prefer to do this using vanilla vim, but if a plugin exists for this, that is an okay alternative. Does anybody know if there is syntax to do such a thing?
Okay a "little bit" dirty, but does this work for you?
:let list = split(execute('g/cat/p'), '\n') | g/foo/ s/bar/\=matchstr(remove(list, 0), '\s\d\+\s\zs.*')/g
It first reads all occurences of cat save them in a list.
Then replace the first bar with the first cat... and so on.
The dirty part ist the matchstr command. the g//p also returns a number for the result so the list looks like this:
1 cat
2 cat
3 cat
...
that's why we have to remove a bit from the front. I would love to hear if someone knows a clean solution for that (I am also interested in a clean vimscript solution, does not have to be a oneliner).
You can do this (at least for multiple :s commands applied to a single :g). Example:
" SHORT STORY TITLES to single word of CapitalizedWords within <h3>s
.,$g/^\L\+$/s/[^A-Z0-9 ]\+//ge|s/\u\+/\L&/ge|s/\<\l\+\>/\u&/ge|s/ \+//ge|s/.*/<h3>&<\/h3>/

Tcsh completion in the format of ls -l

When setting autolist in tcsh.rc, and pressing Tab to complete a filename i get a list of available completions in the format of a "regular" ls command.
is there any way to set tcsh in a way that pressing tab will show a list of available completions in the format of "ls -l"?
or if not, then just sort the "regular" list by date?
pressing tab will show a list of available completions in the format of "ls -l"?
No, this is not possible.
Completion in tcsh works by getting a list of words (ie. my trousers are on fire), checking if one of the word matches, and then insert that word in the commandline.
There is no functionality which says "display this to the user, but insert something else in the commandline". So while you could complete commands with ls -l, this would be fairly useless, since you'll get the entire line in your commandline.
just sort the "regular" list by date?
This is also not possible, since tcsh sorts the completions. You can't disable this ...
Sorry :-( I believe that at least zsh is able to do this, but I'm not sure. Maybe bash can do this as well (but again, not sure).
(This information derived from a careful reading of the manpage, and tw.parse.c in the source code.)

Using bash history to get a previous command, copy it and then 'run' it but with the command commented

Just a question to improve my bash skills. I always do this:
$ history | grep some_long_command
...
...
123 some_long_command1.........
124 some_long_command2.........
...
I can then run the command the command I found by doing:
!123
However, I often want to do this:
some_long_command1foobar
I.e. change the command before I run it. Can you use bash to run this command instead:
#some_long_command1
so it gets commented.
Then I don't have to use my mouse to highlight the command, edit it and then run it (I can just use the keyboard - faster).
I suppose I could write a script to do it but there might already be functionality built in somewhere....?
I'd suggest instead of using the history command, you use ctrl+r and start typing that command. When you press an arrow key as if to go to modify it, it will drop out of autocomplete recognition, and will let you edit before running.
UPDATE: also, if you want to cycle through the different commands that contain the string you just typed, keep on pressing ctrl+r
Actually, you can just append :p to the command to print it without actually running it. For example:
$ ls -la
$ !!:p
Will print out ls -la as the previous command without running it, and you can just press ā†‘ (up) to find it and edit it.
You can also do
!123:p
to print out the 123rd command as your previous command.
You can also try fc command to edit the command in the history.
WIKI says,
ā€‹fcā€‹ is a standard program on Unix that lists or edits and reexecutes,
commands previously entered to an interactive shell. fc is a built-in
command in the bash shell; help fc will show usage information.
Apart from reverse-incremental search(Ctrl+R), we have some more bash shortcuts:
From man bash:
previous-history (C-p)
Fetch the previous command from the history list, moving back in the list.
next-history (C-n)
Fetch the next command from the history list, moving forward in the list.
beginning-of-history (M-&lt)
Move to the first line in the history.
end-of-history (M->)
Move to the end of the input history, i.e., the line currently being entered.
reverse-search-history (C-r)
Search backward starting at the current line and moving 'up' through the history as necessary. This is an incremental search.
forward-search-history (C-s)
Search forward starting at the current line and moving 'down' through the history as necessary. This is an incremental search.
non-incremental-reverse-search-history (M-p)
Search backward through the history starting at the current line using a non-incremental search for a string supplied by the user.
non-incremental-forward-search-history (M-n)
Search forward through the history using a non-incremental search for a string supplied by the user.
yank-nth-arg (M-C-y)
Insert the first argument to the previous command (usually the second word on the previous line) at point. With an argument n, insert the nth word from the previous command (the words in the previous command begin with word 0). A negative argument inserts the nth word from the end of the previous command. Once the argument n is computed, the argument is extracted as if the "!n" history expansion had been specified.
yank-last-arg (M-., M-_)
Insert the last argument to the previous command (the last word of the previous history entry). With an argument, behave exactly like yank-nth-arg. Successive calls to yank-last-arg move back through the history list, inserting the last argument of each line in turn. The history expansion facilities are used to extract the last argument, as if the "!$" history expansion had been specified.
shell-expand-line (M-C-e)
Expand the line as the shell does. This performs alias and history expansion as well as all of the shell word expansions. See HISTORY EXPANSION below for a description of history expansion.
history-expand-line (M-^)
Perform history expansion on the current line. See HISTORY EXPANSION below for a description of history expansion.
insert-last-argument (M-., M-_)
A synonym for yank-last-arg.
operate-and-get-next (C-o)
Accept the current line for execution and fetch the next line relative to the current line from the history for editing. Any argument is ignored.
edit-and-execute-command (C-xC-e)
Invoke an editor on the current command line, and execute the result as shell commands.
!123:gs/old/new/
Will run command 123 replacing the string 'old' with the string 'new'.
You can get to edit mode by hitting M-^ (option-shift-6 on a mac).
Type this:
!123M-^
And you'll be editing command #123. It's sort of like using ctrl-r, but starting with exclamation-point syntax.
Instead of using the history command, bind history-search-backward/history-search-forward to key shortcuts which can be remembered easily (I prefer PgUp/PgDown). To do that, put this into your .inputrc file:
"<key code>": history-search-backward
"<key code>": history-search-forward
To get <key code>, type Ctrl-V <key> in the shell, and replace the starting ^[ with \e in whatever was output.
After this is set up, you can just type some and press PgUp to get some_long_command. If you need some_long_command with_some_arg but there is a similar command some_long_command with_some_other_arg later in the history, you can cycle through until you reach it by typing some and then hitting PgUp repeatedly, or you can type some, hit PgUp, move the cursor to where the two commands start to differ, type a few characters and hit PgUp once more. This ability to quickly page through / differentiate between similar commands makes it in my opinion a much more comfortable tool than Ctrl-R.
You can also put
shopt -s histverify
in your .bash_profile, which causes any history expansion to appear on your command line without running it, allowing you to edit before doing so.
You may wan to try "suggest box"-like history https://github.com/dvorka/hstr - it reads Bash history and allows for quick navigation.
To get the last command simply type hh, navigate to the command and use right arrow to get it on command line (where you can edit it and/or add comment).
^p to get the last typed command in unix/solaris
Put
alias r='fc -s'
in your .bashrc (home dir)
then you can just type in
r <whatever>
at the command prompt and you will execute a copy of the last <whatever> command (same params) that is in your history. just hit up arrow to see what you have executed if you feel the need.

How to do brace expansion tab-completion, for filenames in vim?

In vim (and bash), you can specify alternatives in filenames, eg:
:arga project/html/{index,sitemap}.html
This expands to "project/html/index.html" and "project/html/sitemap.html" (the :arga appends them both to the argument list; you can get to them with :n).
Now, vim already does some filename completion on this, with TAB, by cycling through the possibilities. For the above example, it would show the index one, then the sitemap one, then back to the original text.
I to be able to type this much:
:arga project/html/{in
and press TAB, and have it complete (even though I'm in the middle of a brace):
:arga project/html/{index.html
and have tab-completion also work for the next one, from project/html/{index.html,sit to project/html/{index.html,sitemap.html.
Is there already an option in vim to do this? If not, how would you implement it?
If this is possible, you'll have to define your own :Arga command and to specify your own expansion function. However as vim has a few things hard-coded in regard of command-line completion, I can't guaranty you that this is possible.
You can have a look at my :SearchIn* commands for examples.

Resources