Visual Studio:热键可以向上/向下移动线并移动最近的更改

时间:2008-11-24 05:05:32

标签: visual-studio eclipse hotkeys

我正在从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中文。这两个热键甚至适用于您选择的行块。

有没有人在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推断Charlie的想法来选择一行,在Visual Studio中你可以将光标放在Console.WriteLine上,(无选择)按 CTRL - X 然后向上移动并按 CTRL - V

9 个答案:

答案 0 :(得分:50)

答案提出了工作,但是它们都没有像eclipse那样保存现有的粘贴缓冲区,当前选择的字符,并且它们不允许用户在一系列行上操作。这是我提出的解决方案,它保留了粘贴缓冲区,当前字符选择,有或没有选择(可能跨越多行也可能没有):

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

我编辑了这篇文章,在MoveLineUp()和MoveLineDown()方法的开头添加了UndoContext机制(由Nicolas Dorier建议)并在它们的末尾关闭它。 11/23/11 - 我再次对此进行了更新,以允许移动的线条在跨越支架边界时缩进

答案 1 :(得分:16)

对于在Visual Studio 2010中寻找方法的人来说,免费的Visual Studio 2010 Pro Power Tools扩展程序增加了上下移动行的功能。

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

答案 2 :(得分:14)

如果您还没有找到它,设置这些键盘快捷键的位置在工具|下选项|环境|键盘。通过浏览列表可以找到许多方便的命令,但不幸的是,我从来没有找到任何好的参考来描述每个命令的目的。

至于具体命令:

  • 我相信你所指的前进/后退导航命令是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将带您进入编辑器,一旦定义它们,您就可以通过我上面提到的相同UI设置键盘快捷键。我使用非常方便的Record Temporary Macro命令生成了这些宏,也在Tools |下宏。此命令允许您录制一组键盘输入并重放它们任意次,这有助于构建高级编辑命令以及自动执行重复性任务(例如代码重新格式化)。

答案 3 :(得分:9)

我最近做了同样的事情,当我搬到一个新项目时,从Eclipse迁移到Visual Studio。 强烈推荐Resharper add in - 它增加了eclipse对VS的一些丰富的编辑,导航和重构功能。

Resharper还允许您使用与InteliJ非常相似的键盘映射方案。非常方便的Java逃脱者......

关于你的第二个问题,Resharper具有与eclipse相同的移动代码上/下功能,但有一些警告。首先,使用InteliJ键盘映射,键组合相当曲折。

  

向上移动代码: ctrl + shift + alt +向上光标

     

向下移动代码: ctrl + shift + alt +向下光标

其次,它并不总是仅移动一行,而是实际跳转代码块。所以它不能从if语句外部移动一行到它内部 - 它将所选行跳过if块。要做到这一点,你需要使用

移动“左”和“右”
  

将代码移动到外部代码块中: ctrl + shift + alt + left cursor

     

将代码移动到下一个内部代码块: ctrl + shift + alt + right cursor

答案 4 :(得分:2)

在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和键盘首选项将此宏映射到您喜欢的任何一组击键。

答案 5 :(得分:2)

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

答案 6 :(得分:1)

使用MoveLine extension在VS 2010/2012中向上或向下移动一行(或一组行)。

答案 7 :(得分:0)

我不知道VS是否支持您正在谈论的功能,但我知道resharper插件允许您使用CTRL + SHIFT + BACKSPACE转到之前的编辑。我不认为它支持上下移动一条线(不是我发现的那条)

答案 8 :(得分:0)

Paul Ostrowski我尝试了你的工具。它的工作原理很好。

eclipse所做的另一件事是将线移动到当前的缩进级别。

例如:

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

在console.writeline上进行升级会将其更改为

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

但您的工具似乎是这样做的:

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