Trying to write a Vim function / command? - vim

I'm using Janus (isn't pivotal to understand the question though). Basically what they do, is rewrite :e to be :Edit to work with NERDTree, but NERDTree doesn't support force opening a file (e.g. e!). So I had written something that rewrites :Edit! to :e!, but I like the benefits of using just :Edit!, so I'm trying to spoof if as if it was already built in. This is what I came up with:
ca Edit! e! <bar> Edit
The only problem, is that you can't do that for files that haven't been saved at least once. But I know doing
ca Edit! bd! <bar> Edit
will work: it will close the unsaved buffer and keep moving like nothing happened. All I need to do is write logic that will use the correct command in the right scenario all the time. Preferably the logic doesn't run on every page: only when I actually run the command should it attempt to figure it out. Any ideas?
Edit: I tried asking the #vim channel (gave me tons of help)... they said using expand("%") and checking to see if it exists might help my case? Don't know, just providing as much detail as I can.

Try this. Define a function like this:
function! CommandAbbrForEdit()
if &modified
return 'bd! | Edit'
endif
return 'e! | Edit'
endfunction
Then define your abbreviation like this:
cabbrev <expr> Edit! CommandAbbrForEdit()

Related

Write this in VimScript : "If Lexplore opened a file(anyfile) then close Lexplore"

I want to:
Automaticaly close Lexpore after opening a file for better experience but I don't know vim script.
It shouldn't be hard, I suppose.
I will appreciate any comment!
I'm now learning vim script and trying to do it.
here is where I've got by now:
:autocmd <Lexplore> * :<Lexplore-exit>
or
if <command-mode> == "Lexplore *.*"
excute \\close last buffer. (because now I am in new buffer)
I just need to know how to say "RUN" / "RUNED" in script
then i use regex for anyfile and i need to say "CLOSE".
The truth is
I'm actually Hopeless! :)))))))))))))
There are other avenues to try before going full-on with VimScript. In this case, a simple mapping would probably be enough.
Basically, the right-hand side of a mapping is just a macro, a sequence of commands that you would type yourself, which makes mappings a very good and approchable way to discover Vim automation.
Assuming a simple layout, with only one window, how do you do what you describe manually?
You do :Lexplore and browse around.
In the Netrw window, you press <CR> to open the file.
Then you go back to the previous window (the Netrw window) with <C-w>p.
You close the window with <C-w>q.
Steps 2-4 above are easy to turn into a mapping (<key> is a placeholder, use what you want):
nmap <key> <CR><C-w>p<C-w>q
But that mapping will be available everywhere, which may not be a good idea. Enters the notion of filetype plugins:
Create these directories if they don't already exist:
~/.vim/after/ftplugin/ (Unix-like systems)
%userprofile%\vimfiles\after\ftplugin\ (Windows)
Create a netrw.vim file in the directory above:
~/.vim/after/ftplugin/netrw.vim (Unix-like systems)
%userprofile%\vimfiles\after\ftplugin\netrw.vim (Windows)
Put the mapping above in that file:
nmap <buffer> <key> <CR><C-w>p<C-w>q
The <buffer> tells Vim to only define that mapping in Netrw.
This is the simplest approach, which may or may not work for you.
A few notes regarding your comments…
Buffer numbers are implementation detail. They don't matter at all in your day-to-day work so you shouldn't think too much about them. Buffer names are far more useful and much easier to think about.
The "sidebar file explorer" UX pattern is a familiar one that newcomers like to transfer from their previous editor but it necessitates a lot of fighting against Vim itself to "work". Netrw's take on the pattern is different, yes, and it might take time to adjust to, but it fits much better within the overall experience. Hint: give up on :Lexplore. :Explore, :Sexplore, :Vexplore, and :Texplore are much more useful.
As you learn more, you will soon discover that file explorers, whatever UX pattern they follow, are not that useful to begin with.
Netrw already has a mapping for opening a file in a new tab page: :help netrw-t.

Configure vim to add module declaration for haskell files

When I edit a new Haskell file e.g. "xyz.hs", I'd like vim to automatically add
module Xyz where
at the first line. How can it be configured?
You could do something like
au BufNewFile *.hs call WriteHaskellModuleHeader(expand('%:t:r'))
function! WriteHaskellModuleHeader(fname)
execute "normal imodule " . a:fname . " where\n"
endfunction
in your .vimrc for starters; But of course that breaks the moment you use hierarchical modules (in which case a general vimscript only solution wouldn't work anymore, you'd probably have to invoke cabal or something to find your source roots, and the whole thing would probably get fairly messy very quickly).
Opinion: It doesn't seem to me like something particularly worthwhile, it's not a lot of text to write and you don't write it often.
You can use a snippet engine like Ultisnips together with vim-snippets you can trigger the keyword module to get the desired result.
See https://github.com/honza/vim-snippets/blob/master/snippets/haskell.snippets#L43 for the line responsible for this.
Edit:
For emacs one choice would be yasnippets: and the module keyword is supported in
yasnippet-snippets

Show comments for specific mappings in .vimrc

I know that I can use :nmap, :vmap, :imap commands to display all the mapping for those 3 modes. However, I would like to display comments that I have for a single mapping.
So suppose I have the following entry in my vimrc:
" Execute current line in bash
nmap <F9> :exec '!'.getline('.')<CR>
This could also look like this:
nmap <F9> :exec '!'.getline('.')<CR> " Execute current line in bash
I would like to have a command that for this mapping that would look something like this:
<F9> Execute current line in bash
As this probably can only be done using custom function, where do I start? How do I parse .vimrc to strip only key mappings and their corresponding comments (I have only done some very basic Vim scripts)?
Do I understand correctly from :help map-comments that I should avoid inline comments in .vimrc?
It's very hard to "embed" comments into a mapping without affecting its functionality. And this would only help with our own mappings, not the ones from plugins.
Rather, I'd suggest to learn from (well-written) plugins, which provide :help targets for their (default) key mappings. So, to document your mapping(s), create a help file ~/.vim/doc/mymappings.txt with:
*<F9>*
<F9> Execute current line in bash
After :helptags ~/.vim/doc, you will be able to look up the comments via :h <F9>. By using the help file, you can use syntax highlighting, longer multi-line comments, and even examples, so I think that'a better and more straightforward solution.
Personally, I wouldn't have much use for such a feature for two reasons: the first one, is that I always have a vim session with a note taking buffer that contains all the tips/commands not yet in my muscle memory. Secondly, you can list all the maps using :map, and it's always a great exercise for your brain in learning vim to literally read vim commands.
That being said…
As this probably can only be done using custom function, where do I start?
…well I guess you could imagine using a function with a prototype such as:
AddMap(op, key, cmd, comment)
used like:
call AddMap("nmap", "<F9>", ":exec '!'.getline('.')<CR>", "Execute current line in shell")
which implementation would add key and comment to an array, so that you could list the array to get your own mappings declared. Using a function like ListMap().
let map_list = []
function! AddMap(op, key, cmd, comment)
" add to map list
insert(map_list, [op, key, comment])
" execute map assign
exec op.' '.key.' '.cmd
endfunction
function! ListMap()
for it in map_list
echo it[0] . '\t' . it[1] . '\t' . it[2]
endfor
endfunction
Of course, one could elaborate on the ListMap() function implementation to generate a more "proper" help file that you could open in a buffer. But that's an idea of how you could do an implementation for a feature close to what you're looking for.
N.B.: this snippet is mostly an idea of how I'd tackle this problem, and it's a one shot write that I did not actually try.
How do I parse .vimrc to strip only key mappings and their corresponding comments (I have only done some very basic Vim scripts)?
I don't think that would be a good solution, I think the better way to achieve your goal is my suggestion. Simpler and more explicit, though it won't show off all mappings. But you don't have all your mappings in your .vimrc.
Do I understand correctly from :help map-comments that I should avoid inline comments in .vimrc?
To be more precise you shall not use inline comments after maps, because they will be interpreted part of the mapping.
how to get mapping created by plugins?
Besides, using :map, you just don't. You look at the sources/documenation of your plugins and find out about them. There's no such thing as a reverse lookup from runtime to declaration point.

Auto fill the new file with default content - vi [duplicate]

This is really a newbie question - but basically, how do I enable a template for certain filetypes.
Basically, I just want the template to insert a header of sorts, that is with some functions that I find useful, and libraries loaded etc.
I interpret
:help template
the way that I should place this in my vimrc
au BufNewFile,BufRead ~/.vim/skeleton.R
Running a R script then shows that something could happen, but apparently does not:
--- Auto-Commands ---
This may be because a template consists of commands (and there are no such in skeleton.R) - and in this case I just want it to insert a text header (which skelton.R consist of).
Sorry if this question is mind boggeling stupid ;-/
The command that you've suggested is not going to work: what this will do is run no Vim command whenever you open ~/.vim/skeleton.R
A crude way of achieving what you want would be to use:
:au BufNewFile *.R r ~/.vim/skeleton.R
This will read (:r) your file whenever a new *.R file is created. You want to avoid having BufRead in the autocmd, or it will read the skeleton file into your working file every time you open the file!
There are many plugins that add a lot more control to this process. Being the author and therefore completely biased, I'd recommend this one, but there are plenty of others listed here.
Shameless plug:
They all work in a relatively similar way, but to explain my script:
You install the plugin as described on the linked page and then create some templates in ~/.vim/templates. These templates should have the same extension as the 'target' file, so if it's a template for .R files, call it something like skeleton.R. In your .vimrc, add something like this:
let g:file_template_default = {}
let g:file_template_default['R'] = 'skeleton'
Then create your new .R file (with a filename, so save it if it's new) and enter:
:LoadFileTemplate
You can also skip the .vimrc editing and just do:
:LoadFileTemplate skeleton
See the website for more details.
Assume that your skeletons are in your ~/.vim/templates/ directory, you can put this
snippet in your vimrc file.
augroup templates
au!
" read in templates files
autocmd BufNewFile *.* silent! execute '0r ~/.vim/templates/skeleton.'.expand("<afile>:e")
augroup END
Some explanation,
BufNewFile . = each time we edit a new file
silent! execute = execute silently, no error messages if failed
0r = read file and insert content at top (0) in the new file
expand(":e") = get extension of current filename
see also http://vim.wikia.com/wiki/Use_eval_to_create_dynamic_templates
*fixed missing dot in file path
Create a templates subdirectory in your ~/.vim folder
$ mkdir -p ~/.vim/templates
Create a new file in subdirectory called R.skeleton and put in the header and/or other stuff you want to automagically load upon creating a new ".R " file.
$ vim ~/.vim/templates/R.skeleton
Then, add the following to your ~/.vimrc file, which may have been suggested in a way by "guest"
autocmd BufNewFile * silent! 0r $HOME/.vim/templates/%:e.skeleton
Have a look at my github repository for some more details and other options.
It's just a trick I used to use .
It's cheap but If you ain't know nothing about vim and it's commands it's easy to handle.
make a directory like this :
~/.vim/templates/barney.cpp
and as you konw barney.cpp should be your template code .
then add a function like ForUncleBarney() to end of your .vimrc file located in ~/.vimrc
it should be like
function ForBarneyStinson()
:read ~/.vim/templates/barney.cpp
endfunction
then just use this command in vim
:call ForBarneyStinson()
then you see your template
as an example I already have two templates for .cpp files
:call ForBarney()
:call ACM()
sorry said too much,
Coding's awesome ! :)
Also take a look at https://github.com/aperezdc/vim-template.git.
I use it and have contributed some patches to it and would argue its relatively full featured.
What about using the snipmate plugin? See here
There exist many template-file expanders -- you'll also find there explanations on how to implement a rudimentary template-file expander.
For my part, I'm maintaining the fork of muTemplate. For a simple start, just drop a {ft}.template file into {rtp}/template/. If you want to use any (viml) variable or expression, just do. You can even put vim code (and now even functions) into the template-file if you wish. Several smart decisions are already implemented for C++ and vim files.

Making JavaSciptLint more configurable

I am using mvim with plugin JavaScriptLint. It works great.
However sometimes I work on jQuery or other JavaScript libraries and every single time I save the file, I get tons of warning and cursor moves to the very first warning.
What I would like to have is some way to turn this feature On or off. Something like
:set enableJavaScriptLint
:set disableJavaSCriptLint
My vimrc file is here. And the plugin is here . Notce at line number 14 the plugin autodetects if jsl command is present then it gets enabled. I guess I need to write some function to enable or disable that call.
Any help is appreciated.
Not exactly what you have in mind, but
you can remove the autocommand and call the function manually or replace it with a shortcutkey maybe like this:
map <F11> :call JavascriptLint()
you then have to remember to first save the file, and only call it on *.js files though...
Or, you could fix all warnings...it'll stop complaining too ;-)

Resources