Why does adding files to my args also open the buffers? - vim

Whenever I add files to my args, the same files are also added to my list of buffers. This happens with set hidden and set nohidden. This is not the expected behaviour, right? And how do I stop it?
:ls
1 a "[No Name]" line 1
:args *
:ls
1 a "[No Name]" line 1
3 %a "globals.js" line 1
4 "package.json" line 0
5 "README.md" line 0
6 "spec" line 0
7 "tags" line 0
Spec is a directory not a file, which prompted me to experiment with disabling NERDTree but that made no difference.

It is the standard/normal behavior.
You can switch to the next file using :next.

Related

What's happening here with vim inside TMUX pane?

When I open vim inside of a TMUX pane, The pane is filled with codes I don't recognise. If I just run vim, I get this:
^[[38;2;165;42;42m 1
^[[38;2;0;0;255m~
If I open a file with vim, I get something like this (top pane):
Pretty new to both vim and TMUX. How can I solve this?
It seems that Vim is sending control sequences to your terminal which the latter doesn't understand.
More specifically, the sequences you mentioned in the OP:
^[[38;2;165;42;42m
^[[38;2;0;0;255m
look like they're encoding foreground true colors for the text.
You can find their syntax here:
CSI Pm m
Where CSI stands for “Control Sequence Introducer” and is produced by the keys ESC [, and Pm stands for:
A multiple numeric parameter composed of any number of single numeric parameters, separated by ; character(s).
If you scroll down the page, you should find a description of a more detailed syntax:
CSI Pm m Character Attributes (SGR).
...
This variation on ISO-8613-6 is supported for compatibility with KDE konsole:
Pm = 3 8 ; 2 ; Pr; Pg; Pb
Set foreground color to the closest match in xterm's palette for
the given RGB Pr/Pg/Pb.
Pm = 4 8 ; 2 ; Pr; Pg; Pb
Set background color to the closest match in xterm's palette for
the given RGB Pr/Pg/Pb.*
Applied to your first sequence, you can break it down like so:
┌ CSI
│ ┌ Pm
├─┐├────────────┐
^[[38;2;165;42;42m
├─┘ ├┘ ├┘
│ │ └ Pb = amount of blue
│ └ Pg = amount of green
└ Pr = amount of red
If the terminal doesn't understand this sequence, I can see 3 explanations:
the terminal doesn't support true colors
tmux is not properly configured to support true colors
Vim is not properly configured to support true colors
To test whether 1. is the issue, you can write this bash function in your ~/.bashrc:
truecolor() {
local i r g b
for ((i = 0; i <= 79; i++)); do
b=$((i*255/79))
g=$((2*b))
r=$((255-b))
if [[ $g -gt 255 ]]; then
g=$((2*255 - g))
fi
printf -- '\e[48;2;%d;%d;%dm \e[0m' "$r" "$g" "$b"
done
printf -- '\n'
}
Then execute $ truecolor in your shell, outside tmux. If you get some kind of rainbow, your terminal supports true colors (at least partially).
If you see some cells which are not colored, and others randomly colored, your terminal doesn't support true colors.
Alternatively, you can try the sequences manually:
$ printf '\e[38;2;%d;%d;%dm this text should be colored \e[0m' 165 42 42
$ printf '\e[38;2;%d;%d;%dm this text should be colored \e[0m' 0 0 255
If $ truecolor doesn't produce a rainbow, or if the $ printf commands don't change the foreground color (not the background color) of the text, you'll have to either:
disable 'termguicolors' in your ~/.vimrc; i.e. remove set termguicolors (or make it execute set notermguicolors)
try and upgrade your terminal
find another terminal which supports true colors
To test whether 2. is the issue, inside tmux, you can execute this shell command:
$ tmux info | grep Tc
If the output contains [missing]:
203: Tc: [missing]
^^^^^^^^^
it means that tmux is not configured to support true colors.
In this case, you have to include something like this in ~/.tmux.conf:
set -as terminal-overrides ',*-256color:Tc'
││ ├────────────────┘ ├────────┘ ├┘
││ │ │ └ tell tmux that the terminal suppors true colors
││ │ └ configure the option only if `$TERM` ends with the string `-256color`
││ └ the option to configure is `terminal-overrides` (see `$ man tmux`)
│└ the next option is a server option
└ append the value to the tmux option instead of overwriting it
Then restart tmux, and execute $ tmux info | grep Tc. This time the output should contain true:
203: Tc: (flag) true
^^^^
If it doesn't, have a look at the output of $TERM outside tmux:
$ echo $TERM
The output should be matched by whatever pattern you write before :Tc.
In the previous example, I used the pattern *-256color which will match any terminal whose $TERM ends with the string -256color. If it doesn't match your $TERM, you can try another pattern, or simply write * to describe any type of terminal:
set -as terminal-overrides ',*:Tc'
To test whether 3. is the issue, you can write these commands in your ~/.vimrc:
set termguicolors
let &t_8f = "\<Esc>[38:2:%lu:%lu:%lum"
let &t_8b = "\<Esc>[48:2:%lu:%lu:%lum"
Or:
set termguicolors
let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
The only difference between the 2 versions is the delimiter between the parameters of the sequences. A colon in the first version, a semicolon in the second one. See :h xterm-true-color for more info.
You can check the current values of these 3 options by executing successively:
:echo &tgc
:echo &t_8f
:echo &t_8b
They should output:
1
^[[38:2:%lu:%lu:%lum
^[[48:2:%lu:%lu:%lum
Or:
1
^[[38;2;%lu;%lu;%lum
^[[48;2;%lu;%lu;%lum

How to store the line numbers of the lines containing a specific string in a text file in an environment variable?

I currently have this batch code that tells me the amount of times this string comes up in a text file.
#ECHO OFF
set /a Numb=0
for /f %%i in ('FINDSTR /N .* %1') do (set /a Numb+=1)
echo %Numb%
I need another piece of code that outputs the line numbers that the text is on to a variable.
How to store the line numbers of the lines containing a specific string in a text file in an environment variable?
My batch code for this task which requires the specification of file name and search string as arguments on running the batch file with some error checking:
#echo off
setlocal EnableDelayedExpansion
set "FileName=%~1"
set "Search=%~2"
rem Exit batch file if the two required arguments were not specified.
if "%FileName%" == "" (
echo Error: There is no file name specified as first parameter.
goto ErrorOuput
)
if "%Search%" == "" (
echo Error: There is no search string specified as second parameter.
goto ErrorOuput
)
if not exist "%FileName%" (
echo Error: The file "!FileName!" does not exist.
goto ErrorOuput
)
set "LineNumbers="
for /F "delims=:" %%I in ('%SystemRoot%\System32\findstr.exe /I /L /N /C:"%Search%" "%FileName%" 2^>nul') do set "LineNumbers=!LineNumbers!,%%I"
if "%LineNumbers%" == "" (
echo Info: The string "!Search!" could not be found in "!FileName!"
goto EndBatch
)
rem Remove the comma from begin of list of line numbers.
set "LineNumbers=!LineNumbers:~1!"
echo Found "!Search!" in "!FileName!" on the lines:
echo.
echo %LineNumbers%
goto EndBatch
:ErrorOuput
echo.
echo Usage: %~nx0 "file name" "search string"
:EndBatch
echo.
endlocal
pause
The error checking is not complete. There can still errors occur. For example the first argument could be *.txt which would produce a wrong result as FINDSTR outputs in this case first the file name, then a colon, next the line number, and one more colon instead of just line number and colon like when searching on a single file.
Run at least once in a command prompt window for example
findstr /I /L /N /C:"endbatch" "SearchString.bat"
with above batch code stored in file SearchString.bat in current directory to see what command FOR processes here.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains %~1 and %~2
echo /?
endlocal /?
findstr /?
for /?
goto /?
if /?
pause /?
rem /?
set /?
setlocal /?
Read also the Microsoft article about Using command redirection operators for an explanation of 2>nul to redirect the error message output by FINDSTR to handle STDERR to device NUL to suppress it if the searched string could not be found in search file. The redirection operator > must be escaped here with ^ to apply the redirection on execution of FINDSTR instead of interpreting 2>nul as redirection for command FOR at an invalid position in command line.
How do I store the line numbers of matching lines for a string in a text file?
Use the following batch file.
test.cmd:
#echo off
setlocal enabledelayedexpansion
set line_numbers=
for /f "skip=2 delims=[]" %%i in ('find /n /i "%1" names.txt') do (
set line_numbers=!line_numbers! %%i
)
rem skip leading space
echo %line_numbers:~1%
endlocal
Notes:
Pass search string as an argument to test.cmd.
The file being searched is names.txt (you could pass this as a parameter as well).
The match line numbers are add to the variable line_numbers.
Example usage:
F:\test>type names.txt
Joe Bloggs, 123 Main St, Dunoon
Arnold Jones, 127 Scotland Street, Edinburgh
Joe Bloggs, 123 Main St, Dunoon
Arnold Jones, 127 Scotland Street, Edinburgh
Joe Bloggs, 123 Main St, Dunoon
Arnold Jones, 127 Scotland Street, Edinburgh
F:\test>test bloggs
1 3 5
F:\test>test jones
2 4 6
Further Reading
An A-Z Index of the Windows CMD command line - An excellent reference for all things Windows cmd line related.
find - Search for a text string in a file & display all the lines where it is found.
for /f - Loop command against the results of another command.
variables - Extract part of a variable (substring).

How to insert with increasing numbers of line

This is a small part of the file, the original file has hundreds of lines.
Line 1 below insert the new line Numbers 1, 2, 3 lines below the new line number 2, 3, and so on, are as follows.
How to use gVim command and function to achieve the change from above to below.
I'm using gVim of windows platform.
Before the modification
hsd
xlfh
1lm
2lm
3lm
4lm
5lm
6lm
7lm
8lm
9lm
slm
s1lm
......
After the modification
hsd
1
xlfh
1lm
2
3
2lm
3lm
4lm
4
5
6
5lm
6lm
7lm
8lm
7
8
9
10
9lm
slm
s1lm
......
I do not know why you would need to do this, but if you need this often, consider a function inside .vimrc:
function! Nameme()
1
let mov = 1
let start = 1
let inc = 0
while 1
call append(line('.'), range(start, start+inc))
let mov += 2
let inc += 1
let start += inc
if mov + line('.') > line('$')
break
endif
execute mov + line('.')
endwhile
endfunction
Then you could just :call Nameme().
It is possible in Vim, merging another file containing the numbers to insert (created by /bin/cat -n for example), here is the beginning.
gg go to first line
o1<esc>"ayy a (will increase) initialized to 1
"byy b (will be cumsum of a) initialized to 1
qz loop this:
:.,<c-r>a advance by a lines
"bp put a(a-1)
... but I will only continue if you format your question so that it does not end up deleted

how to detect line number of output of shell script

I am using below script ,
clear
tput cup 1
echo "1";
tput cup 2
echo "2";
tput cup 4
echo "3";
then Out put is coming like
1
2
3
If i use wrong script like ,
clear
tput cup 1
echo "1";
tput cup 2
echo ;"2";
tput cup 3
echo "3";
then out put is
1
3/var.sh: line 5: 2: command not found
This means in third line 3 printed and 2 line error also printed .
So is there any way to detect error line number to print 3 after error?
EDIT:
when I use -x , output is
[root#srinivas Installation]# sh -x var.sh
+ clear
+ tput cup 1
+ echo 1
+ echo
+ echo 3up 2
3 2
[root#srinivas Installation]# found
+ tput cup 3
If you run your shell script with the -x option, it'll show you each line as it executes.
This is because standard output and standard error are printed in different ways - Standard output is synchronous, meaning the lines will be printed in sequence and as they arrive, while standard error is asynchronous, which means it's printed whenever the terminal can fit it in. One way to fix this is to chunk standard error together with standard output:
/var.sh 2>&1
More details in Greg's wiki.
PS: All the semicolons in the file are unnecessary - If your commands are separated by newlines, semicolons will never be necessary.
That output looks like what should be expected. Here's the sequence:
tput cup 1
echo "1"
Move to line 1 and output a 1. This works properly.
tput cup 2
echo ;"2";
Move to line 2, then output a blank line (echo with no arguments) which moves to line 3. Then execute a program named 2, which the script can't find, resulting in the error message ./var.sh: line 5: 2: command not found printed on line 3.
tput cup 3
echo "3";
Move to line 3 and output a 3, which overwrites the . in the above error message. Resulting in the final apparent output that you note, even though it wasn't produced in a strictly left-to-right top-to-bottom order.

VIM: Check if a file is open in current tab? window? (and activate it)

In vim, you can check if a file is open in the current buffer with bufexists. For a short filename (not full path), you can check if it's open using bufexists(bufname('filename')).
Is there any way to check if a file is open in a tab?
My closest workaround is to do something like:
:tabdo if bufnr(bufname('filename')) in tabpagebuflist(): echo "Yes"
However, that's sort of pythonic pseudocode... I'm not sure how to get that to work in vim. My goal is for an external applescript to check if a file is already open and if so go to a line in that file.
Ideally, I'd like to be able to search through different GUI windows too, but I've gathered (e.g. Open vim tab in new (GUI) window?) that working with different GUI windows is very challenging / impossible in VIM.
My impatience and good documentation got the better of me... here's the solution (greatly aided by Check if current tab is empty in vim and Open vim tab in new (GUI) window?). The source is at https://github.com/keflavich/macvim-skim
function! WhichTab(filename)
" Try to determine whether file is open in any tab.
" Return number of tab it's open in
let buffername = bufname(a:filename)
if buffername == ""
return 0
endif
let buffernumber = bufnr(buffername)
" tabdo will loop through pages and leave you on the last one;
" this is to make sure we don't leave the current page
let currenttab = tabpagenr()
let tab_arr = []
tabdo let tab_arr += tabpagebuflist()
" return to current page
exec "tabnext ".currenttab
" Start checking tab numbers for matches
let i = 0
for tnum in tab_arr
let i += 1
echo "tnum: ".tnum." buff: ".buffernumber." i: ".i
if tnum == buffernumber
return i
endif
endfor
endfunction
function! WhichWindow(filename)
" Try to determine whether the file is open in any GVIM *window*
let serverlist = split(serverlist(),"\n")
"let currentserver = ????
for server in serverlist
let remotetabnum = remote_expr(server,
\"WhichTab('".a:filename."')")
if remotetabnum != 0
return server
endif
endfor
endfunction
then use like so:
exec "tabnext ".WhichTab('my_filename')
echo remote_foreground( WhichWindow('my_filename') )
or, from the command line, here's a script to go to a particular line of a file using WhichTab:
#!/bin/bash
file="$1"
line="$2"
for server in `mvim --serverlist`
do
foundfile=`mvim --servername $server --remote-expr "WhichTab('$file')"`
if [[ $foundfile > 0 ]]
then
mvim --servername $server --remote-expr "foreground()"
mvim --servername $server --remote-send ":exec \"tabnext $foundfile\" <CR>"
mvim --servername $server --remote-send ":$line <CR>"
fi
done
I'd reply to keflavich, but I can't yet...
I was working on a similar problem where I wanted to mimic the behavior of gvim --remote-tab-silent when opening files inside of gvim. I found this WhichTab script of yours, but ran into problems when there is more than one window open in any given tab. If you split windows inside of tabs, then you will have more than one buffer returned by tabpagebuflist(), so your method of using the buffer number's position in the List doesn't work. Here's my solution that accounts for that possibility.
" Note: returns a list of tabnos where the buf is found or 0 for none.
" tabnos start at 1, so 0 is always invalid
function! WhichTabNo(bufNo)
let tabNos = []
for tabNo in range(1, tabpagenr("$"))
for bufInTab in tabpagebuflist(tabNo)
if (bufInTab == a:bufNo)
call add(tabNos, tabNo)
endif
endfor
endfor
let numBufsFound = len(tabNos)
return (numBufsFound == 0) ? 0 : tabNos
endfunction
I think I can just return tabNos which will be an empty list that gets evaluated as a scalar 0, but I just learned vimscript and am not that comfortable with the particulars of its dynamic typing behavior yet, so I'm leaving it like that for now.

Resources