vim - execute range of lines as shell, output in same buffer - shell

Let's say I'm in a buffer like this, on line 4, I want to run line 1 to 2 and have the output in the same buffer on line 4 (where cursor is):
echo "Testing"
echo "more testing"
# and here I want the output from running lines 1 to 2
...I know I can do 1,2w !sh to run lines 1 and 2 and have the output shown in whatever that temporary buffer is. But, how do I get into my actual buffer for later editing?
(And the same thing to work with visual mode selected text, not just with line ranges given by numbers.)

You were using :w !... (:help :w_c), but you probably want :! (:help :!):
gg - go to top
Vj - select the two lines
y - yank into a buffer
4gg - go to 4th line
V - select it
p - paste over it
gv - reselect the pasted range
:!sh<CR> - execute in shell and replace
or, trusting ex commands more,
:4d
:1,2y
:3pu
:4,5!sh
NB: !sh is in most cases equivalent to !, as ! will call your default shell.

Yey! Found it. In case anyone else needs this exact same hack on a virgin/foreign vim (plugin-less or someone else's server/config):
:1,2r !sh %
(yeah, output goes after commands, or technically the commands are replaced with their echo but whatever, not at cursor position, but good enough for me to replicate my Sublime + SublimeCommand workflow in vim :) )

Related

Move cursor position in bash at specific column

I want to move the bash cursor in an echo command on a specific column, but without changing the line. What I have so far is:
this.echo('NONE found on ' + accountName + '(' + accountPos + ')' + '\033[30f !!!');
I want the 30 to be the column number, but the line to stay the same, but for a reason or another, the above just thinks my line number is 0, hence it resets the line to that value.
Found the answer to my own question, by moving the cursor at the beginning of line and then move it forward by 30 columns, as in this example:
\033[50D\033[30C My Text Goes Here
There's more than one way, but the simplest would be HPA (refer to XTerm Control Sequences):
CSI Pm ` Character Position Absolute [column] (default = [row,1])
(HPA).
For example
printf '\033[30`%s\n' "My Text Goes Here"
Further reading: ECMA-48:
Control Functions for Coded Character Sets
Below are instructions on how to move your cursor within a bash script or determine the current location of your cursor within a bash script ( or any text file ) using the vi text editor from a bash shell ( i.e. terminal ).
First, you will want to open the bash script ( or any text file ) using the vi editor.
vi bashscript.sh
If you want to move the cursor to line 10 and column 2 within a bash script using the vi editor run the below command ( note you type ':' to enter a command ).
:cal cursor(10, 2)
If you want to see your current row and column within a bash script using the vi editor run the below command.
:echo "Row = " line('.') ", Col = " virtcol('.')

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 to move right or left by 'x' characters in Bash?

In bash sometimes I have very long commands where I need to edit some words. Right now I use End/Home to move end/start of the command, but what if I have to move say x characters in a line?
I need something like xb/xw of VI, but instead of words I need to move characters.
What about ditching emacs mode and switching to vi mode editing?
set -o vi
and you have all the power of vi-like command line editing, like 3l to go left three characters and 5B to go back 5 words. The Pos 1 key then becomes 0 and End becomes $.
In emacs mode, you can use Meta3Controlb to move back 3 characters, and Meta3Controlf to move forward 3 characters. For multi digit counts, you need to precede each digit with the Meta key (e.g., to move 10 characters back, Meta1Meta0Controlb).
Meta is usually the Alt key, but may be the Esc key instead (on Mac OS X, for instance).
(Yes, vi-command mode makes it easier.)
There is a command, universal-argument, that allows you to type all the digits at once, but it is unbound by default. Bind it with, say,
bind "\C-a":universal-argument
then typing Control-a will enter you into an "argument" mode, prefixing the current line (arg: 4), and allowing you to type digits to change the argument used by the next non-digit character you type. (See universal-argument in the bash man page for the full details.)
You could use the command as below
Command:
cp some_file1 some_file2 some_file3 /root/Desktop
After executing the command do the following
^some_file2^some_file4
and it will execute the command
cp some_file1 some_file4 some_file3 /root/Desktop ;
What happened is the some_file2 is replaced by some_file4 and the command is executed

Using pipe symbol and "print" in Windows

I am trying to make a shell script work in Windows. Sorry but I'm not very experienced in Windows (or even that much in shell to be honest). The script works well except for this one line:
print "9\n0\n1\n5\n0\n0\n\n" | /usr/ts23/mm_util
The mm_util is an interactive utility that takes numbers as input. It chooses selection 9 first, then 0, then 1, etc. I've changed the path to use the utility, which has an identical interface in Windows but the output is just the first screen. The "9" input isn't entered, and because of this the output (that is parsed) is incorrect. How can I change this so that the "9" is entered on the first screen?
Here is a method that does not require a file. It works on the command line:
(for %N in (9 0 1 5 0 0 "") do #echo(%~N)|c:\Users\ts23\mm_util
The "" is to get an empty line in the output, as you had in your original question. Your answer does not have the blank line.
The %~N notation strips enclosing quotes from the value.
The echo( is non-intuitive syntax that can reliably print a blank line, in case %~N expands to nothing.
Don't forget to double the percents if you put the code in a batch script.
Try to put that nine-linebreak-zero-stuff in a text file, and then execute print textfile.txt | /usr/ts23/mm_util
And bear in mind that Windows uses the pre-UNIX convention that the linebreak is CR LF, not just LF.
The way I got the output I wanted was by using this:
C:\Users\ts23\mm_util < test.txt
And then just put the following inside test.txt
9
0
1
5
0
0
The output I got was what I needed, hopefully this will help someone trying to do something like this in the future.

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

Resources