With vim text-objects I can copy some text like vib or vi". See :help object-select
I would be happy to have a similar shortcut for selecting a file path like "/my/path/to/file". In functions like gf or ^xf some kind of matching is done, but I could not find a matching shortcut.
Any ideas how to make a shortcuts like vif, yif or dif to work? Or any plugin suggestions?
You can define a text object called "file" quickly if vim-textobj-user is installed.
call textobj#user#plugin('file', {
\ 'file': {
\ 'pattern': '\f\+', 'select': ['af', 'if']
\ }
\ })
Thus vif, yif, etc. would work as expected.
This should be fairly easy to do with my CountJump plugin:
:call CountJump#TextObject#MakeWithCountSearch('', 'f', 'a', 'v', '\f\#<!\f', '\f\f\#!')
This creates an af text object, based on the 'isfname' setting (\f regexp atom).
Related
Say I have the following:
text function(contents) text
and I wanted it to be
text function() text
Placing the cursor right after the opening parenthesis, I thought the following command would work df); however, what I ended up with was the following
text function( text
So I would need someway to specify that I want the character just before the closing parenthesis, but I'm not sure how to do that. There may also be a better way to do this.
What would be the best way to go about this?
You were close! You need dt) as in delete till )
The f motion places the cursor on the ) (remember it like find)
As for the 'best' way to do it, there is at least a more general way: if the
cursor were somewhere in the middle of the ( and ) (or on one of them), you
can do di) (or equivalently di() to delete inside )
If you do da) (or equivalently da() to delete around ), you would
delete the stuff in between and including the brackets.
The same goes for di[, di{, di<, di', di" etc. Using these so-called
text objects, as opposed to the d{motion} way, has the advantage that you can
repeat the edit on other pairs of brackets/quotes without the cursor needing to
be in precisely the same place - it just needs to be on or in between them.
In the following you could position the cursor on e.g. the 'i' of 'initial' in
the first line, do di) to delete the words 'some initial text', then move the
cursor to the 'e' in 'more' in the second line and just do . to also delete
the words 'some more text'):
(some initial text)
(some more text)
This way also works when the brackets (or quotes) are on different lines. For
example, with the cursor somewhere between the {}, doing di} will change
this:
function( args ) {
body of function
}
to this:
function( args ) {
}
I'm a heavy VIM user but I missing one thing…
setting a fix jump marker in a comment on different parts of a (large) current open file
What I expect:
setting a marker in a comment like: // vim: marker(x)
jumping to the marker with: 'x
example (using tcl code) using 'x to jump to function p_structDEF_MqC
proc p_func_arg_name_DEF_MqC {key value} {
set cmd "N"
regexp {^(\w)#(.*)} $value dummy cmd value
set ::ARG_DEFAULT(k,$key) $cmd
set ::ARG_DEFAULT(v,$key) $value
}
proc p_arg_name_DEF_MqC {key value} {
func_arg_name_DEF_${::LANG}_MqC $key $value
}
## vim: marker(x)
proc p_structDEF_MqC {name} {
global xCLASS xPREFIX
set prefix [string range $name 0 end-1]
if {$prefix ne "Mq"} {
lappend xPREFIX "$prefix"
}
lappend xCLASS "${prefix}C"
}
proc p_enumDEF_MqC {name argv} {
}
proc p_typeDEF_MqC {VAR VALUE} {
}
proc p_fupuDEF_MqC {name ret argv} {
}
You can create an autocommand that scans files for those marks,
and create them using setpos(). You can go as complex as
you want in your scripting, i.e. to analyze the next line
and determine where the mark should be. Here is a simple
implementation in a single command that creates marks on the
first character of the next line:
au BufRead * g/vim: marker([a-z])/call setpos(
\ "'".matchstr(getline('.'), '(\zs\w'),
\ [0, getpos('.')[1]+1, 1, 0] )
This answer is based mainly on :autocmd and :g. You should
check the help files for both (:h :au and :h :g). An
autocommand runs the specified command when a certain event
happens for files matching a specific pattern. So, more help
topics for you to read:
autocmd-events
autocmd-patterns
You can use the pattern to restrict this to certain files.
Then, we have the :g command which searches for lines matching
a pattern and executes a command. The search is where you modify
which flags are you looking for. Based on your comment, let's say
for example you want to make the space after : optional. Then
update your regex to:
vim: *marker([a-z])
Modify this as you need.
The command is centered in the setpos() (again search the help
for it... everything I'm saying is in the help anyway). It takes
two arguments, one is what to set and the other is what to set
to. We want to set a mark, so we need to give it an expression
like "'a" to set mark a. To figure out which letter is the
mark supposed to be applied to, we use:
matchstr(getline('.', '(\zs\w')
Here we search for the first letter after the first parenthesis
(with (\zs\w) on the text of our current line, retrieved with
getline(). Search for the help of all these functions. This is
concatenated to a quote, with "'" . {expr} to make a "'x" if
the letter was x.
Then for the second argument, if must be an array similar to what
getpos() returns. Search the help again. However we are
modifying it, to set the mark on the beginning of the next
line. Thus we only use the line item returned by getpos(),
which is the second item, and add 1 to it.
[{buffer}, {line}, {col}, {virtual-offset}]
[0, getpos('.')[1]+1, 1, 0]
the working solution based on previous answer:
au BufRead *.c silent! g/vim: \*Marker(\[a-z])/call setpos(
\ "'".matchstr(getline('.'), '(\zs\w'),
\ [0, getpos('.')[1]+1, 1, 0] )
→ thanks to #sidyll for the help.
I'd like to set up some custom auto-complete macros in vim. I'm thinking something like this (| represents the cursor position):
it<TAB>|
immediately becomes:
it("|", function () {
});
Is this possible using straight vim, or would I need a plugin? If so, is there a preferred plugin out there?
Using an abbreviation you could write something like this:
inorea it it("", function () {<cr>});<c-o>k<c-o>f"
The purpose of <c-o>k<c-o>f" at the end is to reposition your cursor inside the double quotes, but it may not work all the time.
Using a mapping, you could try this:
ino <expr> <tab> <sid>expand_last_word()
let s:your_expansions = {
\ 'it': '\<c-w>it(\"\", function () {\<cr>});\<c-o>k\<right>',
\ }
fu! s:expand_last_word() abort
let last_word = matchstr(getline('.'), '\v<\k+%'.col('.').'c')
return has_key(s:your_expansions, last_word)
\ ? eval('"'.s:your_expansions[last_word].'"')
\ : "\<tab>"
endfu
You would have to add your abbreviations and their expansions inside the dictionary s:your_expansions.
Using the :read command, you could define larger snippets of code, and split them across several files:
ino <expr> <tab> <sid>expand_last_word()
fu! s:expand_last_word() abort
let last_word = matchstr(getline('.'), '\v<\k+%'.col('.').'c')
if last_word ==# 'it'
return "\<c-w>\<c-o>:r /path/to/some_file\<cr>\<c-o>f\"\<right>"
endif
return "\<tab>"
endfu
Here /path/to/some_file should contain your snippet:
it("", function () {
});
They are very simple solutions, if you want something more robust, you probably need a snippets plugin. One of them is UltiSnips, which requires that your Vim version has been compiled with Python support (:echo has('python') or :echo has('python3') returns 1).
With UltiSnips, you would write your snippet like this:
snippet it "your description" b
it("$0", function () {
});
endsnippet
Here the definition is included between the keywords snippet and endsnippet. On the 1st line, you can describe the purpose of your snippet, inside the string in double quotes. It will be displayed by UltiSnips inside a list, if you've defined several snippets with the same tab trigger, and there's an ambiguity.
The ending b is an option to prevent the tab trigger it from being expanded anywhere else than the beginning of a line.
$0 is a tabstop, it stands for the position in which you want the cursor to be, once the snippet has been fully expanded.
The readme page on github gives a quick start, and some links to videos.
If you want to have a look at the snippets written by other people, you can install vim-snippets.
There are other snippet managers but I don't know them well enough to describe the syntax of their snippets. If you want a comparison, here's one, and here are links for some of them:
snipmate
mu-template
neosnippet
xptemplate
Here is a abbreviation that you can use for your particular example
:inoreabbrev it it("", function () {<cr>});<esc>kf"a
Typing it followed by ctrl + ] in insert mode will render
it("|", function () {
});
and keep you in insert mode.
But I would definitely go for ultisnips and there is a screencast for creating snippets on the same page. That's why I am omitting the snippet here as you can do it yourself.
i'm interested in configuring vim to indent haml attributes. right now they automatically indent to two spaces, but i want them to line up like this:
.some-div{ id: something,
data: { key: 'value' },
title: 'etc' }
.the-content
= whatever
this is my current sad state of affairs:
i want it to behave more like the way it indents ruby:
Use tabular to form vim:
https://github.com/godlygeek/tabular
There's a good vimcast on this:
https://www.youtube.com/watch?v=S33w7rcxbOk
It's really easy to insert a closing brace after typing the opening one:
inoremap { {<CR>}<Esc>ko
This way
if (true) {
converts to
if (true) {
|
}
But I'd like to save time and to type 1 character less:
if (true)<CR>
So I'd like to create the following rule: if return is pressed and the line starts with if/for/while, execute {<CR>}<Esc>ko
Is this doable?
Thanks
Building on your previous mapping, this should do what you want:
inoremap )<CR> ) {<CR>}<Esc>ko
However, you should try a snippet expansion plugin like SnipMate or Ultisnips. Both plugins allow you to define snippets with placeholders and miroring (lots of them are included by default) that are expanded when a <Tab> is pressed after a trigger.
For example, you have a snippet associated with the trigger if that expands into:
if ([condition]) {
}
condition is selected, ready for you to type, and, once you are done, you can hit <Tab> again to jump the cursor between the curly braces, ready to type:
if (myVar == 5) {
|
}
This is incredibly handy.