Visual Studio: горячие клавиши для перемещения строки вверх / вниз и перемещения по последним изменениям - PullRequest
40 голосов
/ 24 ноября 2008

Я перехожу из Eclipse в Visual Studio .NET и обнаружил все мои любимые горячие клавиши, кроме двух:

  • в Eclipse вы можете нажать ALT - и ALT - , чтобы просмотреть последние сделанные вами изменения, которыми я пользуюсь часто, чтобы вернуться туда, где я был в каком-то другом файле, а затем вернуться. Видимо в VS.NET CTRL - - и CTRL - SHIFT - - делают это, но они не кажется, не всегда работает (например, на ноутбуке, может быть проблема с минусом) и, похоже, не следует тому же алгоритму «где я был», как я привык в Eclipse. Кто-нибудь заставил это работать и полагаться на это ежедневно и т. Д.?
  • в Eclipse, чтобы переместить линию вверх или вниз, вы нажимаете ALT - вверх или ALT - вниз и просто двигаетесь это через код, пока вы не получите его там, где вы хотите, очень приятно. Также, чтобы сделать копию строки, вы можете нажать SHIFT - ALT - вверх или SHIFT - ALT - DownArrow . Обе эти горячие клавиши работают даже на выбранный вами блок строк.

Кто-нибудь обнаружил эти функции горячих клавиш в Visual Studio .NET?

A D D E N D U M:

Примером использования второй функции, описанной выше, является перемещение нижней строки здесь в цикл for. В Eclipse вы должны навести курсор на Console.WriteLine и затем нажать ALT- (стрелка вверх), я использую это все время: одно нажатие клавиши для перемещения линий вверх и вниз.

for (int i = 0; i < 10; i++) {

}
Console.WriteLine(i);

Хорошо, экстраполируя идею Чарли с помощью no-selection-ctrl-c, чтобы выделить строку, в Visual Studio вы могли бы навести курсор на Console.WriteLine, (без выбора) нажать CTRL - X , а затем поднимитесь и нажмите CTRL - V .

Ответы [ 9 ]

50 голосов
/ 10 июня 2009

Ответы предполагают работу, но ни один из них не так хорош, как затмение, в отношении того, как они сохраняют существующий буфер вставки, выбранные в данный момент символы, и они не позволяют пользователю работать с диапазоном строк. Вот решение, которое я придумала, которое сохраняет буфер вставки, текущий выбор символов и работает с выделением или без него (которое может занимать или не занимать несколько строк):

'' 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

Я отредактировал этот пост, добавив механизм UndoContext (предложенный Николасом Дориером) в начале методов MoveLineUp () и MoveLineDown () и закрыв его в конце. 23.11.11 - Я обновил это снова, чтобы позволить перемещенным линиям отступать, когда вы пересекаете границы скобок

16 голосов
/ 13 июля 2010

Для тех, кто ищет способ сделать это в Visual Studio 2010, бесплатное расширение Power Tools для Visual Studio 2010 Pro добавляет возможность перемещения строк вверх и вниз.

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

14 голосов
/ 24 ноября 2008

Если вы еще не нашли его, место установки этих сочетаний клавиш находится в разделе Инструменты | Варианты | Окружающая среда | Клавиатура. Множество удобных команд можно найти, просто просматривая список, хотя, к сожалению, я никогда не нашел хороших ссылок для описания того, для чего предназначена каждая команда.

Что касается конкретных команд:

  • Я полагаю, что команды перехода вперед / назад, на которые вы ссылаетесь, это View.NavigateBackward и View.NavigateForward. Если ваша клавиатура не взаимодействует с привязками клавиш VS, вы можете переназначить их на предпочитаемые вами клавиши Eclipse. К сожалению, я не знаю, как изменить алгоритм, который он использует, чтобы на самом деле решить, куда идти.

  • Я не думаю, что есть встроенная команда для дублирования строки, но нажатие Ctrl + C без выделенного текста скопирует текущую строку в буфер обмена. Учитывая это, вот простой макрос, который дублирует текущую строку в следующей нижней строке:


    Sub CopyLineBelow()
        DTE.ActiveDocument.Selection.Collapse()
        DTE.ActiveDocument.Selection.Copy()
        DTE.ActiveDocument.Selection.Paste()
    End Sub

    Sub CopyLineAbove()
        DTE.ActiveDocument.Selection.Collapse()
        DTE.ActiveDocument.Selection.Copy()
        DTE.ActiveDocument.Selection.LineUp()
        DTE.ActiveDocument.Selection.Paste()
    End Sub
  • Для перемещения строки текста, Edit.LineTranspose переместит выбранную строку вниз. Я не думаю, что есть команда для перемещения строки вверх, но вот быстрый макрос, который делает это:

    Sub MoveLineUp()
        DTE.ActiveDocument.Selection.Collapse()
        DTE.ActiveDocument.Selection.Cut()
        DTE.ActiveDocument.Selection.LineUp()
        DTE.ActiveDocument.Selection.Paste()
        DTE.ActiveDocument.Selection.LineUp()
    End Sub

Если вы еще не начали играть с макросами, они действительно полезны. Инструменты | Макросы | Macros IDE откроет вам редактор, и, как только они будут определены, вы сможете настроить сочетания клавиш через тот же интерфейс, который я упоминал выше. Я сгенерировал эти макросы с помощью невероятно удобной команды Record Temporary Macro, также в разделе Tools | Макросы. Эта команда позволяет записывать набор клавиатурных вводов и воспроизводить их любое количество раз, что хорошо для создания расширенных команд редактирования, а также для автоматизации повторяющихся задач (например, переформатирование кода).

9 голосов
/ 24 ноября 2008

Я недавно сделал то же самое и перешел из Eclipse в Visual Studio, когда перешел в новый проект. Настоятельно рекомендуется добавить *1002* Resharper - он добавляет некоторые из богатых функций редактирования, навигации и рефакторинга, которые затмение имеет в VS.

Resharper также позволяет вам использовать схему сопоставления клавиш, которая очень похожа на InteliJ. Очень удобно для Java-беглецов ...

Что касается вашего второго вопроса, Resharper имеет ту же функцию перемещения вверх / вниз, что и eclipse, , но с некоторыми оговорками . Во-первых, при использовании сочетаний клавиш InteliJ комбинация клавиш довольно извилистая.

Переместить код вверх: Ctrl + Shift + Alt + курсор вверх

Переместить код вниз: Ctrl + Shift + Alt + курсор вниз

Во-вторых, он не всегда перемещается на одну строку, а фактически переходит на блоки кода. Таким образом, он не может переместить строку извне оператора if внутрь него - он перебирает выбранную строку прямо над блоком if. Для этого вам нужно переместиться «влево» и «вправо», используя

Переместить код во внешний блок кода: Ctrl + Shift + Alt + левый курсор

Переместить код в следующий внутренний блок кода: Ctrl + Shift + Alt + правый курсор

2 голосов
/ 11 апреля 2009

Edit.LineTranspose, но это не работает, чтобы переместить строку вверх ... Вот макрос для перемещения вверх

Sub LineTransposeUp()
    Dim offset As Integer
    Dim sel As TextSelection

    DTE.UndoContext.Open("LineTransposeUp")

    Try
        sel = DTE.ActiveDocument.Selection
        offset = sel.ActivePoint.LineCharOffset
        sel.LineUp()
        DTE.ExecuteCommand("Edit.LineTranspose")
        sel.LineUp()
        sel.MoveToLineAndOffset(sel.ActivePoint.Line, offset)
    Catch ex As System.Exception
    End Try

    DTE.UndoContext.Close()
End Sub
2 голосов
/ 24 ноября 2008

Запишите макрос в visual studio, чтобы выполнить операцию alt-arrow:

ctrl-alt-r -- record mode
ctrl-c -- copy a line
up arrow -- go up a line
home -- beginning of line (maybe there is a way to paste before the current line without this)
ctrl-v -- paste
ctrl-alt-r -- end record mode

Теперь вы можете сопоставить этот макрос с любым набором нажатий клавиш, используя макросы ide и настройки клавиатуры.

1 голос
/ 03 октября 2012

Используйте расширение MoveLine для перемещения линии (или группы линий) вверх или вниз в VS 2010 / 2012.

0 голосов
/ 07 мая 2011

Павел Островский Я попробовал твой инструмент. Это работает в основном хорошо.

Другая вещь, которую делает eclipse, это перемещение строки на текущий уровень отступа.

Например:

function test()
{
    // do stuff
}
Console.WriteLine("test"); 

Выполнение переключения на console.writeline изменит его на

function test()
{
    // do stuff
    Console.WriteLine("test"); 
}

но ваш инструмент, кажется, делает это:

function test()
{
    // do stuff
Console.WriteLine("test"); 
}
0 голосов
/ 24 ноября 2008

Я не знаю, поддерживает ли VS функции, о которых вы говорите изначально, но я знаю, что плагин reharper позволяет вам перейти к предыдущим изменениям, используя CTRL + SHIFT + BACKSPACE. Я не думаю, что у него есть поддержка для перемещения строки вверх и вниз (ну, не то, что я еще нашел)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...