Vim how to add key binding that accepts input - c++

I'm pretty new to vim but I'm trying to create some C++ IDE.
I'm used to ctrl f (or ctrl-shift-f) to help me find in files.. so I saw a plugin I liked called pss.
I'd like to replace ctrl-f with something that would accept input but still add parameters of it's own(*.cpp for example)..
I was thinking of something like:
how can I do it correctly?
noremap <C-f>:Pss $1 *.cpp

Since you have editing capabilities in the command-line, a commonly used approach just builds an incomplete mapping. You can position the cursor in the edit location, like this:
:noremap <C-f> :Pss *.cpp<Left><Left><Left><Left><Left><Left>
After triggering the mapping (via <C-f>), you can insert the search pattern, and then trigger the search via <CR>.
Alternative
You can query for input via the input() function; its result can be inserted into the command-line via :execute:
:noremap <C-f> :execute 'Pss' input('Pattern: ') '*.cpp'<CR>

The default search hot-key is faster than the "Ctrl-F", you may type "/" in the normal mode, and continue input with your keywords. Once you need to search in many files, grep is your friend.

Related

vim abbreviations and regular expressions

In vim, is it possible to use regular expressions in abbreviations? For example, something like
:iab \([0-9]\{-}\)nm \\SI{\1}{\\nano\\meter}
would would expand every instance of, say, '50nm' to '\SI{50}{\nano\meter}'.
Your best bet is to write a little helper function to yourself. Tapping into omni completion or the user defined completion (C-x C-u, see :help 'cfu') is a good choice. I sketched a regular function to imap on a key:
function! ExpandNanometers()
let items = matchlist(expand('<cword>'), '\v(\d+)nm')
if len(items) == 0
return
endif
let modified = '\SI{' . items[1] . '}{\nano\meter}'
exec "normal! ciw" . modified
endf
imap <C-l> <C-o>:call ExpandNanometers()<CR>
Not the best code, perhaps. Bound on insert-mode C-l, it will replace words such as 50nm to the desired if the cursor is on the word or directly after it.
I wanted to add this as a comment to the previous answer, but apparently I can't until 50 rep. I also know this is wayyy too late, but for reference purposes:
If key mappings are acceptable (going by the prev. answer), surely something like
imap <silent> <leader>obscure-key-of-choice <Esc>:%s/\v(\d+)nm/\\SI{\1}{\\nano\\meter}/g<CR>``i
(i.e. global substitute on the whole file with the desired patterns)
would be easier to maintain? I like to avoid vimscript for readability/maintenance of the .vimrc! Obviously you replace obscure-key-of-choice by your obscure key of choice. You only have to do it once after having typed all the text anyway, so better save the other keys for more conventionally useful bindings!
The shortcut replaces something like
50nm blabla 73nm your-interesting-science-here 89nm
... some new lines...
we love nanometers nm! 34nm and finally 18nm
with something like
\SI{50}{\nano\meter} blabla \SI{73}{\nano\meter} your-interesting-science-here \SI{89}{\nano\meter}
... some new lines...
we love nanometers nm! \SI{34}{\nano\meter} and finally \SI{18}{\nano\meter}

Show all matching grep results in new tab in Vim

I am attempting to map a hotkey to do the following in Vim:
Match the current c-word currently marked by the cursor
Generate a list of all found occurrences in current project
Open a new tab showing the results
So, one example I have that uses CTAGS opens the declaration of a variable/function in a new tab like so:
map <C-\> :split<CR>:exec("tag ".expand("<cword>"))<CR>
When it hit CTRL-\, a new tab is opened with the declaration of the variable/function the cursor is on.
The command I am trying to map is shown below:
:lvim /\<\(text_i_want_to_find\)\>/gj *.c
:lw
When I run this command, a new tab is opened showing a list of all .c files containing the text text_i_want_to_find. I need to modify this to do two things different from what it does now:
Search all files with extensions of .c, .h, .cpp, .mk, instead of just .c, and also search files named "Makefile"
Search for the c-word under the cursor like the CTRL-\ mapping I have shown above, as opposed to having to manually type in the text text_i_want_to_find
Here is the code in my .vimrc file for the mapping. I'm not entirely sure if CTRL-/ can be mapped at all, so there's one more problem for me to solve.
map <C-/> :split<CR>:lvim /\<\(.expand("<cword>")\)\>/gj *.c *.h *.cpp *.mk Makefile
Does anyone have any tips on fixing this Vim mapping?
EDIT:
After reviewing the answers provided to me, here's the final version of my code:
command! -nargs=1 SearchAll execute " grep -srnw --binary-files=without-match --exclude={*~,tags} --exclude-dir=.svn . -e " . expand("<args>") . " " <bar> cwindow
map <C-g> :SearchAll <cword><CR>
I mapped it to CTRL+g. I can also invoke it like so as a colon command:
:SearchAll my_text_to_search_for
Hope this helps others as well!
Of course, it does not work: you forgot :execute, :lvimgrep command on its own does not accept expressions, so you are searching for expand("<cword>") that is not followed by a keyword character (\>) and preceded by any character that does not follow keyword character (\<.). \( and \) are useless here. Other notes:
Don’t use map: you need neither this mapping working in visual and operator-pending modes nor ability to use other mappings.
Some patterns can be merged: *.[ch] *.cpp *.mk Makefile or even *.{[ch],cpp,mk} Makefile.
<C-\> can be mapped, but not <C-/> (I hope only currently, but no real work on fixing it is done): \ is 0x5C and <C-\> is 0x5C-0x40=0x1C. But / is 0x2F and 0x2F-0x40<0. On my system pressing <C-/> in terminal transforms into <C-_>, so does <C-->.
:split command does not open a new tab, it opens a new window. Prepend it with :tab to do this.
:lvimgrep is not going to show you the results. It is not either going to jump to the first result unless you remove the j flag.
You forgot final <CR> as well as :lw<CR>. I use :lopen below, in this context they produce just the same result.
You forgot <C-u> after first : or <C-\><C-n> before: it is needed to discard count.
You don’t really need :execute in either of your mappings because there is <C-r>=expand("cword")<CR>, or a default shortcut <C-r><C-w>.
Don’t write :exec(str): it is confusing because :execute is not a function and this syntax encourages others to think it is. Use :execute str.
Thus the final mapping is:
nnoremap <C-\> :<C-u>tab split \| lvimgrep /\V\<<C-r><C-w>\>/gj *.{[ch],cpp,mk} Makefile \| lopen<CR>
. Replace it with
nnoremap <C-\> :<C-u>lvimgrep /\V\<<C-r><C-w>\>/gj *.{[ch],cpp,mk} Makefile \| tab lopen<CR>
if you don’t want to see the current file in a newly opened tab.
Both mappings assume you have neither / nor \ in 'iskeyword' option, if you do replace <C-r><C-w> with <C-r>=escape(expand('<cword>'), '/\')<CR>.

How to get the list of all installed color schemes in Vim?

Is there a way to get a list of all installed color schemes in Vim? That would make very easy to select one without looking at the .vim directory.
Type
:colorscheme then Space followed by TAB.
or as Peter said,
:colorscheme then Space followed by CTRLd
The short version of the command is :colo so you can use it in the two previous commands, instead of using the "long form".
Just for convenient reference as I see that there are a lot of people searching for this topic and are too laz... sorry, busy, to check for themselves (including me). Here is a list of the default set of colour schemes for Vim 7.4:
blue.vim
darkblue.vim,
delek.vim
desert.vim
elflord.vim
evening.vim
industry.vim
koehler.vim
morning.vim
murphy.vim
pablo.vim
peachpuff.vim
ron.vim
shine.vim
slate.vim
torte.vim
zellner.vim
You can see the list of color schemes under /usr/share/vim/vimNN/colors (with NN being the version, e.g. vim74 for vim 7.4).
This is explained here.
On the linux servers I use via ssh, TAB prints ^I and CTRLd prints ^D.
If you are willing to install a plugin, I recommend https://github.com/vim-scripts/CycleColor.
to cycle through all installed colorschemes. Nice way to easily choose a colorscheme.
Looking at my system's menu.vim (look for 'Color Scheme submenu') and #chappar's answer, I came up with the following function:
" Returns the list of available color schemes
function! GetColorSchemes()
return uniq(sort(map(
\ globpath(&runtimepath, "colors/*.vim", 0, 1),
\ 'fnamemodify(v:val, ":t:r")'
\)))
endfunction
It does the following:
Gets the list of available color scheme scripts under all runtime
paths (globpath, runtimepath)
Maps the script paths to their base names (strips parent dirs and
extension) (map, fnamemodify)
Sorts and removes duplicates (uniq, sort)
Then to use the function I do something like this:
let s:schemes = GetColorSchemes()
if index(s:schemes, 'solarized') >= 0
colorscheme solarized
elseif index(s:schemes, 'darkblue') >= 0
colorscheme darkblue
endif
Which means I prefer the 'solarized' and then the 'darkblue' schemes; if none of them is available, do nothing.
Here is a small function I wrote to try all the colorschemes in $VIMRUNTIME/colors directory.
Add the below function to your vimrc, then open your source file and call the function from command.
function! DisplayColorSchemes()
let currDir = getcwd()
exec "cd $VIMRUNTIME/colors"
for myCol in split(glob("*"), '\n')
if myCol =~ '\.vim'
let mycol = substitute(myCol, '\.vim', '', '')
exec "colorscheme " . mycol
exec "redraw!"
echo "colorscheme = ". myCol
sleep 2
endif
endfor
exec "cd " . currDir
endfunction
If you have your vim compiled with +menu, you can follow menus with the :help of console-menu. From there, you can navigate to Edit.Color\ Scheme to get the same list as with in gvim.
Other method is to use a cool script ScrollColors that previews the colorschemes while you scroll the schemes with j/k.
i know i am late for this answer but the correct answer seems to be
See :help getcompletion():
:echo getcompletion('', 'color')
which you can assign to a variable:
:let foo = getcompletion('', 'color')
or use in an expression register:
:put=getcompletion('', 'color')
This is not my answer, this solution is provided by u/romainl in this post on reddit.
A great solution, and my thanks to your contributors. For years I've been struggling with a totally crappy color scheme -- using SSH under Windows Vista to a Redhat system, terminal type xterm.
The editor would come up with a black background and weird colors for various keywords.
Worse -- that weird color scheme sticks in the xterm terminal after leaving Vim.
Really confusing.
Also, Backspace failed during an insert mode, which was nasty to remember -- though Delete did the same thing.
The cure --
In the SSH monitor, select Edit/Settings.
a. Choose Profile Settings/Colors
b. check 'enable ANSI colors'
c. The standard Text colors are probably OK
Add these lines to $HOME/.vimrc:
colorscheme default
if &term == "xterm"
set t_kb=^H
fixdel
endif
NOTE: the ^H MUST be typed as ctrl-V ctrl-H. Seems peculiar, but this seems to work.
Try
set wildmenu
set wildmode=list:full
set wildcharm=<C-z>
let mapleader=','
nnoremap <leader>c :colorscheme <C-z><S-Tab>
in your ~/.vimrc.
The first two lines make possible matches appear as lists. You can use either or both.
The fourth line makes leader , instead of the default \.
The last line allows you to simply type ,c to get a list and a prompt to change your colorscheme.
The third line effectively allows for Tabs to appear in key maps.
(Of course, all of these strategies I've learned from the internet, and mostly SO, very recently.)
Another simpler way is while you are editing a file - tabe ~/.vim/colors/ ENTER
Will open all the themes in a new tab within vim window.
You may come back to the file you were editing using - CTRL + W + W ENTER
Note: Above will work ONLY IF YOU HAVE a .vim/colors directory within your home directory for current $USER
(I have 70+ themes)
[user#host ~]$ ls -l ~/.vim/colors | wc -l
72

To comment out matches in Vim - independent on comment leader?

I want to comment out lines in some code I have. I have different kinds of codes, and they use different comment leaders. E.g. in latex: '%', in Fortran 90: '!' and in python: '#'. I want to do a substitute command that looks something like this:
:g/<search-string>/s/^/<add-comment-leader-here>/
If this is possible, I could also make a command in Vim that automatically commented out the selected text. Something like this:
vmap <z> :'<,'>s/^/<add-comment-leader-here>/
Any ideas are welcome! :)
If you haven't seen it already, you may be interested in the NERD Commenter Vim plugin.
Check out Enhanced Commentify: I think this does what you want: it determines the comment leader based on the file type.
If you want to do it yourself, the easiest way would be to define a mapping that uses exec to build a command and include a variable that is set in your ~/.vim/after/ftplugin/c.vim and other ftplugin files. Alternatively, just add the same mapping (with a different leader) to each ftplugin file.

Opening a file on unix using c++

I am trying to open a file in c++ and the server the progam in running on is based on tux.
string filename = "../dir/input.txt"; works but
string filename = "~jal/dir1/dir/input.txt"; fails
Is there any way to open a file in c++ when the filename provided is in the second format?
The ~jal expansion is performed by the shell (bash/csh/whatever), not by the system itself, so your program is trying to look into the folder named ~jal/, not /home/jal/.
I'm not a C coder, but getpwent() may be what you need.
You could scan the string, replacing ~user by the appropriate directory.
The POSIX function wordexp does that, and a few other things
variable substitution, like you can use $HOME
optional command substitution, like $(echo foo) (can be disabled)
arithmetic expansion, like $((3+4))
word splitting, like splitting ~/a ~/b into two words
wildcard expansion, like *.cpp
and quoting, like "~/a ~/b" remains that
Here is a ready piece of code, that performs this task:
How do I expand `~' in a filename like the shell does?