I'm moving from Eclipse to Visual Studio .NET and have found all my beloved hotkeys except two:
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.
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.
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.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With