Jump to matching "done" while editing bash script in vi - bash

In vi, the % key can be used to jump to a matching opening or closing parenthesis, square bracket or a curly brace.
Could it also be used to jump between matching "do" and "done" in a bash loop?

Not "vi" as such. vim does that.
There is a script matchit.vim which can do this:
The script is documented in the vim wiki page Moving to matching braces.
It part of the vim distribution, but is not installed (in your ~/.vim/plugin directory) by default. See the vim help for matchit-install for details.
Once installed, it has to be enabled, e.g., (see matchit.zip : extended % matching for HTML, LaTeX, and many other languages):
filetype plugin on
in your vimrc file.
For further reading:
Vim: Jumping to if endif in fortran uses simply runtime macros/matchit.vim rather than the two-part install from the vim wiki.
Matchit not working has several answers, some disagreeing.
The runtime macros/matchit.vim line in ~/.vimrc did not make matchit.vim work in my quick test; the procedure in matchit-install, plus the filetype line did work. As usual, your configuration may differ.
I maintain (and of course use) vi-like-emacs, and wrote comparable functionality for that editor using a different approach (see discussion of "fences" in documentation). In a quick test, I see that matchit.vim does not know about the syntax for case-values in a shell case statement. So there is some room for improvement.

Related

Detect prompt with xterm.js

TLDR: I want know how to detect from the output of a shell (e.g. zsh, bash) the location of the prompts (e.g. user#machine /etc % ).
Details
I have made a working shell frontend in the browser based on xtermjs. It is now equivalent feature-wise to e.g. the default macOS terminal application with zsh, bash and powershell. In a nutshell, it works by executing a shell process (e.g. zsh) as the child of a parent process that pipes the input/output from/to the browser via web sockets.
I want now to step up and implement a "collapse" functionality that hides the output of the selected commands in the history (like Visual Studio Code does now).
To this end, I need to detect the location of the prompts from the terminal output: the collapse function would then hide the characters between two consecutive prompts.
I know I can use the approaches below:
detect the prompt with a regular expression (I would need to parse the PS1 variable)
inject some special character sequence before and after the prompt (e.g. in variable PS1)
But both do not seem very robust, and may not work with some specific command interpreter. I could not find yet the location where this functionality is implemented in the source code of Visual Studio Code.
My question is: is there a robust way to achieve this functionality for at least zsh, bash and powershell (it is fine if it is specific to xterm.js)
Edit 1
This SO question is related: ANSI escape sequence for collapsing/folding text (maybe hierarchically)
It links to this interesting thread: https://github.com/PerBothner/DomTerm/issues/54
It appears that DomTerm uses escapes sequences at folding points (my solution 2).
Yet I don't see how to inject them into the terminal, besides hacking the PS1 env var.
Edit 2
While parsing iTerm's documentation I found out that it takes advantage of the hooks provided by the shell (e.g. for zsh) in order to print some special escape sequence at various locations, including before showing the prompt.
For example, in zsh, I can print string "🐮" before each prompt be executing precmd() { echo '🐮' }. Then when I execute e.g. ls I get
$> ls
[...]
🐮
$>
There is a more extensive explanation of the various available hooks for various shells here.
It looks like PowerShell uses a very different system though.

Tab completion ignoring some files in Bash/Debian

I am using tab completion in a standard Debian install with Bash and I have some files being ignored. For example, if I have the files:
index.php
index.php.a
If I type vim i then tab it immediately selects "index.php " (see space after file name). Normally, it would just complete up to "index.php" and give me the option to type something else after.
Why is it behaving differently in this situation?
Update
Some commands such as "cp" seem to handle the tab completion just fine, so maybe it is vim looking for specific file extensions?
The bash-completion package uses the function _filedir_xspec to complete vim. That function in general completes filenames, but excludes certain patterns depending on which command it is completing.
For vim, the exclusion pattern starts like this:
_install_xspec '*.#([ao]|so|so.!(conf|*/*) ...
I.e., among other things, files ending in .a should be ignored. The thinking behind that is probably that these are often created as backup copies and you probably don't want to edit them.
If you want to override this behaviour, you can add your own completions into ~/.bash_completion; for example, to get vim to complete on all filenames, use this:
complete -f vim
which will make vim tab completion default to the built-in file completion bevahiour.

Configure vim word boundary highlight for Bash function names

In vim, when I have a Bash function that ends with a Bash keyword, my vim highlighting starts highlighting it and assumes a new scope (if applicable):
values-for() {
...
}
^yellow "for" highlight
^syntax error highlight
But when I rename the "for" word to "for1" then those undesired highlights disappear.
How do I tell vim to ignore keywords like "for" when it is used as part of a function name?
I cannot reproduce this with the $VIMRUNTIME/syntax/sh.vim script (that ships with Vim 8.0.1358), version 172 from Oct 02, 2017 (assuming a proper #!/bin/bash shebang, so that the syntax detects the Bash dialect).
On the maintainer's web site, there's an even newer update (version 174).
If you can still reproduce the problem with that version, please contact DrChip via email and report this bug.
Just to be clear, this is something that you cannot fix "in Vim"; it's a bug in the syntax definition itself, so that must be changed.
Word boundaries are \< and \>. So use \<for\>.

bash tab completion filter out options

I would like to make tab completion in bash a bit more intelligent.
Let's say I have a folder with a src file .lisp, and a compiled version of that file .fasl. I would like to type vi filename [tab tab], and the .lisp autocompletes as the only option. That is, it's not likely that I want vim to open a compiled binary, so don't have it in the list of autocomplete options to cycle through.
Is there a way that I can keep a flat list of extensions that autocomplete ignores, or somehow customize it for vim, so that autocomplete ignores only particular file extensions when a bash command starts with vi ...
Any ideas are appreciated.
Thanks!
From man bash:
FIGNORE
A colon-separated list of suffixes to ignore when performing
filename completion. A filename whose suffix matches one of the entries in FIGNORE is excluded from the
list of matched filenames. A sample value is ".o:~" (Quoting is
needed when assigning a value to this variable, which contains
tildes).
So, for your example this can be set in your .bashrc file with
FIGNORE=".o:~:.fasl"
or, if you want to keep any other site-wide settings:
FIGNORE=".o:~:.fasl:$FIGNORE"
The bash complete command seems to be what you want.
Here is a Linux Journal link to 'complete' command video. and here is the follow-up page More on Using the Bash Complete Command
The links explain it quite well, and here is a related SO Question/Answer: Bash autocompletion across a symbolic link

Syntax highlighting in Bash vi-input mode

If I enable bash's input mode using set -o vi, then press Esc followed by v, I get a vi window which allows me to edit a temporary file which is executed once I leave. In that window I would like to enjoy Vim syntax highlighting for Bash scripts. It doesn't suffice to execute :syntax enable. The problem might be related to the fact that the temporary file has no .sh ending nor a #!/bin/bash head which could be used to determine the filetype.
I'd use the shorter formulation:
au BufRead,BufNewFile bash-fc-* set filetype=sh
I believe this type of autocmd is the canonical way to handle filetype assignments (at least, my .vimrc has a number of them).
#Eric Fortis, please chime in or correct me if there's a reason you did it differently.
Add this to your .vimrc
if expand('%:t') =~?'bash-fc-\d\+'
setfiletype sh
endif
the temporary files are of the form bash-fc-3537253897, so the regex matches if the file begins with bash-fc- and applies the filetype.

Resources