Autohotkey : Clipboard Convert Tabs to Spaces - text

I have a snippet of code I copied into my clipboard. Pasting it out looks like this. Where[tab] is an actual tab indent
[tab]<header id="masthead" class="site-header">
[tab][tab]<h1>
[tab][tab][tab]<h2>
[tab][tab][tab][tab]<h3>
[tab][tab][tab][tab][tab]<h4>;
I want to press an autohotkey to automatically normalize the code snippet. So if there's a [tab] on every line, remove it.
Then convert each [tab] into 2 spaces [**]
<header id="masthead" class="site-header">
**<h1>
****<h2>
******<h3>
********<h4>;
So the general workflow is:
Copy code to clipboard
Press an autohotkey
Paste the newly formatted contents
Pseudocode for autohotkey would look like this
Dig through every clipboard content line by line
If every item shares an equal number of [tab] spaces, remove them entirely
Line by line, convert [tab] to [**] 2 spaces

; convert each tab into 2 spaces:
clipboard =
(
<header id="masthead" class="site-header">
<h1>
<h2>
<h3>
<h4>;
)
clipboard := StrReplace(clipboard, A_Tab, A_Space A_Space)
https://autohotkey.com/docs/commands/StringReplace.htm

okay problem solved I have everything I want now. I took the other source code snippet here on autohotkey forum
F9::
clipboard := StrReplace(clipboard, A_Tab, A_Space A_Space)
position := RegExMatch(clipboard, "\S")
test := RegExReplace(clipboard, "m)^[ ]{" . position - 1 . "}")
clipboard := test
As a reference, need to highlight the full line on code snippet like so
So all I have to do now is:
Copy the full code
Press F9
Paste into my notetaking app (dynalist.io with codesnippet support)

Related

How can I paste to next line and enter insert mode on current line?

I'm brand new to vim. A common pattern I am dealing with looks like this
myFunction :: some code
myFunction = some more code
how could I create a command where after executing I look like this
myFunction
myFunction
and am in insert mode with my cursor on the end of the first 'myFunction' ?
If you are copying the first line to the down then maybe try yy for yanking the whole (first) line, P for pasting the line before the cursor and A to go in insert mode at the end of first line.
And you can use :map to do whole thing at one. Like :map 'l yyPA
I have found an almost perfect solution "using ultisnips plugin", the only thing missing is the cursor position. I am considering an already typed text:
You must select the target lines (use vip in normal mode) and use your defined trigger on ultisnips
snippet trigger "Description" w
`!p
import re
snip.rv = re.sub("(^\w+).*", r"\1", snip.v.text, flags=re.MULTILINE)
`
endsnippet

How can I delete/yank paste in vim and have it indent correctly? (not talking about :paste)

Please note this is NOT related to :paste / :nopaste and the clipboard. I'm talking about copying and pasting entirely within vim (d, y, p).
It is common to copy and paste a block of code from an outer block into an inner block. Unfortunately, the indentation still is at the level of the outer block and I have to indent it afterwards.
What I want to do is to go from:
function foo() {
}
var bar;
var bazz;
to
function foo() {
var bar;
var bazz;
}
In vim what I normally do is:
1) go to the line
2) switch to visual mode
3) highlight the rows
4) dd to delete the lines
5) move the cursor up
6) P to paste
7) enter visual mode
8) highlight the rows
9) >> to indent the lines
I want it to automatically indent to the correct location. It would be a much smoother workflow if I didn't need to re-highlight the rows and then indent them manually. In other words, eliminate steps 7-9.
Anybody know of a way to do this?
You can easily make this a keymap that does auto indenting as part of pasting.
For example,
nnoremap gp p`[v`]=
Breakdown:
p to paste text
`[v`] to selecte Pasted text
= to autoindent selected text
I came across this plugin.
https://github.com/sickill/vim-pasta
Looks like it does the same thing as ronakg mentioned above with some additional functionality.

Append to top and bottom of selected text in vim

So I have the following text (==== delimiters denotes selected text):
This is some text
I'm not interested in.
This is indented text
not important.
=====================
This text portion is
selected.
=====================
Also not important
indented text
Other text i'm not
interested in.
Now I want to create a vim function so that when called, it appends at the top and at the bottom some default text. For example I would like to end with:
This is some text
I'm not interested in.
This is indented text
not important.
THIS TEXT WAS APPENDED
AFTER FUNCTION CALL
This text portion is
selected.
THIS OTHER TEXT WAS
APPENDED AFTER THE SAME
FUNCTION CALL
Also not important
indented text
Other text i'm not
interested in.
Please note that indentation should be preserved (thanks benjifisher)
How can I do this?
This is a little sloppy, but it works:
function! Frame() range
'<put!=\"THIS OTHER TEXT WAS\nAPPENDED AFTER\nFUNCTION CALL\"
'>put=\"THIS OTHER TEXT WAS\nAPPENDED AFTER THE SAME\nFUNCTION CALL\"
endfun
Select your lines in Visual mode, and type
:'<,'>call Frame()
(The range '<,'> is inserted automatically.) There are some advantages to using :execute with a:firstline and a:lastlineas in :help function-range-example, instead of the Visual marks '< and '>, but that gets a little complicated. You could also prefix each command with :silent if you do not care to be told that 3 lines have been added (twice).
Here is a version that copies the indentation from the first and last selected lines, as requested in the updated question. This version uses :call append() instead of :put, which makes it more convenient to use a:firstline and a:lastline; possibly, this will be useful if you ever want to call the function with a range other than the Visual one.
" Add lines at the bottom before adding at the top, since the line numbers
" will change when you add lines.
function! Frame() range
" Define a list of lines and prepend the desired indentation.
let botlines = ['THIS OTHER TEXT WAS', 'APPENDED AFTER THE SAME', 'FUNCTION CALL']
let botspaces = matchstr(getline(a:lastline), '\s*')
let lines = []
for line in botlines
call add(lines, botspaces . line)
endfor
" Now add those lines at the bottom.
call append(a:lastline, lines)
" Now do the same thing at the top.
let toplines = ['THIS OTHER TEXT WAS', 'APPENDED AFTER', 'FUNCTION CALL']
let topspaces = matchstr(getline(a:firstline), '\s*')
let lines = []
for line in toplines
call add(lines, topspaces . line)
endfor
call append(a:firstline - 1, lines)
endfun

Remove new lines inside a div using vim

I have some data like this
<div>
This
is
some text
</div>
and i want to end up with this
<div>
This is some text
</div>
I know I can search and replace for \n, but I want to limit that search for only the lines inside the <div> tag.
I have a very long HTML file with thousands of Divs, no class or ID.
How can I do this with Vim?
Move your cursor into the <div> block, try this:
vitojJ
To join all non-overlapped <div> blocks, try this:
:g/<div>/+1,/<\/div>/-1 join
Start recording a macro (in register d) with qd
Search for an opening DIV tag with /<div (then press return)
Use visual mode to select everything inside the DIV with vit
Change the visual selection so that it doesn't include the line with the opening tag with oj
Join the lines with J
Stop recording with q
Now you can play back the macro as many times as you need to with #d (or, for a fixed number of repetitions you can prefix it with a number, e.g. 20#d)
(This solution assumes that, as in your example, the open and close tags are always on their own lines. Also, if there is only one line of content in the DIV then the closing tag will end up on the same line as the content.)
You can do one of these:
Select the tree lines with V, and use J to put them in the same line.
Put the cursor on the second line and use 3J.
Put your cursor on the second line, and do J two times.
If you are on "This", VjjJ (select whole lines, down twice, join rows with ' ' as separator.)
--
If you want the end result to be <div>This is some text</div>: place cursor anywhere in tag and do vatJ (visual mode, select inclusive, select tag, join rows.)
:g/<div>/norm! jVjjJ
:................... command
g................... global
/<div> ............. search for <div>
norm! .............. in normal mode
j................... down one line 'j',
V .................. visual by line 'V'
jj ................. down more two lines
J .................. upper 'J' join lines
For variable number of lines try
:g/<div>/norm! jV/\/div^MkJ
:............. command
g ............ global
/<div> ....... search div
norm! ....... execute in normal mode
j ............ down one line
V ............ start visual mode
/\/div ....... search div close
^M ........... type <ctrl-v> in linux or <ctrl-k> on windows, after that <enter>
k ............ up one line
J ............ joine all selected lines
On linux to insert <Enter> press <ctrl-v><enter>
On windows try <ctrl-k><enter>

Align to the right in visual block

I would like to know how to align to the right in a visual block without changing the text before and the block.
I used this code till before:
:<C-U>'<,'>s/\%V\(.\{-}\)\(\s\{-}\)\%(\%V\#!\|$\)/\2\1/
However I noted that it doesn't work when after the visual block is only spaces.
(There has to be text after the visual block in order to make above code work)
Is there no way to align text to the right in a visual block whatever is written after the block?
Example:
text before +align text text after
text before align text text after
text before align text text after
text before align text+ text after
What I want to do is select a block of text from + to + (see example above)
and align it to the right. Output must be:
text before align text text after
text before align text text after
text before align text text after
text before align text text after
Above code does the job but it does not work when there is not something written after align text in every line.
In order to solve the issue correctly handling all corner cases, I would use
the following function.
function! RightAlignVisual() range
let lim = [virtcol("'<"), virtcol("'>")]
let [l, r] = [min(lim), max(lim)]
exe "'<,'>" 's/\%'.l.'v.*\%<'.(r+1).'v./\=StrPadLeft(submatch(0),r-l+1)'
endfunction
function! StrPadLeft(s, w)
let s = substitute(a:s, '^\s\+\|\s\+$', '', 'g')
return repeat(' ', a:w - strwidth(s)) . s
endfunction
I use this. Put the cursor before the text which should be aligned to right. Run :Right
How does it work:
v0 Visualy select the text from current position to the beginning of the line
d Delete selected text and put into the buffer
:right Align the text on the right side of the cursor
0 Put cursor to the first column
gv Visualy select same area which we deleted before
p Replace selection with deleted text
command! Right execute "normal v0d\<CR>:right\<CR>0gvp"
:'<,'>s/\%V.*\%V/\=printf("%*s", col("'>")-col("'<"), substitute(submatch(0), '^\s*\|\s*$', '', 'g'))

Resources