Vimscript print function? - function

Is there a function in Vimscript or a convention that allows you to simply print text to the editor? The function echo only supplies a command line print function, and does not actually print to the editor.

When you say "print to the editor", I take it you mean "print to the current buffer". If that's correct, take a look at :help append().

A facility I sometimes use is :redir #" (or :redir #a for register a), which redirects the output of commands to a buffer, so you can paste it. To stop output redirection, say :redir end. See :help :redir.

Related

Glob as the argument of a shell function

I'm writing a reusable function, so I need the argument to be as flexible as possible.
Consider a simple example:
function testf(){
print ./*.$1
}
This works. For example, with testf mp3 it lists all the files ending with .mp3 in an array, making possible the use of for loops. But this way it only allows me to work with the extension name.
Therefore, I tried:
function testf(){
print ./$1
}
However, it doesn't work. Using testf *.mp3, unlike using print *.mp3 in the terminal, it will only pass the first matching string instead of the whole array.
Any suggestion?
ists all the files ending with .mp3 in an array ... there is no array involved in your question.
But to your problem: First, you want to pass to your function a wildcard pattern, but this is not what you are actually doing. testf *.mp3 expands the pattern before the function is invoked (this process is called filename generation), and your testf gets just a list of files as parameters. You can pass a pattern, but you have to ask the shell not to expand it:
testf '*.mp3'
In this case, your $1 indeed will contain the string *.mp3. However, your print ./$1 will still not work. The reason is that filename generation occurs before parameter expansion (which is the process where $1 is replaced by the string it contains). Again, you have to ask the shell to do it the other way round:
print ./${~1}
The shell performs several types of expansions before launching the command. When you enter
testf *.mp3
the shell will expand the glob first, and pass each filename as a separate argument to the function
Your function could look like this:
function testf(){
printf './%s\n' "$#"
}

How to add html attributes and values for all lines quickly with vim and plugins?

My os:debian8.
uname -a
Linux debian 3.16.0-4-amd64 #1 SMP Debian 3.16.39-1+deb8u2 (2017-03-07) x86_64 GNU/Linux
Here is my base file.
home
help
variables
compatibility
modelines
searching
selection
markers
indenting
reformatting
folding
tags
makefiles
mapping
registers
spelling
plugins
etc
I want to create a html file as bellow.
home
help
variables
compatibility
modelines
searching
selection
markers
indenting
reformatting
folding
tags
makefiles
mapping
registers
spelling
plugins
etc
Every line was added href and id attributes,whose values are line content pasted .html and line content itself correspondingly.
How to add html attributes and values for all lines quickly with vim and plugins?
sed,awk,sublime text 3 are all welcomed to solve the problem.
$ sed 's:.*:&:' file
home
help
variables
compatibility
modelines
searching
selection
markers
indenting
reformatting
folding
tags
makefiles
mapping
registers
spelling
plugins
etc
if you want to do this in vi itself, no plug-in neccessary
Open the file, type : and insert this line as the command
%s:.*:&
it will make all the substitutions in the file.
sed is the best solution (simple and pretty fast here) if your are sure of the content, if not it need a bit of complexity that is better treated by awk:
awk '
{
# change special char for HTML constraint
Org = URL = HTML = $0
# sample of modification
gsub( / /, "%20", URL)
gsub( /</, "%3C", HTML)
printf( "%s\n", URL, Org, HTML)
}
' YourFile
To complete this easily in Sublime Text, without any plugins added:
Open the base file in Sublime Text
Type Ctrl+Shift+P and in the fuzzy search input type syn html to set the file syntax to HTML.
In the View menu, make sure Word Wrap is toggled off.
Ctrl+A to select all.
Ctrl+Shift+L to break selection into multi-line edit.
Ctrl+C to copy selection into clipboard as multiple lines.
Alt+Shift+W to wrap each line with a tag-- then tap a to convert the default <p> tag into an <a> tag (hit esc to quit out of any context menus that might pop up)
Type a space then href=" -- you should see this being added to every line as they all have cursors. Also you should note that Sublime has automatically closed your quotes for you, so you have href="" with the cursor between the quotes.
ctrl+v -- this is where the magic happens-- your clipboard contains every lines worth of contents, so it will paste each appropriate value into the quotes where the cursor is lying. Then you simply type .html to add the extension.
Use the right arrow to move the cursors outside of the quotes for the href attribute and follow the two previous steps to similarly add an id attribute with the intended ids pasted in.
Voila! You're done.
Multi-line editing is very powerful as you learn how to combine it with other keyboard shortcuts. It has been a huge improvement in my workflow. If you have any questions please feel free to comment and I'll adjust as needed.
With bash one-liner:
while read v; do printf '%s\n' "$v" "$v" "$v"; done < file
(OR)
while read v; do echo "$v"; done < file
Try this -
awk '{print a$1b$1c$1d}' a='' d='' file
home
help
variables
compatibility
modelines
searching
selection
markers
indenting
reformatting
folding
tags
makefiles
mapping
registers
spelling
plugins
etc
Here I have created 4 variable a,b,c & d which you can edit as per your choice.
OR
while read -r i;do echo ""$i";done < f
home
help
variables
compatibility
To execute it directly in vim:
!sed 's:.*:&:' %
In awk, no regex, no nothing, just print strings around $1s, escaping "s:
$ awk '{print "" $1 ""}' file
home
help
If you happen to have empty lines in there just add /./ before the {:
/./{print ...
list=$(cat basefile.txt)
for val in $list
do
echo ""$val"" >> newfile.html
done
Using bash, you can always make a script or type this into the command line.
This vim replacement pattern handles your base file:
s#^\s*\(.\{-}\)\s*$#\1#
^\s* matches any leading spaces, then
.\{-} captures everything after that, non-greedily — allowing
\s$ to match any trailing spaces.
This avoids giving you stuff like home .
You can also process several base files with vim at once:
vim -c 'bufdo %s#^\s*\(.\{-}\)\s*$#\1# | saveas! %:p:r.html' some.txt more.txt`
bufdo %s#^\s*\(.\{-}\)\s*$#\1# runs the replacement on each buffer loaded into vim,
saveas! %:p:r.html saves each buffer with an html extension, overwriting if necessary,
vim will open and show you the saved more.html, which you can correct as needed, and
you can use :n and :prev to visit some.html.
Something like sed’s probably best for big jobs, but this lets you tweak the conversions in vim right after it’s made them, use :u to undo, etc. Enjoy!

Function to open a file and navigate to a specified line number

I have the output of recursive grep (actually ag) in a buffer, which is of the form filename:linenumber: ... [match] ..., and I want to be able to go to the occurrence (file and line number) currently under the cursor. This told me that I could execute normal-mode movements, so after extracting the file:line portion, I wrote this function:
function OpenFileNewTab(name)
let l:pair=split(a:name, ":")
execute "tabnew" get(l:pair, 0)
execute "normal!" get(l:pair, 1) . "G"
endfunction
It is supposed to open the specified file in a tab and then do <lineno>G, like I am able to do manually, to go to the specified line number. However, the cursor just stays on line 1. What am I doing wrong?
This question, by title alone, would be an exact duplicate, but it talks locating symbols in other files, while I already have the locations at hand.
Edit: My mappings for grep / ag are as follows:
nnoremap <Leader>ag :execute "new \| read !ag --literal -w" "<C-r><C-w>" g:repo \| :set filetype=c<CR>
nnoremap <Leader>gf ^v2t:"zy :execute OpenFileNewTab("<C-r>z")<CR>
To get my grep / ag results, I put the cursor on the word I want to search and enter <leader>ag, then, in the new buffer, I put the cursor on a line and enter <leader>gf - it selects from the start up to the second colon and calls OpenFileNewTab.
Edit 2: I'm on Cygwin, if it is of any importance - I doubt it.
Why don't you set &grepprg to call ag ?
" according to man ag
set grepprg=ag\ --vimgrep\ $*
set grepformat=%f:%l:%c:%m
" And then (not tested)
nnoremap <Leader>ag :grep -w <c-r><c-w><cr>
As others have said in the comments, you are just trying to emulate what the quickfix windows already provides. And, we are lucky vim can call grep, and it has a variation point to let us specify which grep program we wish to use: 'grepprg'.
Use file-line plugin. Pressing Enter on a line in the quicklist will normally open that file; file-line will make any filename of the form file:line:column (and several other formats) to open file and position to line and column.
I only found this (old) thread after I posted the exact same question on vi.stackexchange: https://vi.stackexchange.com/q/39557/44764. To help anyone who comes looking, I post the best answer to my question below as an alternative to the answers already given.
The gF command, like gf, opens the file in a new tab but additionally it also positions the cursor on the line after the colon. (I note the OP defines <leader>gf so maybe vim/neovim didn't auto-define gf or gF at the time this thread was originally created.)

Seeking a vim function to insert the text behind a hyperlink

I'm writing a book. I have a large notes file, with hyperlinks of interest. I'd like to be able to move the cursor over a hyperlink, execute a command, and have the text of the webpage inserted for reading, cutting, and modifying. Ideally, it would only be the readable text rather than the full HTML, but I'll take what I can get (or what I can wget, if that's the right shell function).
Surely such a thing has already been put together, but searches for "vim insert text hyperlink" and such are not very helpful. Have you seen this function?
With your mouse cursor on a hyperlink, execute
:rC-rC-aEnter
This will insert the raw contents on the following line.
To preprocess:
:r !links -dumpC-rC-aEnter
Of course, you can map this to a key:
:nnoremap <F6> :r !links -dump <C-r><C-a><CR>
Various notes:
If you have quoted urls, you might not be happy about C-rC-a because the quotes will get included. Consider doing
:se iskeyword+=/,:,.
And use C-rC-w instead. Alternatively,
:se isfname-="
allows you to use C-rC-f instead.
If you don't want to tinker with any of your settings, consider creating a function that saves and restores the value of &iskeyword or &isfname. To bring out the big gun, write a regex for URLs and use that:
func! ReadFromUrl()
let url = substitute(getline('.'), '\c\v^.*((https?|ftp|file)://[a-z0-9.:/%+()]+).*$', '\1', '')
exec 'r! links -dump "' . url . '"'
endf
command! ReadFromUrl call ReadFromUrl()
nnoremap! <F6> ReadFromUrl<CR>
Move the cursor to the hype-link, and type this command:
:exec 'r!wget -q -O- ' getline('.') ' | html2text'
It'll append the content of the hype-link after the hype-link.
To make this command work, you need install html2text.
Good luck!

vim run perl script with word under cursor as argument

is it possible to send the word under the cursor to a perl script by typing a shortcut?
how do i do that?
Above solutions are not safe if word under cursor contains special characters. You should use
nnoremap <F2> :execute "!/path/to/script.pl ".shellescape(expand("<cword>"), 1)<CR>
instead.
For the whole line, replace expand("<cword>") with getline('.'). For the filename under cursor use expand("<cfile>").
Given a perl script ${HOME}/test.pl, you could use:
:nnoremap <F2> :!${HOME}/test.pl <C-R><C-W><CR>
Then pressing F2 would send the word under the cursor to your script.
As per my answer to your previous question, CTRL-R CTRL-W represents the word under the cursor.
See the following help topics in Vim to get you started with writing keyboard shortcuts:
:help :nnoremap
:help :map-special-keys
:help !
My test script:
#!/usr/bin/env perl -w
print "You selected '$ARGV[0]'.\n";
You can do the following:
nnoremap <f5> :!perl my_script.pl <c-r><c-w><enter>
In your vimrc, this lines maps the F5 key to this combination of characters. CTRL-R CTRL-W inserts current word in a command line.