How to search at vim 'scriptnames' command - vim

The vim 'scriptnames' command output all scripts loaded. The problem is that I can't find any practical way to filter/search/find on it. I want to look for some script without having to do this by "eye brute force".

There is no such thing as a script command, there are only scriptencoding and scriptnames (which can be abbreviated as scr, according to :h :scr). I presume you're looking for scriptnames.
With Vim 8 you can filter the results of most commands with :filter:
:filter /pattern/ scriptnames
(cf. :h :filter).
With older versions of Vim you can redirect all messages to a file before running :scriptnames, then cancel the redirection:
:redir >file
:scriptnames
:redir END
(cf. :h :redir). Alternatively, you can redirect messages to a register, then paste the contents of the register to a buffer:
:redir #a
:scriptnames
:redir END
:new
"aP
Finally, Tim Pope's plugin scriptease adds a command :Scriptnames that runs :scriptnames and loads the results into a quickfix list.

Instead of :redir, we have execute() with recent versions of vim.
Thus, you can play with :echo filter(split(execute('scritnames'), "\n"), 'v:val =~ "somepattern") or :new+put=execute(':scriptnames')+search in the buffer as you would have explored a log life.

Related

How to move to end of a file upon opening it via a command in .vimrc using vim/MacVim?

I'm trying to open a file using a command I set in my .vimrc file. The relevant line in my .vimrc is similar to the following:
command Of so /Users/Dude/Working/open_file.txt
With open_file.txt containing the following:
tabnew /Users/Dude/Working/Project/config.txt
What I'd like to do when executing the 'Of' command is navigate to the end of config.txt. I've tried adding a large line number which is unlikely to exceed the number of lines in the file like so:
tabnew /Users/Dude/Working/Project/config.txt
250000
This takes me to the end of the file but doesn't seem like the right way to do it. Ideally, I'd also like to add a new line after the last line and navigate there too.
A few things:
I would suggest you use full names instead of short names. e.g. so -> source.
source is probably the wrong choice here as you can do everything with the right-hand-side of command
May want to use ! with command so you can resource your vimrc file. e.g. command! Of ...
$ represents the last line of the file. No need to choose a magic number
Create a new line can be done with :normal o or :put _
So with some tweaks we get the following command:
command! Of tabedit /Users/Dude/Working/Project/config.txt | $put_
For more help see:
:h :command
:h :put
:h :range
:h :bar
Have a look at :h :normal in your case just write :norm Go instead of your number there.
:tabnew, like most variants of :edit (and the command-line arguments when launching Vim), takes arbitrary Ex commands via the [+cmd] argument. The $ command will move to the end of the file:
tabnew +$ /Users/Dude/Working/Project/config.txt

redirecting vim :make output to file

Rather than having vim print the output of the :make command, I want to read the output in a file (which gets updated automatically in vim); so that my compiled file can run right away without having to see the output of the :make command.
I'm using the following makefile
all: compile run
compile: file.cc
g++ -o file file.cc
run: file
./file
How does one redirect the output of the :make command in a way that it isn't also printed to the screen by vim?
First of all we have https://vi.stackexchange.com/ , you can get better answers about Vim in there.
Second, I'll argue that a Makefile is no place to run a program, the idea behind make is to catch compilation errors. But assuming you have your reasons (e.g. ./file opens a graphical display) there are a couple of ways to perform this in Vim:
For a start you can set makeprg to perform the redirection:
:set makeprg=make\ >/dev/null\ 2>&1
(You can change /dev/null to an actual file)
But that still leaves the line:
Press ENTER or type command to continue
And asks for confirmation, which may be annoying when you know that there is no output.
To get rid of the confirmation line you can use silent as follows:
set makeprg=make\ >/dev/null\ 2>&1
function! MyMake()
silent make
redraw!
endfunction
command Mm call MyMake()
And now you can do:
:Mm
To perform the make and go back to straight to Vim. (the redraw! is needed only in some terminals)
You can execute this command:
:silent exec "!make >Output" | :redraw!
The file Output contains the last output of the executed make command.
Use :silent to remove the output and "press enter" prompt. I suggest a nice mapping or command:
command! -nargs=* Smake silent make <args>
nnoremap <f5> :silent make<cr>
:make will populate the quickfix list with the results from :make. Use :copen to open the quickfix window.
For more help see:
:h :command
:h silent
:h :make
:h 'makeprg'
:h quickfix

Open file hook to move the cursor to the buffer/file end

How can i write a hook function that will place the cursor at the end of the file on opening a file.
In elisp, it looks approximately like this,
(add-hook 'open-buffer-hook
(lambda () (end-of-buffer)))
In vim, I can open a file and press :$ to go to the end but i am keen on doing it via a hook.
Using autocmd you may hook into BufReadPost and execute something like G$ in normal mode to advance to the last line and the last character.
autocmd BufReadPost * :normal G$
I used BufReadPost to cause this command to run after the file is fully read into the buffer. The * applies this rule to all buffer types, but you could limit it by FileType or by filename pattern as well. See :help autocmd for more details.
An autocommand seems too much to me.
In your shell,
$ vim file +$
opens file in Vim and jumps to the last line.
In Vim,
:edit +$ file
opens file and jumps to the last line.
This works with other related commands like :vsplit or :tabedit.
It you just want to open files from the command line, you can use
vim +':norm G$' file.txt

set complete+=k[file] not working for whole line completion?

I have ~/.bash_history that contains lines such as sudo apt-get install, aplay foo.wav, etc. I thought it would be convenient if I could use these lines for completing whole lines while writing shell scripts.
:h compl-whole-line says:
CTRL-X CTRL-L
Search backwards for a line that starts with the
same characters as those in the current line before
the cursor. Indent is ignored. The matching line is
inserted in front of the cursor.
** The 'complete' option is used to decide which buffers
are searched for a match. Both loaded and unloaded
buffers are used.**
Note the asterisks I inserted. :h 'complete' says:
k k{dict} scan the file {dict}. Several "k" flags can be given,
patterns are valid too. For example: >
:set cpt=k/usr/dict/*,k~/spanish
So I thought :set complete+=k~/.bash_history would do the job. It didn't.
Start vim with
$ vim -u NONE -N
then
:set complete+=k~/.bash_history
:set complete?
" complete=.,w,b,u,t,i,k~/.bash_history
, I enter to the insert mode (i), and when I type
su<C-x><C-l>
, vim says Whole line completion (^L^N^P) Pattern not found. The completion is working for words, so when I type
su<C-p>
sudo is suggested.
What am I missing? How can I use my history for whole line completion without :sp ~/.bash_history?
set complete+=k[file] has nothing to do with line completion: whatever file you give to it will only be used as a source by dictionary completion (<C-x><C-k>) and keyword completion (<C-n>/<C-p>).
:help i_ctrl-x_ctrl-l is clear: line completion only works with lines found in loaded and unloaded buffers. Since ~/.bash_history is not loaded as a buffer, line completion will obviously never use it as a source.
So yes, the only practical solution is to load that file.
:sp ~/.bash_history is not really optimal, though, because a) it takes too much room, both physically and in your buffer list, and b) it requires way too many keystrokes.
The "too much room" part of the problem is easily solved with a more suited command:
:badd ~/.bash_history
The "too many keystrokes" part of the problem could be solved with an autocommand that runs the command above each time you edit a shell script:
augroup shell
autocmd!
autocmd BufNewFile,BufRead *.sh badd ~/.bash_history
augroup END

redirection to a file of a search in Vim

My problem is simple. I search a specific pattern in a file (let's say label in a Tex file)
:g/label/#
but there are lots of occurrences. So I'd like to redirect this output to another file to be able to work easily with it.
Do you have a trick or a command that I don't know?
it's not clear from the original post what you mean by "work easily with it" but it's often useful to see and quickly jump between all of the matches in a buffer without "extracting" the matches to a separate buffer.
vim has an internal grep built in. your example would be something like this (in vim, % denotes the current file)
:vimgrep /label/ %
This will take you to the first occurrence and report how many matches there were. What's cool is that you can look at all of the matches listed by opening up the quickfix error list using
:cope
Now you can just scroll around and press enter on a line to jump to the exact position of the match.
The quickfix error list is exactly the same buffer you use if you run make from inside vim and your compiler throws errors: it gives you a list of what and where the errors are.
After you've jumped to one location pointed by quickfix, you can go to forwards and backwards in the list via :cn and :cp. :ccl closes the error list.
You can also expand your "error" list via :vimgrepa /newpattern/ % or :vimgrepadd
The (documented) caveat is that vim's internal grep is slower than most native grep implementations (but you do get it "for free" in windows, for example). If you do have a grep installed, you can use :grep instead of :vimgrep for similar results.
quoting :help grep
Vim has two ways to find matches for a
pattern: Internal and external. The
advantage of the internal grep is that
it works on all systems and uses the
powerful Vim search patterns. An
external grep program can be used when
the Vim grep does not do what you
want.
The internal method will be slower,
because files are read into memory.
The advantages are:
- Line separators and encoding are automatically recognized, as if a file
is being edited.
- Uses Vim search patterns. Multi-line patterns can be used.
- When plugins are enabled: compressed and remote files can be searched.
You can also use the location list if you're already using the error list for dealing with compilation errors. just add l (for location) to the beginning of the grep command (:lvimgrep,:lvimgrepa :lgrep, :lgrepa) and use :lopen :ln :lp :lcl instead of the :c* ones.
For more commands consult
:help grep
:help quickfix-window
:help quickfix
:help quickfix-error-lists
:redir > matches.txt|execute 'g/foo/#'|redir END
See :h :redir, you can also redirect to registers, variables, the clipboard etc.
What you're doing is essentially 'grep -n label file' from command line. So you can run that command and > it into a file easily enough.
The derivation of 'grep' is even from basically the same source.
I've gotten this of the net at some point:
function GoToLine(mainbuffer)
let linenumber = expand("<cword>")
silent bd!
silent execute "buffer" a:mainbuffer
silent execute ":"linenumber
silent nunmap <Enter>
endfunction
command -nargs=1 GoToLine :call GoToLine(<f-args>)
function GrepToBuffer(pattern)
let mainbuffer = bufnr("%")
silent %yank g
enew
silent put! g
execute "%!egrep -n" a:pattern "| cut -b1-80 | sed 's/:/ /'"
silent 1s/^/\="# Press Enter on a line to view it\n"/
silent :2
silent execute "nmap <Enter> 0:silent GoToLine" mainbuffer "<Enter>"
" silent nmap <C-G> <C-O>:bd!<Enter>
endfunction
command -nargs=+ Grep :call GrepToBuffer(<q-args>)
Put it in your .vimrc, then :Grep Foo
Requires external grep program to work properly.
(Just an idea -- untested.)
You can delete all the lines with your pattern in it, write to another file, and undo the delete.
:g/label/d
:w matches
u

Resources