How to add "# " to head of the file name put in vim? - vim

I try to use this command to write down my file name when I press the binding key.
:put!=expand('%:t:r')
I want to improve it
Because I only use this command while I am writting markdown.
So I want to add "#" and " " to the head of the file name
I try a lot but didn't works, so how can I achieve.

you can use the "concatenate strings" operator . to prepend '# ' (or whatever string you want) to the expanded filename:
:put = '# ' . expand('%:t:r')

Related

Create a vocabulary notebook [Vim]

I want to use vim to read foreign texts and collect vocabularies quickly. Simply by firing a hotkey, the current word (vocab) and sentence (usage) should be piped to my notebook. This will be done by a vim script (should be simple).
# New words (2019-12-07)
word: "Nullstellensatz"
usage: "A general solution of the ideal membership problem provides an effective Nullstellensatz, at least for the weak form."
time: 2019-12-07T22:19:02-04:00
source: /home/username/Hilbert's-Nullstellensatz.md
word: "disponibles"
usage: "Ces outils sont disponibles pour toute forme de consultation, privée ou publique."
time: 2019-12-07T22:21:49-04:00
source: /home/username/CONFIANCE-DANS-LES-PLATEFORMES.md
So far, I have figured out how to select word and sentence by viw and vis in normal mode, and to pipe selected text to an external file by :'<,'>w!cat >> notebook.md.
remaining problems
I have successfully piped the words and sentences to a file, but they stay in the same line. How can I insert a \n, word: and usage: using vim commands?
How to get the current time, and pipe that into my target file?
How to read the current file name, and pipe that into my target file?
It is way nicer using redir than :w!cat (:help :redir).
function! GrabWord()
normal mz"zyiw"yyis`z
redir >> /path/to/notebook.md " CHANGE PATH
echo 'word: ' . json_encode(#z)
echo 'usage: ' . json_encode(#y)
echo 'time: ' . strftime('%FT%T%z')
echo 'source: ' . json_encode(expand('%:p'))
echo ''
redir END
endfunction
nnoremap <silent> Q :silent call GrabWord()<CR>
I threw in a json_encode so strings including backslashes or double quotes would not break.

VIM: delete strings with the same pattern

I need to find all pairs of strings that have the same pattern.
For example:
another string, that is not interesting
la-di-da-di __pattern__ -di-la-di-la
la-di-da-da-di-la __pattern__ -la-da-li-la
and yet another usual string
So I want to delete strings with __pattern__ inside.
I don't know how to do it just with builtin commands and now I have the function, that doesn't work properly:
function! DelDup(pattern)
echom a:pattern
redir => l:count
execute "normal! :%s/a:pattern//n\<cr>"
redir END
echo l:count
endfunction
Here I try to run ":%s/a:pattern//n" to find the count of occurrences of pattern in the text.
And at the same time I try to put it into the variable "l:count".
Then I tried to echo the count I got, but nothing happens when I try to do it.
So the last my problem in function writing is that I can't write the command execution result to variable.
If you have another solution -- please describe it to me.
Update:
Excuse me for bad description. I want to delete only strings, that has pattern-twins in text.
I'm not sure if I understand your question correctly, but I'm assuming you want to remove all lines where there are at least 2 matches. If that's the case you can use the following command:
:g/\(__pattern__.*\)\{2,}/d
How this works is that it deletes all the lines where there is a match (:g/../d).
The pattern is made up of a group (\(..\)) which needs to be matched at least 2 times (\{2,}). And the pattern has a .* at the end so it matches everything between the matches of the pattern.
There are many ways to count occurrences of a pattern, and I'm quite sure there exist a Q/A on the subject. Let's do it yet another way and chain with the next step. (Yes this is completely obfuscated, but it permits to obtain programmatically the information without the need to parse the localized result of :substitute after redirection.)
" declare a list that contain all matches
let matches = []
" replace each occurrence of the "pattern" with:
" the result of the expression "\=" that can be
" interpreted as the last ([-1]) element of the
" list "matches" returned by the function (add)
" that adds the current match (submatch(0)) to the
" list
:%s/thepattern/\=add(matches, submatch(0))[-1]/gn
" The big caveat of this command is that it modifies
" the current buffer.
" We need something like the following to leave it unmodified:
:g/thepattern/call substitute(getline('.'), 'thepattern', '\=add(counter, submatch(0))[-1]', 'g')
" Note however that this flavour won't work with multi-lines patterns
" Now you can test the number of matches or do anything fancy with it
if len(matches) > 1
" replaces matches with nothing
:%s/thepattern//g
endif
Only if you want to define this as a function you'll need to play with:
exe 'normal :%s/'.escape(a:pattern, '/\').'/replacement..../flags....'

How to replace the a specific character in sed command which have predefine meaning?

I have this text
" File: 'space folder' "
I want to replace this with only this
" space folder "
using sed or awk?
But when i try to do with it using sed it's not taking the command!
Does anyone have solution for this.
If I get your intent correctly, you need all text between single quotes; you can use this:
$ sed -r "s/^.*'([^']*)'.*$/\"\1\"/g" <<< "\" File: 'space folder' \""
"space folder"
$
Edit1: explanation
command <<< string => <<< indicates here string that is you pass a string to the command.
Our final string is this:
$ echo -e "\" File: 'space folder' \""
" File: 'space folder' "
$
since our string contains single quotes we use double quotes for sed command:
-r switch enables extended regular expression
"s/^.*'([^']*)'.*$/\"\1\"/g"
the above command substitutes the whole line with text present between single quotes.
Regular expression breakdown:
^ matches start of line
.* matches 0 or more characters
' matches a literal single quote
([^']*) matches 0 or more characters that are not single quote
and remembers it as a captured group with backreference number \1
' matches literal single quote
.* matches 0 or more chars
$ matches end of line

how to save complex grep output in gvim

In my gvim file I have something like below
Before line
name1/name2/name3/
next line
name2/name3 is the pattern of my interest.
I want to delete the line containing the pattern and the next line of matched pattern.
I want to save the both lines in other file. I am able to search and delete the lines using global
:g/name2\/name3/,+1d
but not able to redirect it into other file.
How can I save the grep output to some other file.
You can use write >> f to append to the file f (or write! >> f if you want to create f if it doesn't exist).
:g/name2\/name3/,+ write! >> f | ,+d
Alternatively you could use :redir >> (which avoids repeating the ,+ range) :
:g/name2\/name3/,+1d | redir! >> f | silent echon #" | redir END
Maybe there is a better solution, but after you deleted the lines they are in the " register (you can check with :reg).
Just open a new buffer with :new, paste the register with p and save the file with :w myfilename

VIM How to insert output of a shell command at a different place in the file

I have come up with a perl script that outputs a template for documenting functions and structures given the definition of a function/struct from my C code.
To use it , i visually select the definition of the struct, yank and paste it right above the original definition, and invoke the script on this pasted struct. It replaces it with document for that struct.
Now is there a way that will avoid that yank paste? I am looking for a way to invoke a shell command but the output from that should be pasted somewhere else in the file, not necessarily on top of it.
IOW
:'a,'b!perl ~/bin/document.pl
replaces text between mark a and markb, I want to add the output of document.pl above mark a.
One possible solution would be to modify the perl script in a way that it also outputs its input at the end. Then you would end up with the desired result.
If you have zsh as your shell, you can use co-process:
'a,'b!coproc perl ~/bin/document.pl ; tee >&p | cat <&p
To get output before your text (this command puts it after), you should use a slightly more complex command:
'a,'b!coproc perl ~/bin/document.pl ; tee >&p | cat <(<&p) -
System-independent solution, using vim and temporary buffer:
'a,'byank a | new | 0put a | $d | execute "%!perl ~/bin/document.pl" | %d a | bw! | 'a-1put a
Try with something like this:
function! MyFunc() range
" Preserve the register.
let old_reg = #a
exec a:firstline.','.a:lastline.'yank a'
" Change to do what you need with register a.
" Insert output before a:firstline
exec (a:firstline - 1).'read !your magic with '.#a
" Restore the register
let #a = old_reg
endfunction
" :2,5MyOwn will process lines from 2 to 5 and insert the output before line 2
command! -bar -range -nargs=? MyOwn <line1>,<line2>call MyFunc()

Resources