Visual Studio: teclas de acceso rápido para mover la línea hacia arriba/hacia abajo y moverse a través de los cambios recientes


Me estoy moviendo de Eclipse a Visual Studio. NET y he encontrado todas mis queridas teclas de acceso rápido excepto dos:

  • en Eclipse puedes presionar ALT- y ALT- para visitar los cambios recientes que ha hecho, algo que uso con frecuencia para volver a donde estaba en algún otro archivo y luego volver. Aparentemente en VS.NET CTRL-- y CTRL-SHIFT-- hacer esto, pero no parecen funcionar siempre (por ejemplo, en el ordenador portátil, puede ser un numkey problema con el menos) y no parecen seguir el mismo algoritmo de "donde estaba" como estoy acostumbrado en Eclipse. Alguien ha conseguido que esto funcione y se basan en día, etc.?
  • en Eclipse, para mover una línea hacia arriba o hacia abajo, presiona ALT-uparrow o ALT-downarrow y simplemente lo mueves a través del código hasta llegar a donde lo quieres, muy bien. También para hacer una copia de una línea, puede pulsar CAMBIO-ALT-uparrow o CAMBIO-ALT-flecha hacia abajo. Ambas teclas de acceso rápido incluso funcionan para el bloque de líneas que ha seleccionado.

¿Alguien ha descubierto estas funciones de teclas rápidas en Visual Studio. NET?

A D D E N D U M:

Un ejemplo de cuando se utilizaría la segunda característica descrita anteriormente es mover la línea inferior aquí hacia arriba en el bucle for. En Eclipse, pondrías el cursor en la consola.WriteLine y luego presione ALT - (uparrow), utilizo que todos los tiempo: un golpe de tecla para mover las líneas hacia arriba y hacia abajo.

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

}
Console.WriteLine(i);

Bien, extrapolando la idea de Charlie con no-selection-ctrl-c para seleccionar una línea, en Visual Studio puedes poner el cursor en la consola.WriteLine (no hay selección) pulse CTRL-X y, a continuación, mover y pulse CTRL-V.

Author: joar, 2008-11-24

9 answers

Las respuestas propuestas funcionan, pero ninguna de ellas es tan agradable como eclipse con respecto a cómo preservan el búfer de pegado existente, los caracteres seleccionados actualmente, y no permiten al usuario operar sobre un rango de líneas. Aquí hay una solución que se me ocurrió que conserva el búfer de pegado, la selección de caracteres actual y funciona con o sin una selección (que puede o no abarcar varias filas):

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

Edité este post para agregar el mecanismo UndoContext (sugerido por Nicolas Dorier) al principio de los métodos MoveLineUp() y MoveLineDown () y cerrándolo al final. 11/23/11-He actualizado esto de nuevo para permitir que las líneas movidas se indenten a medida que se cruzan los límites de corchetes

 50
Author: Paul Ostrowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-23 17:35:22

Para cualquiera que busque una manera de hacer esto en Visual Studio 2010, la extensión gratuita de Herramientas eléctricas Visual Studio 2010 Pro agrega la capacidad de mover líneas hacia arriba y hacia abajo.

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

 16
Author: Polshgiant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-13 19:14:02

Si aún no lo ha encontrado, el lugar donde se configuran estos atajos de teclado es en Herramientas | Opciones | Entorno | Teclado. Se pueden encontrar muchos comandos útiles simplemente navegando por la lista, aunque desafortunadamente nunca he encontrado una buena referencia para describir lo que cada comando está destinado a hacer.

En cuanto a comandos específicos:

  • Creo que los comandos de navegación hacia adelante/atrás a los que se refiere son View.Navegación hacia atrás y Vista.Navegue hacia adelante. Si su teclado no está cooperando con los enlaces de teclas VS, puede reasignarlos a sus teclas Eclipse preferidas. Desafortunadamente, no conozco una manera de cambiar el algoritmo que usa para decidir a dónde ir.

  • No creo que haya un comando incorporado para duplicar una línea, pero presionar Ctrl+C sin texto seleccionado copiará la línea actual en el portapapeles. Teniendo en cuenta que, aquí hay una macro simple que duplica la línea actual en la siguiente inferior línea:


    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
  • Para mover una línea de texto, Edite.LineTranspose moverá la línea seleccionada hacia abajo. No creo que haya un comando para mover una línea hacia arriba, pero aquí hay una macro rápida que lo hace:

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

Si aún no ha comenzado a jugar con macros, son realmente útiles. Herramientas / Macros / Macros IDE le llevará al editor, y una vez que estén definidos, puede configurar atajos de teclado a través de la misma interfaz de usuario que mencioné anteriormente. He generado estas macros usando el increíblemente práctico comando Record Temporary Macro, también en Herramientas / Macros. Este comando le permite grabar un conjunto de entradas de teclado y reproducirlas cualquier número de veces, lo que es bueno para crear comandos de edición avanzados, así como para automatizar tareas repetitivas (por ejemplo, reformateo de código).

 14
Author: Charlie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-24 05:40:56

Recientemente he hecho lo mismo y me mudé de Eclipse a Visual Studio cuando me mudé a un nuevo proyecto. El complemento Resharper en es muy recomendable - agrega algunas de las ricas funciones de edición, navegación y refactorización que eclipse tiene VS.

Resharper también le permite usar un esquema de asignación de keybaord que es muy similar a InteliJ. Muy útil para los fugitivos de Java...

Con respecto a su segunda pregunta, Resharper tiene el mismo movimiento code up / down funciona como eclipse, pero con algunas advertencias. En primer lugar, usando las asignaciones de teclado InteliJ, la combinación de teclas es bastante tortuosa.

Mover el código hacia arriba: ctrl + mayús + alt + cursor hacia arriba

Mueve el código hacia abajo: ctrl + shift + alt + cursor hacia abajo

En segundo lugar, no siempre se mueve por una sola línea, sino que en realidad salta bloques de código. Por lo tanto, no puede mover una línea desde fuera de una sentencia if hacia dentro de ella - salta la línea seleccionada justo sobre el bloque if. Para hacer eso, debe mover "izquierda" y "derecha" usando

Mover código al bloque de código exterior: ctrl + shift + alt + cursor izquierdo

Mueva el código al siguiente bloque de código interno: ctrl + shift + alt + cursor derecho

 9
Author: serg10,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-25 15:54:18

Grabar una macro en visual studio para hacer la cosa 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

Ahora puede asignar esta macro a cualquier conjunto de pulsaciones de teclado que desee utilizando el ide de macros y las preferencias de teclado.

 2
Author: 1800 INFORMATION,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-24 05:33:22

Editar.LineTranspose pero esto no funciona para mover una línea hacia arriba... Aquí está la macro para mover la línea

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
Author: Nicolas Dorier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-20 16:14:02

Utilice la extensión MoveLine para mover una línea (o grupo de líneas) hacia arriba o hacia abajo en VS 2010/2012.

 1
Author: Kevin Aenmey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-03 12:32:22

No se si VS soporta las características de las que estás hablando de forma nativa, pero sé que el plugin resharper te permite ir a las ediciones anteriores usando CTRL + SHIFT + RETROCESO. No creo que tenga soporte para mover una línea arriba y abajo tho (bueno, no es que haya encontrado todavía)

 0
Author: lomaxx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-24 07:09:38

Paul Ostrowski Probé tu herramienta. Funciona mayormente bien.

La otra cosa que eclipse hace es mover la línea al nivel de sangría actual.

Por ejemplo:

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

Haciendo un cambio en la consola.writeline lo cambiaría a

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

Pero su herramienta parece hacer esto:

function test()
{
    // do stuff
Console.WriteLine("test"); 
}
 0
Author: jdeuce,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-07 06:21:28