Run bash command on Vim and copy result to clipboard - vim

How can I create a Vim command and copy it's results to clipboard?
I want to convert Markdown to HTML and copy the result to the clipboard. So far I got:
nmap md :%!/bin/markdown/Markdown.pl --html4tags
But this will substitute my opened file on Vim to the result of Markdown.

You didn't say which system you're using, but generally saving it in the +
register should work. You can call system():
:let #+=system("markdown --html4tags", join(getline(1,line("$")), "\n"))
The system() function takes the second parameter (optional) as input to the
command, and here I'm using a chain of other functions to retrieve the contents
of the current buffer. Not sure, but there should be a better way to do it (if
someone knows, please let me know).
Alternatively, you can pass markdown your file name as input directly:
:let #+=system("markdown --html4tags " . shellescape(expand("%:p")))
But keep in mind that you'll need to write the file before calling this.
Two important notes:
I didn't type your full path to markdown. Use it.
I didn't use maps here, the final result would be something like:
nnoremap md :let #+=system(...)

get the xsel package
and pipe stdout to xsel --clipboard
For instance:
cat /etc/passwd | xsel --clipboard
Is that what you're looking for?

Filling in a missing piece (2+ years late). With the clarification that the user was on a Mac and since the asker's "why doesn't it work for me?" question was not answered.
To redirect the output of a command to the system clipboard from within MacVim (GUI version) you need to set the '*' to be the "clipboard register" you need to change the clipboard setting to 'unnamed':
set clipboard 'unnamed' # 'cb' can be substituted for 'clipboard'
Then sidyll's answer should work except specify the '*' register and not the '+' register:
:let #*=system(...)
The clipboard feature is likely not compiled into the "terminal version" of MacVim and when it is available option setting is different from 'unnamed'. To see more details regarding what works where and how, see the documentation in MacVim using the Vim help command:
:help 'clipboard' (include the single quotes since it's a set option!)
(I'll skip the command mapping issue since it always takes me several tries and I still have to look it up; finding the help for the mapping commands should be easier than finding it for the * register.)

Related

Replace visual selection with command output

I would like to replace parts of one line with the result of the selection being piped into a command.
For example:
echo "hello $(echo "world" | base64)" | vim -
This will open a buffer with hello d29ybGQK in it. Now press wvw to visually select d29ybGQK.
Then I attempted :!base64 -d and I expected the buffer to contain hello world, which did not happen. Indeed, the whole line was piped into the command, and the whole line was replaced.
Is it possible to replace only the visual selection, and have only that selection piped into the command?
I also attempted c<c-r>=system('base64 -d') but that did not send the visual selection to the command's stdin.
Filtering with ! is always line-wise. Your solution with c and the
expression register is an excellent way to solve this. You only forgot
to pass the input to system(), which is its second optional argument.
Since you just changed the text selected, it went into the " register
automatically. All you need to do is to grab it back and pass it to
system with getreg():
c<C-R>=system('base64 -D', getreg('"'))
Note that base64 may echo a newline at the end. If you want to remove
it, either wrap the whole thing in trim(), a new function in Vim 8, or
use [:-2]:
c<C-R>=trim(system('base64 -D', getreg('"')))
c<C-R>=system('base64 -D', getreg('"'))[:-2]
This is a shorthand for [0:-2], meaning grab everything from character
0 to second-last in the resulting string.
Consider creating a visual map if you use it often:
vnoremap <leader>d c<C-R>=system('base64 -D', getreg('"'))[:-2]<CR>
For historical reasons, the Ex commands are inherently line-based; venerable vi also didn't have visual mode yet. That limitation includes filtering through an external command with :range!; it will always filter complete lines.
manual solution
For simple input like in your example, it's probably easiest to temporarily split the line, filter, and then reassemble. For example:
:substitute/ /\r/ | execute '.!base64 -d' | -1join
plugin solution
For a universal solution, you need to use or implement a plugin that grabs the selected text, filters it (probably through system()), and then replaces the selection with the result.
My SubstituteExpression plugin has a {Visual}g= mapping that can filter through Vimscript expressions, Vim functions and commands, and external commands.
express.vim by Tom McDonald offers an almost identical implementation. It also allows on-the-fly creation of operators via :MapExpress and :MapSubpress, something for which I would use my TextTransform plugin, which you need to install as a dependency, anyway. My plugin offers more advanced (cross-mode) repeats, and the :Ex-command expression variant, but has two large dependencies you also need to install.

Vim long file paths break/split over multiple lines in quickfix window

A long file paths is broken up over multiple lines in the Vim quickfix window which then for example does not allow to jump to the error location displayed in the qf.
The file (and the lines around) are diplayed in the quickfix window as (the example is the output from neomakes pdflatex)
|| Enter file name:
|| /long/path/to/file/.../loca
tionOfTexFiles/myTexFile.tex|144 error| Emergency stop.
|| read
to be able to follow to the file line by lnext/cnext I should have
/long/path/to/file/.../locationOfTexFiles/myTexFile.tex|144 error| Emergency stop.
For quickfix files I have the following relevant (in my view) settings which are set to:
setlocal nolinebreak
setlocal nowrap
setlocal textwidth=9999
So I am wondering how I can display the file path in one line within the quickfix window?
On :make, Vim invokes 'makeprg', captures the output, and then parses it according to 'errorformat'. The latter does support multi-line error messages (cp. :help errorformat-multi-line), but that is mostly for what I would call intentional linebreaks, as specified by the compiler. What you suffer from is unintentional linebreaks because of line wrapping (due to overly long paths).
Now, I don't know about "neomakes pdflatex", but it looks like that tool creates the linebreaks, whereas it shouldn't, as Vim is capturing the output, and there's no receiving terminal (or user). Investigating in that direction (or opening an issue at the project's tracker) might be helpful.
The mentioned Vim options ('linebreak', 'wrap', etc.) have nothing to do with it. They apply to normal buffers; the quickfix buffer as such is not modifiable.
Workarounds
A possible workaround might be to :cd first to a directory that is "closer" to the processed files (or even :set autochdir); this might avoid the long paths in the output.
Alternatively, you may "unmangle" the output by adding a sed stage after the compiler:
let &makeprg .= "| sed -e 's/.../...'"
If I'm not mistaken, the issue is on pdflatex side. The || mark is a good indication: you'll have one per output line -- in case filename and/or lines numbers are recognized, they'll be fed in between the bars.
So. This means you'll need a way to fix the path names. It'll be better to do it outside vim. I'm not saying this is trivial. I'm just saying that if you can have a program able to fix pdflatex outputs, you'll just be one pipe away from the solution (plus a correct forwarding of error codes...).
If you prefer to implement it in vim script, this is possible. But you'll experience side-effects. In my BuildToolsWrapper plugin I'm able to post-process compilation output in vim side, but the result is far from being perfect. I'm working on getqflist() result, and parse each line. When I found a line where I want to fix the filename, it's not simply about fixing the filename but also about assigning a valid buffer number to it. See this function where I can replace a filename with another one. The magic happens where lh#buffer#get_nr() is used. Still you'd need to implement a vim script able to merge split filenames.
IOW: my understanding is that vim is not involved. It could be used to fix the issue, but IMO this is not the easier path to undertake.

Vim: map GNU Screen command

Apologies if this has been asked before, but I feel overwhelmed with the Vim docs and I can't seem to figure this out.
I want to map the F5 key in Vim to accomplish the following actions:
Yank text from the visual selection in Vim.
Execute the yanked portion of the text in another GNU Screen session named ipython.
The second portion could be achieved by issuing the following command line argument (via :!), if only I was able to find a way to paste the register content between the double quotes of that line (but I can't figure out how):
map <F5> :!screen -x ipython -X stuff "[REGISTER 0 CONTENT]"<CR><CR>
Any help would be much appreciated!
For the second part, you can use
:execute "!screen -x ipython -X stuff " . shellescape(#0)
Here I copy my previous answer:
Maybe one of these two plugins is what you need:
slime is screen-based.
tslime is a tmux-based version of slime.
Given the nature of your question - I encourage you to take a look at vim-ipython. Using this plugin, you can send lines or whole files for IPython to execute, and also get back object introspection and word completions in Vim, like what you get with: object?<enter> and object.<tab> in IPython.
If you follow that github link, there are a few screencasts demonstrating what you can do with it. It requires IPython 0.11 or later, though, with ZeroMQ enabled.

prevent vim grep from opening first matching file

So, fiddling with the EasyGrep.vim plugin, trying to get it into a state that suits me.
I am using it for recursive searching of a Rails project. Ive almost got it how I want it, this is an example of the grep command my modified EasyGrep executes:
:grep -R -i --include=*.rb --include=*.rbw --include=*.gem --include=*.gemspec --include=[rR]akefile --include=*.erb --include=*.rhtml SEARCH_WORD .
Which finds the word under the cursor, and opens the search results in quicklist.
Only problem is, :grep seems to automatically open the file containing the first match into the current buffer, which I do not want it to do, because then I lose the file I was just looking at.
Anyone know how I can prevent this behavior? Or, at least a hacky workaround that reopens the file I was searching from?
:vimgrep is not an option - its far too slow.
From :help :grep:
Just like ":make", but use 'grepprg' instead of 'makeprg' and 'grepformat' instead of 'errorformat'.
From :help :make:
If [!] is not given the first error is jumped to.
So: :grep!
Add this to your .vimrc:
let g:EasyGrepOpenWindowOnMatch=0
EasyGrep has many options that can control how it behave. Type :GrepOptions for a listing of all of these.

Get the file name without file extension in a Vim function

I want to get the file name without the file extension in Vim.
I wrote the following function in my .vimrc file to compile and run the Java program:
:function! JAVA_RUN()
:!javac %^M
:endfunction
map <F3> :execute JAVA_RUN()<CR> :source $HOME/.vimrc<CR>
How can I get the file name without the extension inside the function?
:help expand() should give you the answer, see expand().
You should use the r modifier for %, with %:r instead of % to get the file name without extension.
If you want to write functions to build and execute files, you should also have a look at the documentation for shellescape, in order to prevent problems with spaces in file name or path.
If you want to expand a filename (other than % etc) take a look at fnamemodify()
fnamemodify({fname}, {mods}) *fnamemodify()*
Modify file name {fname} according to {mods}. {mods} is a
string of characters like it is used for file names on the
command line. See |filename-modifiers|.
fnamemodify("main.java", ":r") returns main.
I literally just read a similar question to this (in that someone else seemed to be trying to configure vim to build automagically for them with the F-key), and wrote an answer about how you can leverage the power of vim's :make command without even needing to write a Makefile. In your case, it's less directly related to the question, but I thought I'd mention it in case you were interested.
Furthermore, someone seems to have written something on Vim Tips Wiki about how to set up vim's :make command to specifically work with Java projects built with ant. I haven't worked with Java in a while myself, but in your case specifically it might be a good place to get started.
I came here looking for an answer for a similar question. I wanted to be able to extract the current class name from the java file being edited. I found a very neat way to do this in vim with an abbreviation:
ab xclass <C-R>=expand('%:t:r')<CR>
Place this line in your .vimrc (or similar) for this to work. An abbreviation will auto-trigger as soon as you press space, and so I usually prefix them with 'x' to avoid their accidental expansion.
The trick here is the combination of :t and :r in the argument to expand(). % is the "current file name", :t selects just the tail of the path ("last path component only") and :r selects just the root ("one extension removed"). (quoted parts are from the official expand() documentation.)
So when you are creating a new class in file /a/b/ClassIAmAboutToCreate.java you would type:
public class xclass {
the moment you press space after "xclass", the abbreviation will be expanded to public class ClassIAmAboutToCreate, which is exactly what you need.
Also, note that an abbreviation can be triggered by pressing Ctrl+] which avoids inserting a space after the class name.

Resources