Paste from clipboard in vim script - clipboard

I want to write a vim function that includes pasting from the clipboard (windows if it matters)
I think it should be something like
function MyPastingFunc()
"+p "paste from clipboard
"do more stuff
endfunction
Of course the "+p is just a comment in the .vim file. How can I make this work?

You are looking for the :normal command:
function MyPastingFunc()
"paste from clipboard
normal! "+p
"do more stuff
endfunction
The ! is used to prevent vim also running user mappings that might be part of "+p.

If you always want to past into a new line you can use the :put command, e.g:
:put + will paste after the current line
:put! + will paste before the current line
:123 put + will paste after line 123
N.B. it will also move the cursor position to the first non-blank character of the inserted text. This may or may not be what you want.

You should be able to use the feedkeys function, whose name is pretty self-explanatory:
function MyPastingFunc()
call feedkeys("\"+p") "paste from clipboard
"do more stuff
endfunction

Related

How do you make the terminal $PS1 indent when wrapping to a second line?

I'm trying to make my PS1 more readable and one issue I'm currently having is that my file prompts are too long. I don't want to shorten them however, since that would mean loss of exactitude.
My solution so far is to simply send the prompt after the file location to a new line. But this still doesn't look clean, as the file location is cut off mid filename and then continued underneath the username.
What I'm trying to do is have it look something like this in the end:
gingerbread: ~/file/file/file/file/file/
file/file/file/file.txt
But what I have right now is this:
gingerbread: ~/file/file/file/file/file/fil
e/file/file/file.txt
N.B. I already have a function doing the name prompt, cos I'm an idiot and made the username show up in all the colors of the rainbow... Here's the code for that in case it helps:
fancyName()
{
PERSPS='';
NAME='gingerbread';
LENGTHNAME=${#NAME};
for i in `seq 1 $LENGTHNAME`;
do
NUM=$((($i % 8) + 30));
PERSPS="$PERSPS\[\033[01;$NUM";
PERSPS+="m\]${NAME:$i-1:1}";
done
PERSPS="$PERSPS\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\n\[$\] ";
}
I then use $PERSPS as the $PS1. The whole thing just cycles through colors basically.
How do I control where the prompt wraps and where it wraps to?
Thanks in advance,
-Me.

insert bash script output in vim file

I'm writing markdown in Vim and using this shortcut to set correct markdown image syntax:
nnoremap <leader>p :s/.*/![](\0)/ <CR>
when pressing ,p, /path/to/image/img.jpg (in my vim text file) becomes
![](/path/to/image/img.jpg)
But I want to add after that this { width = *variable*% }, like this
![](img.jpg){ width = *variable*% }
I made this little bash script (img.sh) that gives me the variable according to the image size:
#!/bin/bash
VAR=$(identify -format '%h' $1)
echo "scale=3; 300 * (100/$VAR)" | bc
If I do this in vim :r !img.sh /path/to/image/img.jpg I get a number in this case 32
I would want to launch this script with the shortcut above, I tried this:
nnoremap <leader>p :s/.*/![](\0){ width=/ <CR> :r !img.sh /path/to/image/img.jpg <CR> % }
I want you to help me to find a way to not type path to image to execute the script. Path to image is already written in the text if i could find a way to indicate to vim to place it in the shortcut after img.sh it would be great !
You can use a Vimscript expression on the replacement side of your :s command, that way you can refer to the text in the match (which is the path to the image) using submatch(0). You can use an expression on the replacement of a :s by beginning it with \=, see :help sub-replace-expression for more details.
Using a replacement expression, you can also use the system() function to call the external command, instead of using a separate :r !... command to read its output into the current buffer.
Putting it all together:
:s/.*/\='![]('.submatch(0).']{ width='.trim(system('img.sh '.submatch(0))).' }'/
Or to add a mapping to it:
nnoremap <leader>p :s/.*/\='![]('.submatch(0).']{ width='.trim(system('img.sh '.submatch(0))).' }'/<CR>
(NOTE: You might also want to add a :noh command to the end of your mapping, otherwise it will keep highlighting the search for .* which matches everything.)
nnoremap <leader>p :s/.*/\='![]('.submatch(0).']{ width='.trim(system('img.sh '.submatch(0))).' }'/\|noh<CR>

Stata delimit in command line

I am working on a .do file created by someone else. This person used a semicolon delimiter in the entire file. I am trying to go through this file and see what is going on. I like to do this by selecting a portion of the code and hitting the "Execute Selection (do)" button. However, the delimiter seems to be messing up this. Are there any workarounds for me?
Suppose your do-file looks like this:
#delimit ;
set obs
10 ;
gen x = _n ;
gen y = x^2 ;
gen z = x
^3;
Anytime you highlight a selection and press "Execute selection (do)", Stata creates a temporary, self-contained do-file, with default delimit at cr and runs that:
"When a do-file begins execution, the delimiter is automatically set to
carriage return, even if it was called from another do-file that set the
delimiter to semicolon."
It does not sequentially run those commands from the console. Therefore, if you select the first 2 commands in the do-file above, the temporary do-file includes a call to #delimit whereas if you selected the last 2 commands, the temporary do-file would not have this call and would throw a syntax error for two line commands.
One solution could be to copy-paste selections to a fresh do-file that just had the #delimit command at the beginning, and then run that.
You could also write a script to rid your do-file of semicolons. If a line does not end in a semicolon, then append the next line to the end of the current line, and check this line again. Depending on how complex the syntax is in your do-file, this would be more or less difficult.
Another option is comment out the lines you have already ran by enclosing them with /* */ and to use exit; where you want to stop. You do have to be a little careful with local macros.

How would you do a cut and paste with this in VIM?

Say you had this text:
SOMETHING_XXXXXXXXXXXXXX_ELSE
SOMETHING_XXXXXXXXXXXXXX_ELSE2
SOMETHING_XXXXXXXXXXXXXX_ELSE3
SOMETHING_XXXXXXXXXXXXXX_ELSE4
And you wanted to replace all XXX..XXX with this word:
HELLOWORLD
If I go into visual mode, then yank the word, how could I then replace the XXX..XXX in the 4 lines above using cut and paste?
If I try, what happens is the X gets into my 'clipboard' and then I'm stuck to just typing it out manually.
I'm not sure if it will work in viemu, but in VIM you can do the following...
Using Yank and Paste
Yank the text to a specific register. Select the text in visual mode and use the command "ay to yank the text to the register a. Then when pasting call the command "ap, which pastes the contents of the a register.
Using Normal Command
But I would strongly prefer to use the normal command. Just select the lines
SOMETHING_XXXXXXXXXXXXXX_ELSE
SOMETHING_XXXXXXXXXXXXXX_ELSE2
SOMETHING_XXXXXXXXXXXXXX_ELSE3
SOMETHING_XXXXXXXXXXXXXX_ELSE4
using line visual mode (<C-v>) and then issue this command: :'<,'>normal fXct_HELLOWORLD. Then you'll have
SOMETHING_HELLOWORLD_ELSE
SOMETHING_HELLOWORLD_ELSE2
SOMETHING_HELLOWORLD_ELSE3
SOMETHING_HELLOWORLD_ELSE4
This means that it will run the command fXct_HELLOWORLD for each line. Let me explain the command:
fX - moves the cursor until the first X;
ct_ - deletes everything untill _ and puts you in insert mode;
HELLOWORLD - the word which will substitute XXXXXXXXXXXXXX;
One way would be to visually select all the code you want to replace and change it at once
Ctrl+v 3jt_cHELLOWORLD[Esc]
Note: it takes a couple of seconds for all lines to be updated
Another way to be by creating a macro:
record macro:
q10fXct_HELLOWORLD[esc]q
run macro on other lines:
j#1j#1j#1
q1 records a macro on character 1
#1 replays macro
But search and replace is a good alternative for your question
Highlight the four lines in visual mode, then
:'<,'>s/X\+/HELLOWORLD/g
Via this question: How do I use vim registers? I found ^R in command mode will paste from a register.
For example, with XXXX highlighted then yanked into the " register:
:s/^R"/HELLOWORLD/g

Block Comments in a Shell Script

Is there a simple way to comment out a block of code in a shell script?
In bash:
#!/bin/bash
echo before comment
: <<'END'
bla bla
blurfl
END
echo after comment
The ' and ' around the END delimiter are important, otherwise things inside the block like for example $(command) will be parsed and executed.
For an explanation, see this and this question.
There is no block comment on shell script.
Using vi (yes, vi) you can easily comment from line n to m
<ESC>
:10,100s/^/#/
(that reads, from line 10 to 100 substitute line start (^) with a # sign.)
and un comment with
<ESC>
:10,100s/^#//
(that reads, from line 10 to 100 substitute line start (^) followed by # with noting //.)
vi is almost universal anywhere where there is /bin/sh.
Use : ' to open and ' to close.
For example:
: '
This is a
very neat comment
in bash
'
This is from Vegas's example found here
You can use:
if [ 1 -eq 0 ]; then
echo "The code that you want commented out goes here."
echo "This echo statement will not be called."
fi
The following should work for sh,bash, ksh and zsh.
The blocks of code to be commented can be put inside BEGINCOMMENT and ENDCOMMENT:
[ -z $BASH ] || shopt -s expand_aliases
alias BEGINCOMMENT="if [ ]; then"
alias ENDCOMMENT="fi"
BEGINCOMMENT
echo "This line appears in a commented block"
echo "And this one too!"
ENDCOMMENT
echo "This is outside the commented block"
Executing the above code would result in:
This is outside the commented block
In order to uncomment the code blocks thus commented, say
alias BEGINCOMMENT="if : ; then"
instead of
alias BEGINCOMMENT="if [ ]; then"
in the example above.
if you can dodge the single quotes:
__='
blah blah comment.
'
In Vim:
go to first line of block you want to comment
shift-V (enter visual mode), up down highlight lines in block
execute the following on selection :s/^/#/
the command will look like this:
:'<,'>s/^/#
hit enter
e.g.
shift-V
jjj
:s/^/#
<enter>
You could use Vi/Vim's Visual Block mode which is designed for stuff like this:
Ctrl-V
Highlight first element in rows you want commented
Shift-i
#
esc
Uncomment would be:
Ctrl-V
Highlight #'s
d
l
This is vi's interactive way of doing this sort of thing rather than counting or reading line numbers.
Lastly, in Gvim you use ctrl-q to get into Visual Block mode rather than ctrl-v (because that's the shortcut for paste).
In all honesty, why so much overengineering...
I consider it really a bad practice to write active code for generating passive code.
My solution: most editors have block select mode. Just use it to add # to all lines you want to comment out.
What's the big deal...
Notepad example:
To create: Alt - mousedrag down, press #.
To delete: Alt-mousedrag down, shift-right arrow, delete.
A variation on the here-doc trick in the accepted answer by sunny256 is to use the Perl keywords for comments. If your comments are actually some sort of documentation, you can then start using the Perl syntax inside the commented block, which allows you to print it out nicely formatted, convert it to a man-page, etc.
As far as the shell is concerned, you only need to replace 'END' with '=cut'.
echo "before comment"
: <<'=cut'
=pod
=head1 NAME
podtest.sh - Example shell script with embedded POD documentation
etc.
=cut
echo "after comment"
(Found on "Embedding documentation in shell script")
You can put the code to comment inside a function. A good thing about this is you can "uncomment" by calling the function just after the definition.
Unless you plan to "uncomment" by calling the function, the text inside the function does not have to be syntactically correct.
ignored() {
echo this is comment
echo another line of comment
}
Many GUI editors will allow you to select a block of text, and press "{" to automatically put braces around the selected block of code.
Let's combine the best of all of these ideas and suggestions.
alias _CommentBegin_=": <<'_CommentEnd_'"
as has been said, the single quote is very important, in that without them
$(commandName) and ${varName} would get evaluated.
You would use it as:
_CommentBegin_
echo "bash code"
or
none code can be in here
_CommentEnd_
The alias makes the usage more obvious and better looking.
I like a single line open and close:
if [ ]; then ##
...
...
fi; ##
The '##' helps me easily find the start and end to the block comment. I can stick a number after the '##' if I've got a bunch of them. To turn off the comment, I just stick a '1' in the '[ ]'. I also avoid some issues I've had with single-quotes in the commented block.
Another mode is:
If your editor HAS NO BLOCK comment option,
Open a second instance of the editor (for example File=>New File...)
From THE PREVIOUS file you are working on, select ONLY THE PART YOU WANT COMMENT
Copy and paste it in the window of the new temporary file...
Open the Edit menu, select REPLACE and input as string to be replaced '\n'
input as replace string: '\n#'
press the button 'replace ALL'
DONE
it WORKS with ANY editor
In vscode ctrl+K+C (ctrl+K+U to uncomment).

Resources