I'm writing python code, and I'm facing to an annoying problem with the { and } moving keys : the vim definition for paragraphs is "blocks separated by an empty line".
However, when I code in python a class, I like to keep the indentation between methods, so is there an easy way to do paragraphs move to move like this :
class A:
def f(): #cursor here, when I type {, go between f and g
return 1
#the previous line is indented
def g():
return 2
Of course, it's always possible to remap } as a function doing
let a = #/
normal /\S\n\s*$/
normal j
let #/ = a
and { to a similar
but is there an easier way ?
The solution posted by #romainl is fine, but you might also want to look at Kana's textobj-user. It's a framework for defining text objects. Among other things, there is a plugin that uses this to define text objects for Python, which in turn have keys for moving across functions and classes. People have written many other similar plugins.
The default python ftplugin already redefines [m and ]m to jump to previous and next ^\s*\(def\|class\).
Related
I am new to Vim and I need to speed up my typing for this kind of statements.
if (a == 'e') {
foo();
}
In other text editors, I usually type if() {} first and then insert the text in to the parenthesis and curly braces. If I do this in Vim, I need to switch back to normal, move cursor to middle of () then middle of {}... switch between i and esc ...
What is your suggestion on typing this kind of syntax for Vim beginner? I would be grateful if you can show me the commands for that example step by step.
This is a job for snippet expansion. Take a look at SnipMate or UltiSnips.
snippets are like the built-in :abbreviate on steroids, usually with parameter insertions, mirroring, and multiple stops inside them. One of the first, very famous (and still widely used) Vim plugins is snipMate (inspired by the TextMate editor); unfortunately, it's not maintained any more; though there is a fork. A modern alternative (that requires Python though) is UltiSnips. There are more, see this list on the Vim Tips Wiki.
There are three things to evaluate: First, the features of the snippet engine itself, second, the quality and breadth of snippets provided by the author or others; third, how easy it is to add new snippets.
There are two approaches that solves your goal:
abbreviations
and snippets engines
Abbreviations and the old way of doing things. You just type if and space, and tada! You'll find plenty examples around the web. Only a few will be context-sensitive (i.e. they won't expand within comment or string contexts), or able to take the current project spacing style into consideration. In lh-cpp, you'll find the usual control-statement abbreviations for C and C++, they'll need to be duplicated for similar languages (a runtime ftplugin/c/c_snippets.vim from a php ftplugin should do it in your case)-- in lh-misc I support a couple of others languages (for VimL and shell)
Snippet engines are the trendy way of doing the same thing. This time, you will be able to type i or if and then <tab> (or CTRL+SPACE, or ...). Control-statement snippets won't need to be aware of the current context as we need to explicitly require the expansion. Others have already given links to the trendy snippets engines. Snippets from lh-cpp (which relies on mu-template) take the project style into account when expanding control-statement snippets (i.e. some projects want ) and { on a same line, other want a newline in between, ...)
Here's my answer in case you want to go with vanilla Vim.
In the majority of the cases I guess there is no point in entering the parentheses first and filling in the condition later, just type it all in right away:
if (a == 'e')
Then you can either continue
by typing {}<ESC>:
if (a == 'e') {}
^ cursor is here
The cursor is already placed so you can continue with i<CR> and type the body (if properly configured, Vim should indent for you).
or by typing {<CR>}<ESC>:
if (a == 'e') {
}
^ cursor is here
Then you can enter the body by pressing O (open new line above cursor). Possibly Vim also automatically indents here (it doesn't in my configuration).
If you really want to fill in the condition after you have entered this:
if () {
}
^ cursor
you can do so by typing kf(a.
If anybody knows better ways to do this without plugins, suggestions are welcome.
I am searching for an easy way to do search and replace things in vim as a "workaround" for refactoring.
On some other stackoverflow-question I found this snippet of code:
nnoremap gR gD:%s/<C-R>///gc<left><left><left>
I thought gD selects the current word under the cursor in the whole document and %s then search and replaces the matches after I typed the replace pattern.
gc stands for globally with confirmation?!
However: This does not work as expected. For example in some python class of mine I can easy rename occurencies of self in the whole file but it does not work on method identifieres or field identifieres with a length of one.
def __init__(self):
self.test = []
self.A = []
...
So self could be changed using this snippet, but doing gR on the field A simply does not work.
How can I get this work to do an easy search and replace on one file?
Any tips on intelligent refactoring would be also appreciated. After hours of searching I just found plugins and workarounds which work mostly with C files, but I would also need at least Java, Python and PHP compatibility.
Thanks for every answer :)
UPDATE: I recently found out it just works if the initial selected pattern is on the beginning of the line. If the pattern is somewhere in the middle of the line it does not work...any ideas?
gD is "Go to global declaration", see :help gD.
The mapping:
jumps to the 1st occurrence of the word under the cursor in the buffer with gD,
populates the command-line with %s/, meaning "substitute in the whole buffer",
followed by the search pattern used by gD, inserted with <C-r>/,
an empty pair of slashes, //, for the replacement,
the flags gc that mean "do your magic on every match on the line and ask for confirmation",
and goes <left><left><left> to place the cursor between the //, ready for you to type the replacement.
That mapping does exactly what it claims to do, here, no matter how long the word under the cursor is.
Vim is not an IDE, don't expect anything "intelligent".
A lot of times, I have a list of initializers in some of my code, like this:
class Foo(object):
def __init__(self, data):
self.foo = data.getFoo()
self.bar = data.getBar()
self.something = data.getSomething()
As you can see, I like my code aligned like a table. In a lot of cases, the above code can be generated by scripting Vim, coming from the output of some other program (DESCRIBE "foo"; in a database for example). Unfortunately, the scripted output usually looks like this, first:
class Foo(object):
def __init__(self, data):
self.foo = data.getFoo()
self.bar = data.getBar()
self.something = data.getSomething()
So after the automatic generation of th assignment statements, I'll have to manually align all statements for the desired look.
Now: Is there a way to get vim to align those "second halves"of the statements automatically?
The tabular plugin does exactly this. You can see it in action (and learn how to use it) here.
UPDATE: I'll give a brief explanation about the plugin usage, but no explanation will be better then Drew's video, so I strongly suggest everybody to watch it.
To use the plugin just call :Tab /= and it will align all the equal signs in the file. If you want to specify which line you want to align just give it a range :5,10Tab /= or use the visual mode (v or V) to select the desired lines, press : and insert the Tabularize command, your command line will look like this: :'<,'>Tab /=.
The argument in the Tabcommand is a Regular Expression, this means you can use this command to align many things. You'll be restricted only by your Regular Expression knowledge.
Sorry for any English mistake :D
An alternative to the already mentioned Tabular plugin is the venerable Align plugin.
One naive approach would be to first make enough space around the equal signs:
:s/=/ =/
Then, block-selecting (Ctrl-V) so that all the = characters and everything that follows is selected. Yank(y) that, paste it somewhere else.
Next, un-indent the pasted lines (10< is usually sufficient) until they're aligned to the leftmost position. Then, block-select again and paste to where they were cut off.
This feels like a lot of work though, for the desired effect.
Is there a way to do this? I know you can do all the obvious ones like ,c and ,cs
But I don't think there's a binding for commenting out an entire function...
From anywhere inside the function, do:
va{,c<space>
off course, you can map this to something:
:map ,o va{,c<space>
so pressing ,o inside a function will comment it (or uncomment it if it is already commented).
It depends..
It depends on how the function is, and where you are.
public function test()
{
$name = "whatever";
$data = array(
'name' => $name
);
return $data;
}
Scenario 1: Cursor Line 1 at public function test()
Sequence: Vj%
V Start linewise visual mode
j Go down one line
% Go to matching closing bracket
Scenario 2: Cursor Line 3 at $name = "whatever"
Sequence: va{ok
v Start visual mode
a{ Arround bracket
o Exchange cursor from top to bottom of selection
k Go up one line
Then, comment as usual ,,c depending on your Nerd Commenter mapping.
There are no binding for commenting out the whole function (as far as i know). I think there are couple of ways you can achieve this - for example you can place cursor on the closing bracket, go to the visual line mode, press % key (and select additional line if you place opening bracket in new line) and then use \cc for example.
When I want to achieve this i use textobj-user and textobj-rubyblock (I am currently programming mostly in Ruby) plugins, which allow me to easily select block of code with var and expand it with ar. That's quite nice, because I don't need to go to the end keyword (in C that would be closing bracket), but I select whole function without moving cursor from the function's body. I have not tried this, but for you this plugin should work. That's not a solution with one binding, but it's quite quick too. I hope this will be usefull for you. :)
As title, if I'm in the middle of function body and the function body is very long, how can I jump back to the beginning of the function body .
[m
Go to [count] previous start of a method
Works for Java or similar structured languages, and for Python as well.
C language [[
If your C code is in the non-Egyptian style:
[[
[m only works if you have an enclosing {} around the function, e.g. class { method(){} } for Java / C++.
And this is a good bet that works for both Egyptian and non-Egyptian braces:
?^[^ \t#]
Examples:
void egypt() {
#define DONTCARE 1
int indented code = 1;
}
void tpyge()
{
#define DONTCARE 1
int indented code = 1
}
For functions contained in a pair of curly-braces {}:
Jump to beginning: [{
Jump to end: ]}
Replace the curly-blackets by parens or square-brackets for functions that use those.
I spent hours to make this pattern: /^\s*\(\i\+\_[ \t\*]\+\)\+\i\+\_s*(\_[^)]*)\_s*{, it works good for me.
EDIT: a better pattern(version 2): /\(\(if\|for\|while\|switch\|catch\)\_s*\)\#64<!(\_[^)]*)\_[^;{}()]*\zs{
see the effect here:
you can map some convenient bindings in your .vimrc, such as:
" jump to the previous function
nnoremap <silent> [f :call search('^\s*\(\i\+\_[ \t\*]\+\)\+\i\+\_s*(\_[^)]*)\_s*{', "bw")<CR>
" jump to the next function
nnoremap <silent> ]f :call search('^\s*\(\i\+\_[ \t\*]\+\)\+\i\+\_s*(\_[^)]*)\_s*{', "w")<CR>
EDIT: a better pattern(version 2):
" jump to the previous function
nnoremap <silent> [f :call
\ search('\(\(if\\|for\\|while\\|switch\\|catch\)\_s*\)\#64<!(\_[^)]*)\_[^;{}()]*\zs{', "bw")<CR>
" jump to the next function
nnoremap <silent> ]f :call
\ search('\(\(if\\|for\\|while\\|switch\\|catch\)\_s*\)\#64<!(\_[^)]*)\_[^;{}()]*\zs{', "w")<CR>
In 2022, treesitter deserves your attention.
The built-in [m uses lexical rules and always jumps to the previous { position or the outermost { position.
In contrast, treesitter takes advantage of syntactic information, so it can jump to a more precise position, and there are no limitations as described below:
The above two commands assume that the file contains a class with methods.
The class definition is surrounded in '{' and '}'. Each method in the class
Each method in the class is also surrounded with '{' and '}'. This applies to the Java language.
file looks like this: >
If you want to learn more, check https://github.com/nvim-treesitter/nvim-treesitter-textobjects
BTW, the only relatively sure way to be able to do this is to modify vim, see this post
[edit]
and this only works with languages supported by exuberant ctags. Since we've not been deigned fit to know which language you wish to do this in, it's possible that this answer will not be correct either.
[/edit]
Once you've got moving around blocks and paragraphs in code sorted you might like to look at what you can do when you're in the middle of those blocks by looking at this part of the vim doc's.
Things like delete the block, insert before the block, append after the block, etc.
HTH
Searching (backwards) for ?^{ should normally get you there.