Edit: This question had been tagged "Tolstoy" in appreciation of the quality and length of my writing:) Just reading the first and the last paragraph should be enough:) If you tend to select and move code with the mouse, the stuff in middle could be interesting to you.
This question is about how you use text editors in general. I’m looking for the best way to delete a plurality of lines of code (no intent to patent it:) This extends to transposing lines, i.e. deleting and adding them somewhere else. Most importantly, I don’t want to be creating any blank lines that I have to delete separately. Sort of like Visual Studio's SHIFT+DELETE feature, but working for multiple lines at once.
Say you want to delete line 3 from following code (tabs and newlines visualized as well). The naïve way would be to select the text between angle brackets:
if (true) {\n
\t int i = 1;\n
\t <i *= 2;>\n
\t i += 3;\n
}\n
Then hit backspace. This creates a blank line. Hit backspace twice more to delete \t and \n.
You end up with:
if (true) {\n
\t int i = 1;\n
\t i += 3;\n
}\n
When you try to select a whole line, Visual Studio doesn't let you select the trailing newline character. For example, placing the cursor on a line and hitting SHIFT+END will not select the newline at the end. Neither will you select the newline if you use your mouse, i.e. clicking in the middle of a line and dragging the cursor all the way to the right. You only select the trailing newline characters if you make a selection that spans at least two lines. Most editors I use do it this way; Microsoft WordPad and Word are counter-examples (and I frequently get newlines wrong when deleting text there; at least Word has a way to display end-of-line and end-of-paragraph characters explicitly).
When using Visual Studio and other editors in general, here’s the solution that currently works best for me:
Using the mouse, I select the characters that I put between angle brackets:
if (true) {\n
\t int i = 1;<\n
\t i *= 2;>\n
\t i += 3;\n
}\n
Hitting backspace now, you delete the line in one go without having to delete any other characters. This works for several contiguous lines at once. Additionally, it can be used for transposing lines. You could drag the selection between the angle brackets to the point marked with a caret:
if (true) {\n
\t int i = 1;<\n
\t i *= 2;>\n
\t i += 3;^\n
}\n
This leaves you with:
if (true) {\n
\t int i = 1;\n
\t i += 3;<\n
\t i *= 2;>\n
}\n
where lines 3 and 4 have switched place.
There are variations on this theme. When you want to delete line 3, you could also select the following characters:
if (true) {\n
\t int i = 1;\n
<\t i *= 2;\n
>\t i += 3;\n
}\n
In fact, this is what Visual Studio does if you tell it to select a complete line. You do this by clicking in the margin between your code and the column where the red circles go which indicate breakpoints. The mouse pointer is mirrored in that area to distinguish it a little better, but I think it's too narrow and physically too far removed from the code I want to select.
Maybe this method is useful to other people as well, even if it only serves to make them aware of how newlines are handled when selecting/deleting text:) It works nicely for most non-specialized text editors. However, given the vast amount of features and plugins for Visual Studio (which I use most), I'm sure there is better way to use it to delete and move lines of code. Getting the indentation right automatically when moving code between different blocks would be nice (i.e. without hitting "Format Document/Selection"). I'm looking forward to suggestions; no rants on micro-optimization, please:)
Summary of Answers
With respect to Visual Studio: Navigating well with the cursor keys.
The solution that would best suit my style of going over and editing code is the Eclipse way:
You can select several consecutive lines of code, where the first and the last selected line may be selected only partially. Pressing ALT+{up,down} moves the complete lines (not just the selection) up and down, fixing indentation as you go. Hitting CTRL+D deletes the lines completely (not just the selection) without leaving any unwanted blank lines. I would love to see this in Visual Studio!
In Emacs:
kill-line C-k
transpose-lines C-x C-t
C-a C-k C-k -- kill whole line including newline (or kill-whole-line by C-S-backspace).
C-u <number> C-k -- kill <number> of lines (including newlines).
C-y -- yank back the most recently killed text (aka paste)
In VIM:
Delete the whole line including the newline: dd
Transpose lines: dd p
You can always prefix any command with a number to repeat it, so to delete 10 lines do:
10 dd
You can also specify a range of lines to delete. For instance, to delete lines 10-15:
:10,15d
Or you can move the lines, for instance move lines 10-15 below line 20:
:10,15m20
Or you can copy the lines:
:10,15t20
What I do is, starting with the cursor at the start of the line (in some editors you have to press home twice to do this), hold shift and press down until all lines that I want to delete are selected. Then I press delete.
In Eclipse you can ALT-↓ or ALT-↑ to move a line. I find this incredibly useful, as well as ALT-SHIFT-{↓, ↑} to copy a line. In addition, it doesn't wreck your clipboard. It even corrects indentation as the line is moving!
Adding to the existing vim answer, you can use d along with any cursor movement command to delete from the cursor's current position to the new position. For example, to delete...
...to end-of-paragraph (usually meaning "to the next blank line"): d}
...the line containing the cursor and the next 5 lines: d5j
...a set of parentheses, braces, etc. and its contents: d% (with the cursor on the opening or closing paren/brace/etc.)
...to the third appearance of the word "foo": d3/foo
It's quite flexible.
Learn to use your cursor keys.
For moving lines I do the following:
Use ↑/↓to move to the line you want to copy.
Hit Home if not there already, and again if it places the cursor after whitespace.
Then press Shift+↓ to select the line (or lines) you want to move
Ctrl+X to cut the line.
Move Up/Down to the line you want to insert
Ctrl+V
This should work in pretty much any text editor on Windows.
When deleting lines I still tend to use Ctrl+X (although I guess I also use backspace) as the above is so ingrained in how I edit, and it's also more forgiving.
(Although I find them disorienting on the occasions I use Macs, I think Apple might have been on to something with the way they've set up the Home/End, skip word shortcuts on Macs)
Ctrl+Shift+L removes line without copying it to the buffer.
in Eclipse i use CTRL+ D to delete a single line (or a couple)
for many lines i'll select them with the mouse or with SHIFT + ARROW then press the DEL key.
In addition to the above, use Resharper for Visual Studio to do what you want. Best VS plugin you will find ever. It provides a bunch of different commands that help with moving/deleting/copying code here there and everywhere. Not to mention refactor/generate/etc code.
Ctrl-Shift-Alt ↑or ↓ will move a method up or down, line up or down, etc.
Shift-Del - deletes the current line, but puts it in the clipboard (unless you modify your settings to not do this - I'm trying to recall if this is a VS standard shortcut, not just Resharper - been too long).
Ctrl-C, Ctrl-X without selecting copies/cuts the current line.
And on and on...
See http://www.jetbrains.com/resharper/docs/ReSharper40DefaultKeymap2.pdf for a full list.
Using the Brief keyboard mapping this is done using the Alt+L to mark the line and the - key on the numeric keypad (or Alt+D) to cut the line to clipboard. The cut will remove the line entirely, including the newline character.
Hitting the Ins key on the numeric keypad would put the line back into the document including the newline character.
IMHO Brief is a really well designed keyboard mapping.
PS: I think MSVC has an option to emulate the Brief keyboard mapping.
In Emacs, in addition to C-k (and C-k with a numeric prefix arg, to kill N lines), you can just use the mouse:
To kill one line: triple-click it, then right-click twice
To kill multiple lines: triple-click the first line, then right-click on the last line ("first" line can be after the "last" line -- "first" here means first one you click)
Related
I am on Ubuntu and use Gvim. Based on my understanding,I have set tab to expand to 4 spaces. I did not even touch the line that has create_namespace but git diff shows it as shifted by a character. It seems perfectly fine in the editor or when I run cat. Same issue is when I added a new line of txt cluster_token and it shows as shifted by a character in git diff. I have wasted hours trying to understand this silly issue but no clue. What is the issue and how do I fix it?
- echo "--create_namespace"
+ echo "--create_namespace" //Did not even touch this line
echo "--all"
echo "--custom_merge_pipeline_commands"
+ echo "--cluster_token" //Looks fine in editor
If this is TL;DR, skip down to the bolded text below.
As I noted in a comment, the issue of spaces vs tabs sets off flame wars, so I'm going to attempt to be completely neutral on the subject. (Note: I did say attempt. :-) ) It's also worth covering a bit of history, i.e., how we got here in the first place. Also, there is an entirely separate, though currently beta, StackExchange web site devoted to vi / vim at https://vi.stackexchange.com/ so I am not going to get into the many vim settings available here.
First, note that tabs go back to the days of mechanical typewriters (well, probably even before then).
Different models had different features, but most had a key labeled TAB that, when pressed, caused the platen—the rubber roller that holds the paper—to slide leftward (assuming a Western-style, left-to-right carriage typewriter) from its current position to the next tab stop. Tab stops were set mechanically, since all of this was run by wires and springs. Since the type bars would always strike the paper at the center where the ribbon was held against the paper, sliding the platen leftward has the effect of making the next character come out somewhere to the right. How far to the right, depends on the current column and, of course, the tab stop settings.
Early computer interfaces used or emulated mechanical typewriters—well, more precisely, teletype interrfaces—sometimes complete with the exact same mechanically-controlled tab stops. When glass ttys came out, they tended to emulate the existing TTYs. Over time, the terminals got smarter, to the point where some had software-adjustable tab stops.
Others, however, limited tab stops in software to simply "every N columns", where N was variable. DEC chose 10 for some of their early systems, but 8 proved more popular and became the default. Here, sending an ASCII TAB (code 9 decimal) byte to the display terminal caused the terminal to move the cursor from whichever column it was in now, to one up-to-but-not-exceeding N (usually 8) characters to the right. (The behavior of a cursor close to the end of the physical screen line varied, and still varies in software emulations, but the VT100 behavior is pretty common now.)
We no longer use any of these bits of hardware—at least, not commonly—but we do emulate them. Pressing the TAB key in an editor tends to move the cursor to "the next tab stop", wherever that may be. Terminal emulators will emulate whatever terminal—often, again, the VT100, which has variable tab stops (set via escape sequences) but defaults to every eighth column (columns 9, 17, 25, and so on, if we number the first column 1—as is traditional—instead of the proper mathematical column zero :-) ).
For storing text in files, however, there is an option: we can store the literal ASCII TAB character (or the Unicode equivalent which is U+0009), or we can store however many spaces it might take to get to the selected column. If we store a literal TAB, it is up to whatever it is that displays the file to choose which column is the desired column. If we store literal space characters, whatever is displaying the file must display that many space characters.1 The effect is that if we store literal TABs, the display depends on previous output (since the cursor column depends on previous output), but if we store literal spaces, it does not.
Meanwhile, when git diff displays lines, it inserts one character in front of each line. If the line being displayed starts with a literal TAB followed by the word old, what happens is that git diff writes a space or plus or minus character, then a TAB, then the next character. Assuming your terminal has its tab-stops at columns 9, 17, 25, and so on, the character after the TAB shows up in column 9:
0 1
1234567890123456789
- old
If, on the other hand, the line in the file starts with eight spaces followed by the word new, what you see is the git diff character, then eight spaces, then the word in column 10:
0 1
1234567890123456789
+ new
Stacking these atop one another we get:
0 1
1234567890123456789
- old
+ new
which is what you are seeing. This means that your claim:
- echo "--create_namespace"
+ echo "--create_namespace" //Did not even touch this line
is at best half-true: you might not have touched the line, but your editor did. It replaced at least one literal TAB character with spaces. (We cannot tell from here how many such characters were changed—perhaps, for instance, it replaced one TAB with four spaces, leaving four existing spaces in place, if you have everything rigged up to use columns 5, 9, 13, 17, and so on.)
1It is now time to avoid an entire separate aside on fixed vs variable pitch fonts. :-)
This problem has not always been around, and I can find no option in VS or ReSharper to correct it, but when I use the mouse to place the cursor on a shortish line of code, and I place the cursor near the end of the line, in whitespace, it stays there, instead of jumping back to the last character on the line.
You can uncheck the option Texteditor -> All Languages -> General -> Enable virtual space in Visual Studio. This way your cursor will always be placed at the last character of a line when you click anywhere in the whitespace area at the end of a line.
Note however if your line ends with whitespaces you actually typed in, it will place the cursor after the last actual whitespace of that line. Use Ctrl + Left Arrow to jump to the last actual character of that line.
You can use Alt + Backspace to quickly delete all whitespaces at the end of a line.
Very close to reverse of this question. I prefer coding with 2-whitespace indentation, but need to have files indented with tabs to align with project convention. What I would like to do is preferably automatically convert 2 spaces upon entry to tab symbol in Notepad++ and have the editor configured to tab length of 2.
A possible manual way for doing this could be Edit->Blank Operations->Space to TAB but this converts all of my spaces to tabs, even those of length 1 - which are, for example, spaces between function arguments, not just leading spaces.
In a perfect case scenario I'm trying to achieve formatting style as described in this question, but with typing just spaces and the editor taking care of the rest.
I'm on Notepad++ 6.0, but willing to upgrade if this helps
Let me complete the answer of Ari Okkonen to add a workaround to the problem commented by Sergii Zaskaleta of mixed tabs and spaces at the beginning of the line.
Settings->Preferences->Tab Settings->Tab size: 2 (if not already)
Edit->Blank Operations->Space to TAB (Leading)
Select a block of lines of text with the problem of mixed spaces and tabs. Press [Tab] and [Shift]+[Tab] to add and remove a tab from each line. In the process, the leading spaces had been converted to tabs.
A manual way that seems to work: After having edited the file before saving you may try (Works in Notepad++ v6.8.3):
Settings->Preferences->Tab Settings->Tab size: 2 (if not already)
Edit->Blank Operations->Space to TAB (Leading)
How can I make code completion case-sensitive?
How can I make Ctrl-k kill the content of the line and the new line character?
How can I make backspace always delete only one character, no matter what it is? Right now, it deletes spaces in chunks equal to my indent level.
How to change the indentation style in file templates? I like to have the opening brace on its own line.
How can I make the font aliased?
I'm using Xcode 3.2.2.
EDIT: Issues 2, 4, and 5 are solved. 1 and 3 are still open.
EDIT2: ad.3. Yes, I set Xcode to use spaces, not tabs.
3.
Look in Preferences : Key Bindings : Text Key Bindings : Indent Friendly Delete Backwards
If the delete key is mapped to this entry change it to plain Delete Backwards.
2.
In that same preference area, you can see that there is no delete line option to map ^k to.
How can I make code completion case-sensitive?
I don't think that's possible.
How can I make Ctrl-k kill the content of the line and the new line character?
I can't answer that one, you might need to write a script to do it.
How can I make backspace always delete only one character, no matter what it is? Right now, it deletes spaces in chunks equal to my indent level.
Backspace always deletes one character. It sounds like your file has tab characters in it, each one of which takes up the space of 4 spaces by default. You can tell Xcode to use spaces instead by de-selecting Tab key inserts tab, not spaces in the Indentation preference panel.
How to change the indentation style in file templates? I like to have the opening brace on its own line.
You need to create custom file templates. You can find the Xcode templates here:
/Developer/Library/Xcode/Templates/File Templates
You need to copy the appropriate templates to this location:
~/Library/Application Support/Developer/Shared/Xcode/File Templates
You can then edit the template files to use whatever indents you like.
How can I make the font aliased?
You need to use a font that has aliased characters. Try Monaco at 9 or 10 points.
What is the best way to move around on a given very long command line in the terminal?
Say I used the arrow key or Ctrl-R to get this long command line:
./cmd --option1 --option2 --option3 --option4 --option5 --option6 --option7 --option8 --option9 --option10 --option11 --option12 --option13 --option14 --option15 --option16 --option17 --option18 --option19 --option20 --option21 --option22 --option23 --option24 --option25 --option26 --option27 --option28 --option29 --option30 --option31 --option32 --option33 --option34 --option35 --option36 --option37 --option38 --option39 --option40 --option41 --option42 --option43 --option44 --option45 --option46 --option47 --option48 --option49 --option50
Now I need to move (starting from the beginning or the end of the line) the cursor to --option25 to modify something there.
What is the fastest way to get there? What I usually do is Ctrl-A to get to the beginning and then repeatedly Alt-F to move forward, word by word (or Ctrl-E to go the end and Alt-B to then go backward). But on a long line that takes too much time. There must be a way to search and jump directly to the part I need to modify, e.g. option25?
To be clear, you don't want a "fast way to move the cursor on a terminal command line".
What you actually want is a fast way to navigate over command line in you shell program.
Bash is very common shell, for example.
It uses Readline library to implement command line input. And so to say, it is very convenient to know Readline bindings since it is used not only in bash. For example, gdb also uses Readline to process input.
In Readline documentation you can find all navigation related bindings (and more):
http://www.gnu.org/software/bash/manual/bash.html#Readline-Interaction
Short copy-paste if the link above goes down:
Bare Essentials
Ctrl-b Move back one character.
Ctrl-f Move forward one character.
[DEL] or [Backspace] Delete the character to the left of the cursor.
Ctrl-d Delete the character underneath the cursor.
Ctrl-_ or C-x C-u Undo the last editing command. You can undo all the way back to an empty line.
Movement
Ctrl-a Move to the start of the line.
Ctrl-e Move to the end of the line.
Meta-f Move forward a word, where a word is composed of letters and digits.
Meta-b Move backward a word.
Ctrl-l Clear the screen, reprinting the current line at the top.
Kill and yank
Ctrl-k Kill the text from the current cursor position to the end of the line.
M-d Kill from the cursor to the end of the current word, or, if between words, to the end of the next word. Word boundaries are the same as those used by M-f.
M-[DEL] Kill from the cursor the start of the current word, or, if between words, to the start of the previous word. Word boundaries are the same as those used by M-b.
Ctrl-w Kill from the cursor to the previous whitespace. This is different than M- because the word boundaries differ.
Ctrl-y Yank the most recently killed text back into the buffer at the cursor.
M-y Rotate the kill-ring, and yank the new top. You can only do this if the prior command is C-y or M-y.
M is Meta key.
For Max OS X Terminal you can enable "Use option as meta key" in Settings/Keyboard for that.
For Linux its more complicated.
Update
Also note, that Readline can operate in two modes:
emacs mode (which is the default)
vi mode
To switch Bash to use vi mode:
$ set -o vi
Personaly I prefer vi mode since I use vim for text editing.
Bonus
In macOS Terminal app (and in iTerm too) you can Option-Click to move the cursor (cursor will move to clicked position). This even works inside vim.
Since this hasn't been closed yet, here are a few more options.
Use Ctrl+x followed by Ctrl+e to open the current line in the editor specified by $FCEDIT or $EDITOR or emacs (tried in that order).
If you ran the command earlier, hit Ctrl+r for a reverse history search and type option25 (in this case). The line will be displayed. Hit Tab to start editing at this point.
Use history expansion with the s/// modifier. E.g. !-2:s/--option25/--newoption/ would rerun the second-to-last command, but replace option25. To modify the last ./cmd command, use the !string syntax: !./cmd:s/--option25/--newoption/
Any delimiter may be used in place of / in the substitution.
If editing the previous line, you can use quick substitution: ^--option25^--newoption
Character search. This was mentioned by Pax, and can be done in regular emacs-mode with Ctrl+] for forward search, and Ctrl+Alt+] for backward search.
I recommend the second option. Ctrl+r is really handy and fast, no mucking about with editors, and you see the results before the command is run (unlike the history expansions).
Hold down the Option key and click where you'd like the cursor to move, and Terminal rushes the cursor that precise spot.
I tend to prefer vi editing mode (since those keystrokes are embedded into my spinal cord now (the brain's not used at all), along with the CTRL-K, CTRL-X from WordStar 3.3 :-). You can use the command line set -o vi to activate it (and set -o emacs to revert).
In Vi, it would be (ESC-K to get the line up first of course) "f5;;B" (without the double quotes).
Of course, you have to understand what's on the line to get away with this. Basically, it's
f5 to find the first occurrence of "5" (in --option5).
; to find the next one (in --option15).
; to find the next one (in --option25).
B to back up to the start of the word.
Let's see if the emacs aficionados can come up with a better solution, less than 5 keystrokes (although I don't want to start a religious war).
Have you thought about whether you'd maybe like to put this horrendously long command into a script? :-)
Actually, I can go one better than that: "3f5B" to find the third occurrence of "5" then back up to the start of the word.
Use Meta-b / Meta-f to move backward/forward by a word respectively.
In OSX, Meta translates as ESC, which sucks.
But alternatively, you can open terminal preferences -> settings -> profile -> keyboard and check "use option as meta key"
After running the command once, run fc
It will launch $EDITOR with the previous command, then you can use your regular editor to modify the command. When you save and exit, the file will be executed.
..but, as Pax said - the command line isn't particularly good for editing absurdly long lines - why not make the command into a script?
If you want to move forward a certain number of words, hit M-<n> (M- is for Meta and its usually the escape key) then hit a number. This sends a repeat argument to readline, so you can repeat whatever command you want - if you want to go forward then hit M-<n> M-f and the cursor will move forward <n> number of words.
E.g.
$|echo "two three four five six seven"
$ M-4
(arg: 4) echo "two three four five six seven"
$ M-f
$ echo "two three four| five six seven"
So for your example from the cursor at the beginning of the line you would hit, M-26 M-f and your cursor would be at --option25| -or- from the end of the line M-26 M-b would put your cursor at --|option25
Incremental history searching
in terminal enter:
gedit ~/.inputrc
then copy paste and save
"\e[A": history-search-backward
"\e[B": history-search-forward
"\e[C": forward-char
"\e[D": backward-char
all you need to do to find a previous command is to enter say the first 2 or 3 letters and upward arrow will take you there quickly say i want:
for f in *.mid ; do timidity "$f"; done
all i need to do is enter
fo
and hit upward arrow command will soon appear
It might not be the fastest, but this need to be here, some reading about ANSI cursor movements
ANSI escape sequences allow you to move the cursor around the screen at will. This is more useful for full screen user interfaces generated by shell scripts, but can also be used in prompts. The movement escape sequences are as follows:
- Position the Cursor:
\033[<L>;<C>H
Or
\033[<L>;<C>f
puts the cursor at line L and column C.
- Move the cursor up N lines:
\033[<N>A
- Move the cursor down N lines:
\033[<N>B
- Move the cursor forward N columns:
\033[<N>C
- Move the cursor backward N columns:
\033[<N>D
- Clear the screen, move to (0,0):
\033[2J or \033c
- Erase to end of line:
\033[K
- Save cursor position:
\033[s
- Restore cursor position:
\033[u
(...)
Try putting in the following line of code at the prompt (it's a little clearer what it does if the prompt is several lines down the terminal when you put this in): echo -en "\033[7A\033[1;35m BASH \033[7B\033[6D" This should move the cursor seven lines up screen, print the word " BASH ", and then return to where it started to produce a normal prompt.
Examples:
Move the cursor back 7 lines:
echo -e "\033[7A"
Move the cursor to line 10, column 5:
echo -e "\033[10;5H"
Quickly echo colors codes, to colorize a program:
echo -e "\033[35;42m" ; ifconfig
using option key and using a click the place you want to place the cursor with mouse or touchpad is you are using Mac build-in terminal.
One option is to use M-x shell in emacs. That provides all editing facilities and keystrokes that emacs has, so C-s can be used to search the text option25, for example.
(But I'd still prefer to be in the real terminal shell instead if someone can point me to good search and edit facilities.)
Use the mouse
Sometimes, the easiest way to edit a commandline is using a mouse. Some previous answers give a command to open your current line in your $EDITOR. For me (zhs with grml config) that combination is Alt+e. If you enable mouse in your editor, you can make use of it.
To enable mouse in Vim, add this to your ~/.vimrc
set mouse=a
set ttymouse=xterm2
If you then want to do a text selection in terminal (instead of passing the mouseclick to vim), hold Shift when you click; this is terminal specific, of course.
Sysadmins should not be afraid of the mouse.
In Cygwin, you can activate such feature by right-clicking the window. In the pop-up window, select Options... -> Mouse -> activate Clicks place command line cursor -> Apply.
From now on, simply clicking the left mouse button at some position within the command line will place the cursor there.
first:
export EDITOR='nano -m'
then:
CTRL+X CTRL+E in sequence.
You current line will open in nano editor with mouse enable. You can click in any part of text and edit
then CTRL+X to exit and y to confirm saving.
I made a script to make the command line cursor move on mouse click :
Enable xterm mouse tracking reporting
Set readline bindings to consume the escape sequence generated by clicks
It can be found on github
More info on another post
Will work if echo -e "\e[?1000;1006;1015h" # Enable tracking print escape sequences on terminal when clicking with mouse