I have a text file with many lines.
test =
more text more text more text more text
more text more text more text more text
... etc....
more text more text more text more text
more text more text more text more text
1 text
test2 =
more text more text more text more text
more text more text more text more text
3 more text
etc
What I want to do is to move lines up starting with a number
and attach them after the first line found (going backwards) ending with '=\s'
expected output:
test = 1 text
more text more text more text more text
more text more text more text more text
... etc....
more text more text more text more text
more text more text more text more text
test2 = 3 more text
more text more text more text more text
more text more text more text more text
I have no idea how to do this.
Can someone help me?
Using :global, :norm, :move and the possibility to use a search as target for Ex commands:
:g/^\d/m?.*=$|norm kJ
Breakdown:
:g/pattern/command " executes command for every line matching pattern
^\d " pattern for "lines that start with a number"
m?.*=$ " move matched line to right below the first
" line ending with = upward
| " separator between Ex commands
norm " execute normal mode command
kJ " go to line above and join
A macro may help...
/^\d<cr>:.m?=<cr>kJ
short explanation:
/^\d " find line beginning with number
:.m?= " move current line under the previous line with (=)
kJ "move cursor back to the line with (=), and join the next
it is working like:
(it seems that I typed one more ? and the last n in screenshot, but I won't record it again.)
Related
I need to capture part of a text within several other texts and within these several texts I have some that always have the same initial and final word, how can I do that?
I trying make a program to search part of the a text, in the text I have a key initial and a final key.
The text format is this:
my random text this my random text this my random text this my random
text this my random text this MY_START_WORD_KEY my text this my text
this my text this my text this my text this MY_END_WORD_KEY my random text this my random text this my random text this my random text this my random text this MY_START_WORD_KEY my text this my text
this my text this my text this my text this MY_END_WORD_KEY my random text this my random text this my random text this my random text this my random text this
I created this code:
txt = "my_text.txt"
with open(txt, encoding="utf8") as text:
all_text = text.read()
start='START MY KEY WORD '
end='END MY KEY WORD'
result=[]
temp=all_text.split(start)
for part in temp:
if end in part:
result.append(part.split(end)[0])
But that way the initial and final word is lost in my final full text.
I need everything between the initial keyword to the final keyword.
you can try something like
import re
txt = '''my random text this my random text this my random text this my random text this my random text this START_KEY my text this my text this my text this my text this my text this END_KEY my text this my text this my text this my text this my text this my text this my text this
more random START_KEY text END_KEY.'''
START_KEY='START_KEY'
END_KEY='END_KEY'
matches = re.findall(START_KEY+r"\s.*\s"+END_KEY, txt)
the result will be
matches = ['START_KEY my text this my text this my text this my text this my text this END_KEY',
'START_KEY text END_KEY']
Regex can be very useful for things like this,
you can find more about 're' lib here
Assuming you only see one occurrence of the start and end word in the text:
text = ...
start="start"
end="end"
result = text.split(start)[1].split(end)[0].strip()
You can split and select the middle portion.
Try this:
keys = ['start','end']
text = "Everything between key[0] and key[1]+3 is suposed to return as substring. start extracting here and stop at the end. This part should not appear in extracted substring."
start = text.index(keys[0])
end = text.index(keys[1])
print(text[:start], '\n', text[start:end+3], '\n', text[end+3:])
Tô kee START and END words, use a regexp like:
/(START.*END)/gm
To remove the limiting words,nuse the following regexp:
/START(.*)END/gm
I hope it helps.
When a fold is collapsed in vim, all of the nested headings are hidden away so that you can't see what's inside. I'm curious if anyone knows if it's possible or has a solution for foldtext function (or through another method) that can display the sections inside a fold when a fold is collapsed.
I'm looking for something that would display folds more like this:
+ -- 2000 TopSection1 " Fold Level 1
+ --- 500 TopSection1 : ChildSection1 " Fold Level 2
+ ---- 50 TopSection1 : ChildSection1 : BottomSection1 " Fold Level 3
+ --- 100 TopSection1 : ChildSection2 : BottomSection1 " Fold Level 2
+ -- 500 TopSection2 " Fold Level 1
+ --- 25 TopSection2 : ChildSection1 " Fold Level 2
I've been digging around, but have not figured out a method to make this work (or if it's possible). Any suggestions?
the following command gets all folding lines without the body texts in between :
:g/{{{/
It works for this example below that contains multiple nested folds with foldmethod=marker and default ({{{) mark :
Text 1/*{{{*/
some text here
subtext 1.1/*{{{*/
some text here
subsubtext 1.1.1/*{{{*/
some text here/*}}}*/
subsubtext 1.1.2/*{{{*/
some text here/*}}}*//*}}}*/
subtext 1.2/*{{{*/
some text here
subsubtext 1.2.1/*{{{*/
some text here/*}}}*/
subsubtext 1.2.2/*{{{*/
some text here/*}}}*//*}}}*//*}}}*/
Text 2/*{{{*/
some text here
subtext 2.1/*{{{*/
some text here
subsubtext 2.1.1/*{{{*/
some text here/*}}}*/
subsubtext 2.1.2/*{{{*/
some text here/*}}}*//*}}}*/
subtext 2.2/*{{{*/
some text here
subsubtext 2.2.1/*{{{*/
some text here/*}}}*/
subsubtext 2.2.2/*{{{*/
some text here/*}}}*//*}}}*//*}}}*/
After you run the :g/{{{/ command, you get this :
Text 1/*{{{*/
subtext 1.1/*{{{*/
subsubtext 1.1.1/*{{{*/
subsubtext 1.1.2/*{{{*/
subtext 1.2/*{{{*/
subsubtext 1.2.1/*{{{*/
subsubtext 1.2.2/*{{{*/
Text 2/*{{{*/
subtext 2.1/*{{{*/
subsubtext 2.1.1/*{{{*/
subsubtext 2.1.2/*{{{*/
subtext 2.2/*{{{*/
subsubtext 2.2.1/*{{{*/
subsubtext 2.2.2/*{{{*/
If you want to redirect the result to a new buffer, then you can run :
:let #a='' | execute 'g/{{{/y A' | new | setlocal bt=nofile | put! a
It yanks the {{{ pattern to register "a", opens a new buffer and pastes the reg.
You may then need to expand the result with zR if your default is 'collapse folds'.
You will have to play with foldtext but also to parse the content of the section to fetch what you want to display.
I use zr and zm normal commands to open and close another folding level.
I agree that zr will also show text between a folding level and a sub-level ; hence it does not fully address your question.
It's seems that a better way would be to use foldmethod=syntax and then filter all folding lines with a global (g) command based on the regex of the foldmethod syntax.
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
I am creating the SVG text by using the <text> with <tspan> for each line.
The text has many lines and one of them is empty line, some thing like this:
this is text line 1
this is text line 3
the example above is a text with three lines, one of them is empty.
the problem is the SVG text only displays two lines instead of three lines (the first and the end line, without the middle line).
See here: http://jsfiddle.net/svincoll4/DX4Cn/
Anyone have solution about this to make it display three lines?
Note: I am using the Raphael JS to create these text.
By default whitespace is compressed in html and svg so \n\n\n becomes \n. Also if there's no text at all then the middle line is ignored. xml:space="preserve" stops whitespace compression in SVG and and extra space makes the middle line exist.
var $svg = Raphael('container', 400, 400);
var $text = "this is line 1\n \nthis is line 3";
$svg.canvas.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:space","preserve");
$svg.text(50, 100, $text);
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'))