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

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

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

Кто-нибудь открыл эти функции hotkey в Visual Studio.NET?

A D D E N D U M:

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

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

}
Console.WriteLine(i);

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

Ответ 1

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

'' 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() и закрыть его с их конца. 11/23/11 - Я обновил это снова, чтобы перемещенные строки сами вставлялись, когда вы пересекаете границы скобок

Ответ 3

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

Как для конкретных команд:

  • Я считаю, что команды навигации вперед/назад, о которых вы говорите, - 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

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

Ответ 4

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

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

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

Переместить код вверх: ctrl + shift + alt + курсор вверх

Переместить код вниз: ctrl + shift + alt + вниз курсор

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

Переместить код во внешний код: ctrl + shift + alt + левый курсор

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

Ответ 5

Запишите макрос в визуальной студии, чтобы сделать объект 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 и предпочтений клавиатуры.

Ответ 6

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

Ответ 7

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

Ответ 8

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

Ответ 9

Paul Ostrowski Я попробовал ваш инструмент. Он работает в основном нормально.

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

Например:

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

Выполнение смены на console.writeline изменит его на

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

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

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