Macro: Delete lines that contains text in clipboard



  • Hi,

    I want to create a simple macro to delete the lines that contains the string that is stored in the clipboard (when is executed). The process that I follow is:

    • Start recording macro
    • Open the find window and paste wanted text XXX into the Mark section. Then mark the lines.
    • Execute the option “Delete marked lines”.

    The problem is when I change the content of the string to YYY (clipboard), the Macro keeps marking and deleting the string I’ve used to record the macro (XXX).

    How can I change the macro to use the content of the clipboard instead of the static string?

    Thank you



  • @APica_Al

    The way it works is that only when you “run” a “find”-related function, that is when all of the settings (Find’s edit boxes, checkboxes, etc) get captured into the macro.

    Note that “run” here means “press a button to do a find operation”. So you can be macro recording and change all of the individual settings all you want but nothing is recorded until you actually press the (e.g.'s) Find Next button or the Find All button.

    So…in your case, when you paste from the clipboard into the Find what zone, that paste action isn’t recorded into the macro…but at some point farther on in your actions the text from the paste is. Thus the text becomes hardcoded as a constant into the macro.



  • Thank you.

    So, is there a way to reload that string text each time? I’ve found the shortcuts.xml file with the macro code, but I don’t know which commands to use (if they exist) .



  • @APica_Al said:

    is there a way to reload that string text each time

    AFAIK, no. shortcuts.xml gets read into memory when Notepad++ starts; no (reasonable!) way to “intercept” that data item to insert something else…which I think is what you are considering…??



  • @Scott-Sumner said:

    AFAIK, no. shortcuts.xml gets read into memory when Notepad++ starts; no (reasonable!) way to “intercept” that data item to insert something else…which I think is what you are considering…??

    Exactly. That’s why I wanted to read the data from clipboard dynamically.

    Thank you anyway



  • @APica_Al

    I’ve found a possible solution without using the macro feature of Notepad++ but it takes some effort.

    1. You need to install the NppExec Notepad++ plugin (available via PluginManager).

    2. You need a helper program - NirCmdC by Nir Sofer. It is available here, packaged with the GUI version (NirCmd) in a ZIP file (scroll down to the end of the site to find the download link).

    3. Unpack the ZIP file of NirCmdC to a folder of your choice.

    4. Go to Menu Plugins -> NppExec -> Execute... and paste the following code to the Command(s) area:

      set NirCmdPath=<Path-to-the-folder-of-step-3>\nircmdc.exe
      set SearchAndMarkDialogTitle=<Title-of-Npp’s-Mark-window-(depends on your locale, it’s “Mark” in english)>

      npp_sendmsg WM_COMMAND IDM_SEARCH_MARK

      “$(NirCmdPath)” sendkeypress ctrl+v
      “$(NirCmdPath)” sendkeypress enter
      “$(NirCmdPath)” win close title “$(SearchAndMarkDialogTitle)”

      npp_sendmsg WM_COMMAND IDM_SEARCH_DELETEMARKEDLINES

      unset SearchAndMarkDialogTitle
      unset NirCmdPath

    5. Perform the required changes in lines 1 and 2 and save the code e.g. as DelLinesContainingClipboardContent.

    6. Go to Menu Plugins -> NppExec -> Advanced options.... Here you can associate the script of step 5 to a new entry in the Macros menu.

    7. Go to Menu Settings -> Shortcut Mapper... and assign the menu entry to a keyboard shortcut of your choice.

    8. Go to Menu Search -> Mark... and check the options Bookmark line and Purge for each search. Maybe it is possible to automate this using NirCmdC but this is your “homework” ;-).

    Now you can select the word you are searching for, hit CTRL+C, hit the keyboard shortcut of step 7, and all the lines containing the selected word will be deleted.



  • Wow, this is very nice!
    The script can be simplified a little:

    set local NirCmdPath = <Path-to-the-folder-of-step-3>\nircmdc.exe
    
    npp_sendmsg WM_COMMAND IDM_SEARCH_MARK // show the Mark dialog
    
    "$(NirCmdPath)" sendkeypress ctrl+v // paste from the clipboard
    "$(NirCmdPath)" sendkeypress enter // apply - i.e. mark all
    "$(NirCmdPath)" sendkeypress esc // close the Mark dialig
    
    npp_sendmsg WM_COMMAND IDM_SEARCH_DELETEMARKEDLINES // delete the lines
    // don't forget to check "Bookmark line" and "Purge for each search" for that!
    


  • @Vitaliy-Dovgan

    Nice optimization.


    For the script to work on ALL lines of course option Wrap around must be checked too.



  • Well if we are opening it up to scripts, then I’ll offer up the following Pythonscript; I call it DeleteLinesWithClipboardText.py:

    def DLWCT__main():
    
        if not editor.getSelectionEmpty(): return  # keep it simple; maybe prompt user to cancel selection and re-run...
        if not editor.canPaste(): return           # keep it simple; maybe prompt user that no text is in clipboard...
        orig_document_len = editor.getTextLength()
        editor.beginUndoAction()
        editor.paste()
        pasted_text_len = editor.getTextLength() - orig_document_len
        curr_pos = editor.getCurrentPos()
        clipboard_text = editor.getTextRange(curr_pos - pasted_text_len, curr_pos)
        editor.deleteRange(curr_pos - pasted_text_len, pasted_text_len)
        if '\r' in clipboard_text or '\n' in clipboard_text:
            # keep it simple; don't allow multiline search text
            editor.endUndoAction()
            return
        del_line_list = []
        find_start_pos = 0
        while True:
            f = editor.findText(FINDOPTION.MATCHCASE, find_start_pos, editor.getTextLength(), clipboard_text)
            if f == None: break
            (found_start_pos, found_end_pos) = f
            line_nbr = editor.lineFromPosition(found_start_pos)
            if len(del_line_list) > 0:
                if del_line_list[0] != line_nbr: del_line_list.insert(0, line_nbr)
            else:
                del_line_list.append(line_nbr)
            find_start_pos = found_end_pos
        for line in del_line_list: editor.deleteLine(line)
        editor.endUndoAction()
    
    DLWCT__main()
    

    The only tricky part is in getting the clipboard data. I paste the clipboard contents into the document, read what was just pasted, and then delete those contents. After that it is a simple matter to locate the desired text and delete the lines it occurs on.


Log in to reply