40

我正在从 Eclipse 迁移到 Visual Studio .NET,并且找到了所有我心爱的热键,除了两个:

  • 在 Eclipse 中,您可以按ALT-←</kbd> and ALT-→</kbd> 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.?
  • 在 Eclipse 中,要向上或向下移动一行,你按下ALT-uparrowALT-downarrow你只需在代码中移动它,直到你把它拿到你想要的地方,非常好。此外,要复制一行,您可以按SHIFT- ALT-uparrowSHIFT- ALT- downarrow。这两个热键甚至适用于您选择的行块。

有没有人在 Visual Studio .NET 中发现这些热键功能?

附录:

使用上述第二个功能的一个示例是将此处的底线向上移动到 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

4

9 回答 9

49

提出的答案是可行的,但在如何保存现有的粘贴缓冲区、当前选择的字符以及不允许用户对一系列行进行操作方面,没有一个比 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 建议)并在其末尾关闭它。2011 年 11 月 23 日 - 我再次更新了此内容,以允许移动的行在您越过括号边界时缩进

于 2009-06-10T00:08:52.317 回答
16

对于希望在 Visual Studio 2010 中执行此操作的任何人,免费的 Visual Studio 2010 Pro Power Tools 扩展增加了上下移动线条的功能。

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

于 2010-07-13T19:14:02.030 回答
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 命令生成了这些宏,也在工具 | 下。宏。此命令可让您记录一组键盘输入并多次重播,这对于构建高级编辑命令以及自动执行重复性任务(例如代码重新格式化)非常有用。

于 2008-11-24T05:16:35.453 回答
8

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

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

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

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

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

其次,它并不总是只移动一行,而是实际跳转代码块。因此它不能将一条线从 if 语句的外部移动到它的内部——它会将选定的行直接跳过 if 块。为此,您需要使用“左”和“右”移动

将代码移动到外部代码块:ctrl + shift + alt + 左光标

将代码移动到下一个内部代码块:ctrl + shift + alt + 右光标

于 2008-11-24T12:51:42.867 回答
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 和键盘首选项将此宏映射到您喜欢的任何击键集。

于 2008-11-24T05:33:22.067 回答
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
于 2009-04-11T14:00:33.957 回答
1

使用MoveLine 扩展在 VS 2010/2012 中向上或向下移动一条线(或一组线)。

于 2012-10-03T12:32:22.520 回答
0

我不知道 VS 是否支持您在本机谈论的功能,但我知道 resharper 插件允许您使用 CTRL + SHIFT + BACKSPACE 转到以前的编辑。我认为它不支持上下移动一条线(我还没有找到)

于 2008-11-24T05:14:56.703 回答
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"); 
}
于 2011-05-07T06:21:28.593 回答