Commenting out a function with NerdCommenter - vim

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. :)

Related

Vim copy line and comment out old line

I'm trying to achieve the same thing asked here, but in Vim.
Duplicate line and comment out old one
Basically I want to yank line, comment out the old one, paste new one, and keep cursor at the beginning of new line and end in insert mode.
For example:
def func (param)
will change to:
//def func (param)
def func (param)
I recorded a macro for it, put it into .vimrc and I'm using it via #y
" copy-and-comment-line macro
" yank line, comment out original line, move cursor at the begining
" of copied line and end in insert mode
let #y='yypkui//kdklkl'
(I'm not sure it will work for you as it contains unprintable ~# characters which code block won't display)
Macro works, but is there a built-in command in vim that I can achieve same thing with?
This mapping should do it for you:
nnoremap YOURKEY YI//<esc>p
The cursor will be on the pasted line.
replace YOURKEY by a key (or keys) you like
Note that this answer works only for your example, //style comment. If you want it to be generic solution, you have to build a function, in this function check the filetype, and decide which comment style should be used. There is no good built-in solution so far, but you can check the NERDCommenter or vim-commentary plugins to see how they achieve this, or you can install one of them (or a similar plugin) and call it's function in your mapping.

Sublime Text 3 - End key toggles end of line and start of comment

If I remember correctly, in Eclipse IDE you can press the End key and go to the end of a line, then again to go to the end of your code line, before the beginning of a comment. Here's an example with | as the cursor:
var str = 'press end to move the cursor here:'| // then here:|
It's very similar to how when you press Home it goes to the very start of the line, then another press moves the cursor to the beginning of your code, like this:
| |var str = 'press home to toggle cursor position';
Anyone know how to acheive this functionality in Sublime Text 3?
Sublime Text's native move and move_to commands don't support scopes or comments as an argument, therefore it is necessary to create a plugin in Python to achieve this behavior, and bind the End key to it.
From the Tools menu in Sublime Text, click New Plugin.
Replace the contents with the following:
import sublime, sublime_plugin
class MoveToEndOfLineOrStartOfCommentCommand(sublime_plugin.TextCommand):
def run(self, edit):
new_cursors = []
for cursor in self.view.sel():
cursor_end_pos = cursor.end()
line_end_pos = self.view.line(cursor_end_pos).end()
if line_end_pos == cursor_end_pos and self.view.match_selector(line_end_pos, 'comment'): # if the cursor is already at the end of the line and there is a comment at the end of the line
# move the cursor to the start of the comment
new_cursors.append(sublime.Region(self.view.extract_scope(line_end_pos).begin()))
else:
new_cursors.append(sublime.Region(line_end_pos)) # use default end of line behavior
self.view.sel().clear()
self.view.sel().add_all(new_cursors)
self.view.show(new_cursors[0]) # scroll to show the first cursor, if it is not already visible
Save it in the folder ST suggests, the name is unimportant as long as the extension is .py. (The command name for reference by the keybinding is based on the Python code/class name, not the file name.)
Goto Preferences menu -> Key Bindings - User and insert the following:
{ "keys": ["end"], "command": "move_to_end_of_line_or_start_of_comment" }
When pressing the End key, it will move to the end of the line as usual, unless it is already at the end of the line, and there is a comment, in which case it will move to the start of the comment.
Note that this is a tiny bit different to your example of:
var str = 'press end to move the cursor here:'| // then here:|
because it will move the cursor to after the whitespace at the end of the code like this:
var str = 'press end to move the cursor here:' |// then here:|
but it should give you a framework to work from. You can use the substr method of the view to get the characters in a certain region, so you can check for spaces using this quite easily.
EDIT: Note that since this answer was written, I have created a package for this functionality with some extra considerations, customization and use case support, as mentioned in another answer to this question.
Years later, I’ve stumbled onto this package: https://github.com/SublimeText/GoToEndOfLineOrScope
Sublime's scope documentation isn’t super easy to understand so it took a bit of digging and trial and error, but here’s a key binding that makes it work pretty well:
{
"keys": ["end"],
"command": "move_to_end_of_line_or_before_specified_scope",
"args": {
"scope": "comment.line",
"before_whitespace": true,
"eol_first": false
}
},
This makes the End key toggle between the end of the line and to the left of the comment delimiter, before any white space that trails code. It will also move to end of code first, then end of the line, saving a key press where that’s the intended behavior. It’s very easy to tweak though obviously.
The comment scope (as used above in Keith Hall’s answer) works too, but I don’t like the toggling behavior in block/multiline comments, so comment.line was a nice find.

How to delete a paragraph as quickly as possible

I want to delete the following codes in my config file:
server {
listen 80;
server_name xxx;
location / {
try_files xx;
}
}
I know I can use 7dd, but this is not handy enough- if the section is too long, counting the rows would be inconvenient.
Is there a better way to do this?
Sometimes, I have to delete a whole function, any ideas for that?
As in common in Vim, there are a bunch of ways!
Note that the first two solutions depend on an absence of blank lines within the block.
If your cursor is on the server line, try d}. It will delete everything to the next block.
Within the entry itself, dap will delete the 'paragraph'.
You can delete a curly brack block with da}. (If you like this syntax, I recommend Tim Pope's fantastic surround.vim, which adds more features with a similar feel).
You could also try using regular expressions to delete until the next far left-indented closing curly brace: d/^}Enter
]] and [[ move to the next/previous first-column curly brace (equivalent to using / and ? with that regex I mentioned above. Combine with the d motion, and you acheive the same effect.
If you're below a block, you can also make use of the handy 'offset' feature of a Vim search. d?^{?-1 will delete backwards to one line before the first occurrence of a first-column opening curly brace. This command's a bit tricky to type. Maybe you could make a <leader> shortcut out of it.
Note that much of this answer is taken from previous answer I gave on a similar topic.
If there is a blank line immediately after these lines, Vim will identify it as a paragraph, so you can simply use d} to delete it (assuming the cursor is on the first line).
Try using visual mode with %.
For example, say your cursor is at the beginning of the "server" line.
Press v to go into visual mode. Press % to highlight to the end of the block. Press d to delete it.
As David said their are many ways. Here are a few that I like:
Vf{%d This assumes you are on the line w/ server and you do a visual line selection, find the { and then find the matching } via the % command.
set relativenumber or set rnu for short. This turns on line numbering relative to your cursor. So you do not have to count the lines just look and 7dd away to deleting your block.
Use VaB to visually select a block i.e. { to }, line-wise. While still in visual mode continue doing aB until the proper block is selected then execute d. This means you can select a block from inside the block instead of at the start or end.
d} will delete a paragraph. This works in your current scenario because there is no blank line inside the block. If there is one then all bets are off. Although you can continue pressing . until the block is properly deleted.
If inside a block you can jump to the current block via [{ then continue executing [{ until you are at the correct block then V%d or d%dd to delete the block
Using the techniques above you can delete a function as well, but you can also use the [M and friends ([m, ]m, ]M) to jump to the start and endings of methods but they commonly work for functions as well.
For more information
:h %
:h 'rnu'
:h aB
:h }
:h .
:h [{
:h [m
Given matching parens, or braces, you can use % with d to delete, spanning lines.
So, assuming that you're on the server { line, you can do d%. This is generally useful for all code blocks, e.g. function blocks, loop blocks, try blocks.
Similarly, dip works, but d} is shorter. However, both will only delete to the next empty line.

Enclosing the function call in another function call (retval as parameter)

Having this LOC:
printf("%s (%d)\t(%d)\t%d-%d\t", meta_scanner_token_name($ret['major']), $ret['major'], (string)$ret['dirty'], $ret['start_line'], $ret['minor']);
What is the fastest way in terms of key strokes to enclose the call to meta_scanner_token_name in another function call to foo, yelding:
printf("%s (%d)\t(%d)\t%d-%d\t", foo(meta_scanner_token_name($ret['major'])), $ret['major'], (string)$ret['dirty'], $ret['start_line'], $ret['minor']);
given that
first scenario: my cursor is on 'm' at the beginning of the function?
second scenario: my cursor is somewhere on meta_scanner_token_name?
va)oB would select the entire line, and ys%) would enclose only the m, resulting in:
... (m)eta_sca...
Please answer to both scenarios.
(I am using spf13-vim with default settings except some visual changes, if that has any relevance)
ifoo(<Esc> then f)i)<Esc>
bifoo(<Esc> then f)i)<Esc>
but I'm still a Vim noob
-- EDIT --
I see "Surrounding.vim" is a modified version of "Surround.vim" if it's compatible with Surround you can do:
Scenario 1
vt,sffoo<CR>
vt, to select everything until the first ,
s to launch Surround.vim
f to instruct Surround to input a "function"
foo the identifier
<CR> Enter key.
That's 6 keystrokes not including typing foo which — I think — can't really be avoided.
Scenario 2
bvt,sffoo<CR>
It's the same as scenario 1 except that you type b first to go back to the first letter of meta_scanner_token_name.
Using normal vim you could do this (prefix with b for scenario 2)
`cf)foo()<esc>P`
If your vim plugins add the closing paren for you, you can drop that from the sequence. Depending on where it leaves your cursor, you might need to use p instead of P.

Vim: replacing text within function body

I have some very useful plugins to find and replace text through files (see EasyGrep vim script - it's very helpful for programmers). I can even replace text only in the current buffer - by using plugins or :%s .... But what if I just want replace text within the current function body?
Consider the following example:
void f0()
{
int foo = 0;
// ...
}
// 99 other functions that uses foo as local variable.
void f100()
{
int foo = 0; // I want to replace foo with bar only in this function
// 1000 lines of code that uses foo goes below
// ...
}
Of course, I can use :%s ... with c flag for confirmation, but I believe there is a faster way to do this.
Thanks.
You can apply a substitution to the whole file using % or on a selection.
To create a selection :
Go in Visual mode Linewise for example, with Shift+v, select a few line and then type :.
Your prompt will look like :
:'<,'> it means : current selection
Type then s/foo/bar/g and it will replace foo by bar in the current selected line.
The better way to select a function content is to go inside a function with your cursor and type :
vi} it will select everything between { and }.
See :help text-objects for more tips on selection.
You could mark the function with V. Then when you type a command in :, it'll automatically be prefixed by and only be executed in the marked area.
There's probably a command for jumping to beginning of function and end of function, so you could do begin-function, V, end-function, substitute very quickly. Don't know those commands though.
I've always used [[ to jump to the beginning of the function, then use % to jump to the end of the function. I used mt and mb to mark the top and bottom of the function, respectively. Then to search and replace within the marked top and bottom, :'t,'bs/pattern/newpattern/g. This has always worked for me. I'm sure you can create a macro for this.
The visual select (vi}) is much easier and faster. It is aware of the cursor position. So, if the cursor is inside a fucntion sub block, then vi} selects all lines in that block. If you want to select the entire function, one needs to place the cursor outside of the sub blocks then do vi}. This is great for function blocks that fits in the current window. For functions that spans beyond the current window, the selection is lost once scroll up.
I really like the visual select of the vi} because it's so much easier and faster, but I have to resort the old school method on occasion.

Resources