3

Using an AutoHotkey script I'd like to set the keyboard command Ctrl+D to delete the current line in any active Windows app.

How?

GollyJer
  • 23,857
  • 16
  • 106
  • 174

4 Answers4

2
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del}

Might not work in all edge cases, but passes some very basic testing in Notepad. =~)

HaveSpacesuit
  • 3,572
  • 6
  • 40
  • 59
  • Thanks! Your answer works great if there is any text on the line. I updated the question to remove "of text" as I'd love it to work even if the line is empty. I get that a simple press of the Delete key would work in that case, but trying to keep muscle memory the same. :-D – GollyJer Sep 25 '17 at 20:43
  • I tweaked the answer some. Nothing too fancy, but it should work for empty lines and the last line of the file. – HaveSpacesuit Sep 25 '17 at 20:55
  • Works in Word, SciTE4AutoHotkey, and VisualStudio Code. Each of those handle key commands a little differently but this behaved the same in each. Thanks again! – GollyJer Sep 25 '17 at 21:04
2

HaveSpacesuit's answer works but after using it for a while I realized it deletes the active line and sometimes re-positions the spacing of the line below.

This led me to rethink his solution. Instead of going from the front of the line to the back, I tried going from back to front. This solved the re-positioning issue.

SendInput {End}
SendInput +{Home}
SendInput ^+{Left}
SendInput {Delete}

There is still a small problem though. If the cursor is on an empty line, with more empty lines above, then all empty lines get deleted.

I don't know a key combo to replace ^+{Left} that doesn't have this behavior so I had to write a more comprehensive solution.

^d:: DeleteCurrentLine()

DeleteCurrentLine() {
   SendInput {End}
   SendInput +{Home}
   If get_SelectedText() = "" {
      ; On an empty line.
      SendInput {Delete}
   } Else {
      SendInput ^+{Left}
      SendInput {Delete}
   }
}

get_SelectedText() {

    ; See if selection can be captured without using the clipboard.
    WinActive("A")
    ControlGetFocus ctrl
    ControlGet selectedText, Selected,, %ctrl%

    ;If not, use the clipboard as a fallback.
    If (selectedText = "") {
        originalClipboard := ClipboardAll ; Store current clipboard.
        Clipboard := ""
        SendInput ^c
        ClipWait .2
        selectedText := ClipBoard
        ClipBoard := originalClipboard
    }

    Return selectedText
}

As far as I can tell this produces no unexpected behaviour.

However, be careful if you're using a clipboard manager as this script uses the clipboard, if necessary, as an intermediary to get the selected text. This will impact clipboard manager history.

GollyJer
  • 23,857
  • 16
  • 106
  • 174
  • Nice. Hopefully this can be useful for someone in the future. – HaveSpacesuit Sep 27 '17 at 16:22
  • Great work. Unfortunately, I can't use it, because I do delete lines very frequently, and this would mess with my clipboard too much. :/ – tinker May 23 '20 at 06:07
  • There might be a way to NOT mess with the clipboard. – tinker May 23 '20 at 06:09
  • I was just playing with your solution. It is pretty clever. You don't like it? – GollyJer May 23 '20 at 06:16
  • Curious what you think of `^d::SendInput {End} {ShiftDown}{Home 2}{Left}{ShiftUp}{Delete}{Right}` Solves reposition issue and only deletes single blank line – Jonathan Lerner May 25 '20 at 03:30
  • @JonathanLerner That is inconsistent for me in Notepad++ and OneNote (two of the places I use this the most). – GollyJer May 25 '20 at 19:54
  • @GollyJer I just realized there was a typo (unintended space after `{End}`), that ive just removed, and it works better for me in Notepad++ now with empty lines. Are there other cases that dont work for you? New script: `^d::SendInput {End}{ShiftDown}{Home 2}{Left}{ShiftUp}{Delete}{Right}` – Jonathan Lerner May 26 '20 at 00:23
  • Try it on a line with a bunch of spaces (appears empty) with the cursor somewhere in the middle of the spaces. – GollyJer May 26 '20 at 21:49
  • It's easy to write a script to save your clipboard contents, do your copy/paste, and then restore your clipboard when done. I have that on a lot of my scripts. Google should help with that if anyone needs... – HaveSpacesuit Aug 09 '21 at 20:58
0

In case you run into problems where you need different behaviours for different programs, you can "duplicate" your ^d command for specific programs like this:

SetTitleMatchMode, 2 ; Makes the #IfWinActive name searching flexible
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del} ; Generic response to ^d.

#IfWinActive, Gmail ; Gmail specific response
  ^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del} ; adapt this line for gmail
#IfWinActive ; End of Gmail's specific response to ^d

#IfWinActive, Excel ; Excel specific response.
  ^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del} ; adapt this line for Excel
#IfWinActive ; End of Excel's specific response to ^d

This way your ^d command will work differently in Excel and Gmail.

Robert Ilbrink
  • 7,738
  • 2
  • 22
  • 32
0

I have a simple way to solve the repositioning issue. Without using the clipboard.

The repositioning issue is due to the need to handle 2 separate cases.

  1. if there's existing text in a line, we want to select them all, and delete the text (backspace 1) and backspace one more time to delete the empty line (backspace 2)

  2. if it's a blank line, we want to delete the empty line (backspace 1)

To cater for both of above cases, I introduced a dummy character. This will make sure BOTH cases will act the same way. So doing backspace 2 times, will result in the same transformation each time.

Simply,

; enable delete line shortcut
^d::
    Send {Home}
    Send {Shift Down}{End}{Shift Up}
    Send d
    Send {Backspace 2}
    Send {down}
return 

Disadvantage with this approach, the dummy character "d" will appear when you undo. Not a bad tradeoff since I don't undo delete lines very often.

tinker
  • 483
  • 4
  • 16