How to yank an entire block in Vim? - python

Is it possible to yank an entire block of Python code in Vim?
Be it a def, for, if, etc. block...

You can yank a paragraph with y}. This will not yank all the methods if you have a blank line though.

If you want to yank everything except the { use yi{ (or yi}). If you to include the curly braces use ya{ (or ya}).
The i and a modifiers mean in and all.
To yank a word no matter where in the word you are: yiw
To yank the contents of parentheses: yi); if you want to include them, use ya(
You can do the same for " or ' with yi", ya" or yi' and ya'.
Of course, you're not limited to yanking. You can delete a word with diw or change it with ciw, etc... etc...

The excellent add-on suite Python-mode includes some key commands to navigate classes, methods, and function blocks.
To yank a method: yaM (inner method: yiM)
To yank a class: yaC
There are other handy motions, like moving from function-to-function (]]). See the complete list of keys for more.

There's a vim add-on script python_fn.vim which has, as one of its functions, a key binding to visually select a block of Python code using ]v. You could then yank it with y as normal.

I usually just use visual block mode. Shift-V, move, and 'y'ank the highlighted block. There's only so many shortcuts I can keep in memory at once :)

You can combine a search with yank, so if your function ends with return retval you can type y/return retval

Enter visual line selection by pressing 'V'
When finished selecting the block pres 'y'
Paste it somewhere with 'p' or 'P'

I made a plugin named spacebox which does a Visual selection of all lines with the same or more indentation as the current line.
With Python whitespace being the way it is, you could place your cursor on the line below def or if, and issue the command :SpaceBox to select your "block".

vim-indent-object works pretty well. Worth a shot.

Just fold the class using za and then use visual mode ( V ) to select the collapsed class. This way you don't have to scroll too much. Then just yank with y. When you are done yanking unfold the class with za again.

In .py file, press Esc
Press shift V to enter visual line mode
Highlight with up and down arrow keys
Press d to delete the selected rows
Go to the row you would like to place the lines and press p to paste lines after a row or press shift P to paste before a row
Hope that helps.

Related

how to indent block of python code without using tabs

I am just learning python and need to know how to indent a block of code without using the tab button (because, as I have read, tab should not be used).
Example:
in a simple print function
def test(string):
print(string)
print("'" + string + "'")
test('test')
IF now, I want to put the print functions in an if statement
def test(string):
if len(string) > 2:
print(string)
print("'" + string + "'")
test('test')
How can I indent the two print statements without using the 'tab', or having to click on every line and insert 4 spaces? I am very used to selecting all the lines I need to move to the right and pressing tab regardless of program (geany, ipython, notepad++).
I would like to set off following the PEP8 style guide from the introduction into Python.
My concern is not this particular example, but if I have a code block I want to move left or right that is many more lines.
Thanks,
Ivan
It depends on what text editor you're using. I use Notepad++, which is one of the ones you mention, and it has an option to use spaces in place of tabs. So I just enable that for .py files, then I can indent a block by hitting tab exactly as you're used to (and unindent with shift-tab).
Go to settings > preferences > tab settings, select "python" from the list on the right and check the "replace by space" checkbox. Other text editors that offer the same feature will presumably each have their own way of enabling it, and their own way of making it language-specific.
Be aware that pressing tab to change the indentation of a selection is just a UI convention, albeit a common one. It doesn't work for example in Notepad, where hitting tab while text is highlighted behaves the same as typing anything else: replaces the selection with a tab. If you were using Notepad then I'm pretty sure the answer would be "it's not possible". If you use lots of different editors then I think unfortunately you're going to have to investigate each one in turn.
As you have mentioned, PEP8 recommends four spaces for each level of indentation. Many text editors allow you to set tabs to be replaced by a certain number of spaces. So in many cases it is still ok to use tab to program in python, just make sure that it is replaced by four spaces.
I personally use Sublime Text and there seems to be an option to customize Tabs:
{
"tab_size": 4,
"translate_tabs_to_spaces": true
}
In the Packages/User/Preferences.sublime-settings. Maybe worth trying that.

Is there a quick way to decrease the indentation of multiple lines in Python?

I am a newbie to python programming. I find that decreasing the indentation of a block of codes in python is quite annoying. For example, given the following code snippet
for i in range(density):
if i < 5:
x, y = rnd(0,shape[1]//2)*2, rnd(0,shape[0]//2)*2
Z[y,x] = 1
....
....
If I comment the if statement, I have to decrease the indentation for lines in the if block one by one, is there a way that I can do this by one key stroke as I increase the indentation of a block of codes by selecting them and press the TAB key? I guess this is environment dependent, so could you please provide solutions to do so in Eclipse+Pydev, VIM, and other common editors?
In vim, you select the block and then press the < key.
In Eclipse you select it and then press SHIFT + TAB.
Every code editor worth its salt has a one-key way to indent and dedent blocks.
You could also replace the if statement with:
if True: # if i < 5:
and leave everything else alone - no indent/dedent to undo later.
Perhaps late for your case, but if useful for others:
SHIFT + TAB will do unindent for the selected text in Eclipse.
Use Preferences-Pydev-Editor settings uncheck change tabs to spaces. It makes detent errors and your problem. And test other options like 4 space tab, 8 space tab and so on.

How to skip over closing braces / brackets / parentheses in PyCharm?

I can't get the auto-indentations to work properly unless I use the automatic closing of braces, et al (which I don't like), and I see no option allowing one to skip over/out.
Eclipse has a configuration option for this, and Visual Studio doesn't auto-close everything by default, but rather formats the code block after manually entering the closing brace (which I rather prefer).
Surely there's something apart from going all the way over to the "End" key?
Edit / update:
As I consider it bad form to leave a question without a marked answer, would someone with more recent experience with PyCharm (I haven't used it in quite some time) weigh in with a recommendation for the best among the below solutions? Perhaps there's a newer configuration option or simple solution not yet listed?
Press Ctrl-Shift-Enter to close the missing braces on the current line (if any), add the missing colon (if missing) and put the caret into the correctly indented position on the next line.
Shift + Enter will jump past completions and drop you onto the next line.
Ctrl + ] will jump to the end of the current element.
This seems to work in most cases to skip past auto-completions. I find it the most versatile of the options.
Ctrl + [ will jump you to the start of whatever code block you are in.
As previously mentioned Ctrl + Shift + Enter will add any extra auto-completions you might need and drop onto a new line.
A college told me a solution:
First you type this:
def test_foo(
PyCharm inserts self) as soon as you type (
Current state: ^ indicates the cursor position:
def test_foo(self^):
Just type ): and hit ENTER, and you are on the next line.
Since I type with ten fingers Ctrl-Shift-Enter is not a solution for me in such common editing operations.
Why do you dislike the auto-closing brackets? They do not disturb anyone, see:
^ specifies the cursor position
method([a, {b: c^}])
behaves as if no brackets were there if you insert new brackets!
insert a '}':
method([a, {b: c}^])
now insert a ']':
method([a, {b: c}]^)
now insert a ')':
method([a, {b: c}])^
et voila! From a users point of view, if you typed blindly, you can not tell from what you see now if the auto-closing brackets were inserted or not.
Or simply: keep the closing brackets on. IntelliJ did a great work on a lot of small things we want to have intuitively.

Reverse a word in Vim

How can I reverse a word in Vim? Preferably with a regex or normal-mode commands, but other methods are welcome too:
word => drow
Thanks for your help!
PS: I'm in windows XP
Python is built in supported in my vim, but not Perl.
Here is another (pythonic) solution based on how this works:
:echo join(reverse(split('hello', '.\zs')), '')
olleh
If you want to replace all words in the buffer,
:%s/\(\<.\{-}\>\)/\=join(reverse(split(submatch(1), '.\zs')), '')/g
This works by first creating a list of characters in the word, which is reversed and joined back to form the word. The substitute command finds each word and then passes the word to the expressions and uses the result as replacement.
This Tip might help: http://vim.wikia.com/wiki/Reverse_letters
It says:
Simply enable visual mode (v), highlight the characters you want inverted, and hit \is. For a single word you can use vw (or viw): viw\is
vnoremap <silent> <Leader>is :<C-U>let old_reg_a=#a<CR>
\:let old_reg=#"<CR>
\gv"ay
\:let #a=substitute(#a, '.\(.*\)\#=',
\ '\=#a[strlen(submatch(1))]', 'g')<CR>
\gvc<C-R>a<Esc>
\:let #a=old_reg_a<CR>
\:let #"=old_reg<CR>
There are more solutions in the comments.
Assuming you've got perl support built in to vim, you can do this:
command! ReverseWord call ReverseWord()
function! ReverseWord()
perl << EOF
$curword = VIM::Eval('expand("<cword>")');
$reversed = reverse($curword);
VIM::Msg("$curword => $reversed");
VIM::DoCommand("norm lbcw$reversed");
EOF
endfun
And potentially bind that to a keystroke like so:
nmap ,r :ReverseWord<CR>
I don't have Python supported on my VIM, but it looks like it would be pretty simple to do it with Python. This article seems like a good explanation of how to use Python in VIM and I'm guessing you'd do something like this:
:python 'word'[::-1]
The article indicates that the result will appear in the status bar, which would be non-optimal if you were trying to replace the string in a document, but if you just want to check that your girlfriend is properly reversing strings in her head, this should be fine.
If you have rev installed (e.g. via MSys or Cygwin) then it's really not this difficult.
Select what you want to reverse and filter (%! <cmd>) it:
:%! rev
This pipes your selection to your shell while passing it a command.
if your version of VIM supports it you can do vw\is or viw\is (put your cursor at the first letter of the word before typing the command)... but I have had a lot of compatibility issues with that. Not sure what has to be compiled in or turned on but this only works sometimes.
EDIT:
\is is:
:<C-U>let old_reg_a=#a<CR>
\ :let old_reg=#"<CR>
\ gv"ay :let #a=substitute(#a, '.\(.*\)\#=', '\=#a[strlen(submatch(1))]', 'g')<CR>
\ gvc<C-R>a<Esc> :let #a=old_reg_a<CR>
\ :let #"=old_reg<CR>
Didn't remember where it came from but a google search come this article on vim.wikia.com. Which shows the same thing so I guess that's it.
Well you could use python itself to reverse the line through the filter command. Say the text you had written was:
Python
You could reverse it by issuing.
:1 ! python -c "print raw_input()[::-1]"
And your text will be replaced to become:
nohtyP
The "1" in the command tells vi to send line 1 to the python statement which we are executing: "print raw_input()[::-1]". So if you wanted some other line reversed, you would send that line number as argument. The python statement then reverses the line of input.
There is a tricky way to do this if you have Vim compiled with +rightleft. You set 'allowrevins' which let you hit Ctrl+_ in insert mode to start Reverse Insert mode. It was originally made for inserting bidirectional scripts.
Type your desired word in Insert mode, or move your cursor to the end of an already typed word. Hit Ctrl+_ and then pick a completion (i_Ctrl-x) method which is the most likely not to return any results for your word. Ysing Ctrl+e to cancel in-place completion does not seem to work in this case.
I.e. for an unsyntactic text file you can hit in insert mode Ctrl+x Ctrl+d which is guaranteed to fail to find any macro/function names in the current file (See :h i_CTRL-X_CTRL-D and:h complete for more information).
And voila! Completion lookup in reverse mode makes the looked up word reverse. Notice that the cursor will move to the beginning of that word (it's reversed direction of writing, remember?)
You should then hit Ctrl+_ again to get back to regular insert mode and keyboard layout and go on with editing.
Tip: You can set 'complete' exclusively (for the buffer, at least) to a completion option that is guaranteed to return no result. Just go over the options in :h 'complete'. This will make the easy i_Ctrl-N / i_Ctrl-P bindings available for a handy word reversal session. You can ofcourse further automate this with a macro, a function or a binding
Note: Setting/resetting 'paste' and 'compatible' can set/reset 'allowrevins'. See :h allowrevins.
If you have some time on your hands, you can bubble your way there by iteratively transposing characters (xp)...
I realize I'm a little late to the game, but I thought I'd just add what I think is the simplest method.
It's two things:
Vim's expression register
pyeval (py3eval on recent vim releases) function
So to reverse a word you would do the following:
"ayiw yank word into register a
<C-r>=py3eval('"".join(reversed(str(' . #a ')))') use vim's = (expression) register to call the py3eval function which evaluates python code (duh) and returns the result, which is then fed via the expression register into our document.
For more info on the expression register see https://www.brianstorti.com/vim-registers/#the-expression-and-the-search-registers
you can use revins mode in order to do it:
at the beginning type :set revins. from now on every letter you type will be inserted in a reverse order, until you type :set norevins to turn off. i.e, while revins is set, typing word will output drow.
in order to change an existing word after revins mode is set, and the cursor on beginning of the word, type:
dwi<C-r>"<ESC>
explanation:
dw deleted a word.
i to enter insert mode
<C-r>" to paste the last deleted or yaked text in insert mode, <ESC> to exit insert mode.
remember to :set norevins at the end!

How to comment out a block of code in Python [duplicate]

This question already has answers here:
Why doesn't Python have multiline comments?
(18 answers)
Closed 9 years ago.
Is there a mechanism to comment out large blocks of Python code?
Right now, the only ways I can see of commenting out code are to either start every line with a #, or to enclose the code in triple quotes: """.
The problem with these is that inserting # before every line is cumbersome and """ makes the string I want to use as a comment show up in generated documentation.
After reading all comments, the answer seems to be "No".
Python does not have such a mechanism. Prepend a # to each line to block comment. For more information see PEP 8. Most Python IDEs support a mechanism to do the block-commenting-with-hash-signs automatically for you. For example, in IDLE on my machine, it's Alt+3 and Alt+4.
Don't use triple-quotes; as you discovered, this is for documentation strings not block comments, although it has a similar effect. If you're just commenting things out temporarily, this is fine as a temporary measure.
Hide the triple quotes in a context that won't be mistaken for a docstring, eg:
'''
...statements...
''' and None
or:
if False: '''
...statements...
'''
The only cure I know for this is a good editor. Sorry.
The only way you can do this without triple quotes is to add an:
if False:
And then indent all your code. Note that the code will still need to have proper syntax.
Many Python IDEs can add # for you on each selected line, and remove them when un-commenting too. Likewise, if you use vi or Emacs you can create a macro to do this for you for a block of code.
In JetBrains PyCharm on Mac use Command + / to comment/uncomment selected block of code. On Windows, use CTRL + /.
M-x comment-region, in Emacs' Python mode.
At least in VIM you can select the first column of text you want to insert using Block Visual mode (CTRL+V in non-windows VIMs) and then prepend a # before each line using this sequence:
I#<esc>
In Block Visual mode I moves to insert mode with the cursor before the block on its first line. The inserted text is copied before each line in the block.
In vi:
Go to top of block and mark it with letter a.
Go to bottom of block and mark it with letter b
Then do
:'a,'b s!^!#!
comm='''
Junk, or working code
that I need to comment.
'''
You can replace comm by a variable of your choice that is perhaps shorter, easy to touch-type, and you know does not (and will not) occur in your programs. Examples: xxx, oo, null, nil.
In Visual Studio using the Python Tools for Visual Studio, blocks can be commented out by Ctrl+K, Ctrl+C and uncommented by Ctrl+K, Ctrl+U.
I use Notepad++ on a Windows machine, select your code, type CTRL-K. To uncomment you select code and press Ctrl + Shift + K.
Incidentally, Notepad++ works nicely as a Python editor. With auto-completion, code folding, syntax highlighting, and much more. And it's free as in speech and as in beer!
In Eclipse + PyDev, Python block commenting is similar to Eclipse Java block commenting; select the lines you want to comment and use Ctrl + / to comment. To uncomment a commented block, do the same thing.
Yes, there is (depending on your editor). In PyDev (and in Aptana Studio with PyDev):
Ctrl + 4 - comment selected block
Ctrl + 5 - uncomment selected block
The only mechanism to comment out Python code (understood as code ignored by the interpreter) is the #.
As you say, you can also use string literals, that are not ignored by the interpreter, but can be completely irrelevant for the program execution.
In Eclipse using PyDev, you can select a code block and press Ctrl + #.
Triple quotes are OK to me.
You can use ''' foo ''' for docstrings and """ bar """ for comments or vice-versa to make the code more readable.
Another editor-based solution: text "rectangles" in Emacs.
Highlight the code you want to comment out, then C-x-r-t #
To un-comment the code: highlight, then C-x-r-k
I use this all-day, every day. (Assigned to hot-keys, of course.)
This and powerful regex search/replace is the reason I tolerate Emacs's other "eccentricities".
On Eric4 there is an easy way: select a block, type Ctrl+M to comment the whole block or Ctrl+alt+M to uncomment.
Use a nice editor like SciTe, select your code, press Ctrl + Q and done.
If you don't have an editor that supports block comments you can use a triple quoted string at the start and the end of your code block to 'effectively' comment it out. It is not the best practice though.

Categories