Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio: hotkeys to move line up/down and move through recent changes

I'm moving from Eclipse to Visual Studio .NET and have found all my beloved hotkeys except two:

  • in Eclipse you can press ALT- and ALT- to visit recent changes you have made, something I use frequently to go back to where I was in some other file and then return. Apparently in VS.NET the CTRL-- and CTRL-SHIFT-- do this but they don't seem to always work (e.g. on laptop, may be a numkey issue with the minus) and don't seem to follow the same algorithm of "where I was" as I am used to in Eclipse. Has anyone gotten this to work and rely on it daily, etc.?
  • in Eclipse, to move a line up or down you press ALT-uparrow or ALT-downarrow and you just move it through the code until you get it to where you want it, very nice. Also to make a copy of a line, you can press SHIFT-ALT-uparrow or SHIFT-ALT-downarrow. Both of these hotkeys even work for block of lines that you have selected.

Has anyone discovered these hotkey features in Visual Studio .NET?

A D D E N D U M :

An example of when you would use the second feature described above is to move the bottom line here up into the for loop. In Eclipse, you would put the cursor on the Console.WriteLine and then press ALT-(uparrow), I use that all the time: one key stroke to move lines up and down.

for (int i = 0; i < 10; i++) {  } Console.WriteLine(i); 

Ok, extrapolating Charlie's idea with no-selection-ctrl-c to select a line, in Visual Studio you could put your cursor on Console.WriteLine, (no selection) press CTRL-X and then move up and press CTRL-V.

like image 561
Edward Tanguay Avatar asked Nov 24 '08 05:11

Edward Tanguay


People also ask

How do you move a line up or down in Visual Studio Windows code?

You could open File --> Preferences --> Keyboard Shorcuts in VS Code and change Move Line Up/Down settings to something else. Thanks! Set them to ctrl+shift+UpArrow/DownArrow.

What is Ctrl Shift F in Visual Studio?

Ctrl-Shift-F is used to find all the ocuurance of a string with in entire solution and display find result window as shown below. Ctrl-F is used to find a string in the current document, project and all open documents one by one.


2 Answers

The answers proposed work, but none of them are as nice as eclipse with regard to how they preserve the existing paste buffer, the currently selected characters, and they do not allow the user to operate upon a range of lines. Here is a solution I came up with that preserves the paste buffer, the current character selection, and works with or without a selection (that may or may not span multiple rows):

'' Duplicates the current line (or selection of lines) and places the copy '' one line below or above the current cursor position (based upon the parameter) Sub CopyLine(ByVal movingDown As Boolean)     DTE.UndoContext.Open("CopyLine")     Dim objSel As TextSelection = DTE.ActiveDocument.Selection      ' store the original selection and cursor position     Dim topPoint As TextPoint = objSel.TopPoint     Dim bottomPoint As TextPoint = objSel.BottomPoint     Dim lTopLine As Long = topPoint.Line     Dim lTopColumn As Long = topPoint.LineCharOffset     Dim lBottomLine As Long = bottomPoint.Line     Dim lBottomColumn As Long = bottomPoint.LineCharOffset()      ' copy each line from the top line to the bottom line     Dim readLine As Long = lTopLine     Dim endLine As Long = lBottomLine + 1     Dim selectionPresent As Boolean = ((lTopLine <> lBottomLine) Or (lTopColumn <> lBottomColumn))     If (selectionPresent And (lBottomColumn = 1)) Then         ' A selection is present, but the cursor is in front of the first character         ' on the bottom line. exclude that bottom line from the copy selection.         endLine = lBottomLine     End If      ' figure out how many lines we are copying, so we can re-position     ' our selection after the copy is done     Dim verticalOffset As Integer = 0     If (movingDown) Then         verticalOffset = endLine - lTopLine     End If      ' copy each line, one at a time.     ' The Insert command doesn't handle multiple lines well, and we need     ' to use Insert to avoid autocompletions     Dim insertLine As Long = endLine     While (readLine < endLine)         ' move to read postion, and read the current line         objSel.MoveToLineAndOffset(readLine, 1)         objSel.EndOfLine(True) 'extend to EOL         Dim lineTxt As String = objSel.Text.Clone         ' move to the destination position, and insert the copy         objSel.MoveToLineAndOffset(insertLine, 1)         objSel.Insert(lineTxt)         objSel.NewLine()         ' adjust the read & insertion points         readLine = readLine + 1         insertLine = insertLine + 1     End While      ' restore the cursor to original position and selection     objSel.MoveToLineAndOffset(lBottomLine + verticalOffset, lBottomColumn)     objSel.MoveToLineAndOffset(lTopLine + verticalOffset, lTopColumn, True)     DTE.UndoContext.Close() End Sub  '' Duplicates the current line (or selection of lines) and places the copy '' one line below the current cursor position Sub CopyLineDown()     CopyLine(True) End Sub  '' Duplicates the current line (or selection of lines) and places the copy '' one line above the current cursor position Sub CopyLineUp()     CopyLine(False) End Sub   '' Moves the selected lines up one line. If no line is '' selected, the current line is moved. '' Sub MoveLineUp()     DTE.UndoContext.Open("MoveLineUp")     Dim objSel As TextSelection = DTE.ActiveDocument.Selection     ' store the original selection and cursor position     Dim topPoint As TextPoint = objSel.TopPoint     Dim bottomPoint As TextPoint = objSel.BottomPoint     Dim lTopLine As Long = topPoint.Line     Dim lTopColumn As Long = topPoint.LineCharOffset     Dim lBottomLine As Long = bottomPoint.Line     Dim lBottomColumn As Long = bottomPoint.LineCharOffset()      Dim textLineAbove As TextSelection = DTE.ActiveDocument.Selection     textLineAbove.MoveToLineAndOffset(lTopLine - 1, 1, False)     textLineAbove.MoveToLineAndOffset(lTopLine, 1, True)     Dim indentChange As Integer = CountIndentations(textLineAbove.Text) * -1      ' If multiple lines are selected, but the bottom line doesn't     ' have any characters selected, don't count it as selected     Dim lEffectiveBottomLine = lBottomLine     If ((lBottomColumn = 1) And (lBottomLine <> lTopLine)) Then         lEffectiveBottomLine = lBottomLine - 1     End If      ' move to the line above the top line     objSel.MoveToLineAndOffset(lTopLine - 1, 1)     ' and move it down, until its below the bottom line:     Do         DTE.ExecuteCommand("Edit.LineTranspose")     Loop Until (objSel.BottomPoint.Line >= lEffectiveBottomLine)     ' Since the line we are on has moved up, our location in the file has changed:     lTopLine = lTopLine - 1     lBottomLine = lBottomLine - 1      IndentBlockAndRestoreSelection(objSel, lBottomLine, lBottomColumn, lTopLine, lTopColumn, indentChange)      DTE.UndoContext.Close() End Sub  '' Moves the selected lines down one line. If no line is '' selected, the current line is moved. '' Sub MoveLineDown()     DTE.UndoContext.Open("MoveLineDown")     Dim objSel As TextSelection = DTE.ActiveDocument.Selection     ' store the original selection and cursor position     Dim topPoint As TextPoint = objSel.TopPoint     Dim bottomPoint As TextPoint = objSel.BottomPoint     Dim lTopLine As Long = topPoint.Line     Dim lTopColumn As Long = topPoint.LineCharOffset     Dim lBottomLine As Long = bottomPoint.Line     Dim lBottomColumn As Long = bottomPoint.LineCharOffset()      ' If multiple lines are selected, but the bottom line doesn't     ' have any characters selected, don't count it as selected     Dim lEffectiveBottomLine = lBottomLine     If ((lBottomColumn = 1) And (lBottomLine <> lTopLine)) Then         lEffectiveBottomLine = lBottomLine - 1     End If      Dim textLineBelow As TextSelection = DTE.ActiveDocument.Selection     textLineBelow.MoveToLineAndOffset(lEffectiveBottomLine + 1, 1, False)     textLineBelow.MoveToLineAndOffset(lEffectiveBottomLine + 2, 1, True)     Dim indentChange As Integer = CountIndentations(textLineBelow.Text)       ' move to the bottom line     objSel.MoveToLineAndOffset(lEffectiveBottomLine, 1)     ' and move it down, which effectively moves the line below it up     ' then move the cursor up, always staying one line above the line     ' that is moving up, and keep moving it up until its above the top line:     Dim lineCount As Long = lEffectiveBottomLine - lTopLine     Do         DTE.ExecuteCommand("Edit.LineTranspose")         objSel.LineUp(False, 2)         lineCount = lineCount - 1     Loop Until (lineCount < 0)     ' Since the line we are on has moved down, our location in the file has changed:     lTopLine = lTopLine + 1     lBottomLine = lBottomLine + 1      IndentBlockAndRestoreSelection(objSel, lBottomLine, lBottomColumn, lTopLine, lTopColumn, indentChange)      DTE.UndoContext.Close() End Sub  '' This method takes care of indenting the selected text by the indentChange parameter '' It then restores the selection to the lTopLine:lTopColumn - lBottomLine:lBottomColumn parameter. '' It will adjust these values according to the indentChange performed Sub IndentBlockAndRestoreSelection(ByVal objSel As TextSelection, ByVal lBottomLine As Long, ByVal lBottomColumn As Long, ByVal lTopLine As Long, ByVal lTopColumn As Long, ByVal indentChange As Integer)     ' restore the cursor to original position and selection     objSel.MoveToLineAndOffset(lBottomLine, lBottomColumn)     objSel.MoveToLineAndOffset(lTopLine, lTopColumn, True)     If (indentChange = 0) Then         ' If we don't change the indent, we are done         Return     End If      If (lBottomLine = lTopLine) Then         If (indentChange > 0) Then             objSel.StartOfLine()         Else             objSel.StartOfLine()             objSel.WordRight()         End If     End If     objSel.Indent(indentChange)      ' Since the selected text has changed column, adjust the columns accordingly:     ' restore the cursor to original position and selection     Dim lNewBottomColumn As Long = (lBottomColumn + indentChange)     Dim lNewTopColumn As Long = (lTopColumn + indentChange)     ' ensure that we we still on the page.     ' The "or" clause makes it so if we were at the left edge of the line, we remain on the left edge.     If ((lNewBottomColumn < 2) Or (lBottomColumn = 1)) Then         ' Single line selections, or a bottomColumn that is already at 1 may still have a new BottomColumn of 1         If ((lTopLine = lBottomLine) Or (lBottomColumn = 1)) Then             lNewBottomColumn = 1         Else             ' If we have multiple lines selected, don't allow the bottom edge to touch the left column,             ' or the next move will ignore that bottom line.             lNewBottomColumn = 2         End If     End If     If ((lNewTopColumn < 2) Or (lTopColumn = 1)) Then         lNewTopColumn = 1     End If      ' restore the selection to the modified selection     objSel.MoveToLineAndOffset(lBottomLine, lNewBottomColumn)     objSel.MoveToLineAndOffset(lTopLine, lNewTopColumn, True) End Sub   '' This method counts the indentation changes within the text provided as the paramter Function CountIndentations(ByVal text As String) As Integer     Dim indent As Integer = 0     While (Text.Length > 0)         If (Text.StartsWith("//")) Then             Dim endOfLine As Integer = Text.IndexOf("\n", 2)             If (Equals(endOfLine, -1)) Then                 ' The remaining text is all on one line, so the '//' terminates our search                 ' Ignore the rest of the text                 Exit While             End If             ' continue looking after the end of line             Text = Text.Substring(endOfLine + 1)         End If          If (Text.StartsWith("/*")) Then             Dim endComment As Integer = Text.IndexOf("*/", 2)             If (Equals(endComment, -1)) Then                 ' This comment continues beyond the length of this line.                 ' Ignore the rest of the text                 Exit While             End If             ' continue looking after the end of this comment block             Text = Text.Substring(endComment + 1)         End If          If (Text.StartsWith("{")) Then             indent = indent + 1         Else             If (Text.StartsWith("}")) Then                 indent = indent - 1             End If         End If         Text = Text.Substring(1)     End While     Return indent End Function 

I edited this post to add the UndoContext mechanism (suggested by Nicolas Dorier) at the beginning of the MoveLineUp() and MoveLineDown() methods and closing it at their end. 11/23/11 - I updated this again to allow the moved lines to indent themselves as you cross bracket boundaries

like image 51
Paul Ostrowski Avatar answered Sep 27 '22 18:09

Paul Ostrowski


For anyone looking for a way to do this in Visual Studio 2010, the free Visual Studio 2010 Pro Power Tools extension adds the capability to move lines up and down.

http://visualstudiogallery.msdn.microsoft.com/en-us/d0d33361-18e2-46c0-8ff2-4adea1e34fef

like image 35
Polshgiant Avatar answered Sep 27 '22 19:09

Polshgiant