Sublime Forum

Macros don't record Find/Replace?

#44

+1 not recording everything in a Sublime Text macro is a shocking omission. Even Microsoft product macros have been recording everything since the '90’s

0 Likes

#46

Just stumbled on the same disappointment in ST3… (even after all these years)

My use case is to perform ~15 steps to clean up and pre-process a data file,
which I need to do very often… many of the steps involve search and replace by regular expression
So unfortunately a macro can’t help me here.

My guess is that there is something fundamental to the API which limits scope and prevents recording of it…
(does anyone have more details on why? are there any other actions that similarly aren’t recorded?)

0 Likes

#47

Just started using Sublime Text on a Mac having used TextPad on the PC for years
This macro search/replace issue came up pretty quick
All I want to do is remove all blank lines from a text file
e.g. something like: global search/replace on \n\n and replace with \n

0 Likes

#48

I am not certain if this will help, and I do not use it myself, but there is the package Delete Blank Lines.

1 Like

#49

There is also RegReplace. It allows you to define a find and replace (or multiple which you can chain together) and then create a command to execute it. Commands configured to display in the palette, bound to a key map, or even shown in the menu. I use it to set up replaces I commonly do.

1 Like

#50

No dependency workaround

I use find_replace by deathaxe above, because it has a human-readable syntax.

But here is a native-only workaround:

// clean-up-diacritics.sublime-macro
// Replace all incorrectly used Turkish diacritics with Romanian diacritics
[
  {"command": "select_all", "args": null},
  {"command": "insert_snippet", "args": {"contents": "${SELECTION/(?<1>Ş)|(?<2>ş)|(?<3>Ţ)|(?<4>ţ)/(?{1}Ș:(?{2}ș:(?{3}Ț:ț)))/gm}"}}
]

via this answer to [pcre] Multiple replacement with just one regex - Stack Overflow

1 Like

Variable substitution ignoring `g` flag?
#51

Been using sublime since I started programming and now I’m starting to actually become a professional I was 100% sure I was going to purchase a license. Now that I found out that such basic feature is not implemented turns me down a bit, since this is essential for my work. Probably going to rely on emacs for doing things like this for now

2 Likes

#52

I just bought a license today. I was disappointed that I couldn’t properly use find in macro, as I have used this extensively (while on MS windows) with Notebook++.
I plan for Sublime text to be my go to data editor for Linux, but being able to create macho that can find starting point is crucial.

Please make this functionality high priority.

Larz60+ (python-forum.io)

1 Like

#53

Another vote for making this a priority, please! I’m an outlier in that I’m not a huge coder, but Sublime is my go-to for writing, and also converting texts in bulk from Word and other places to web-ready <p> wrapped copy, and for those purposes, being able to F&R things like \n\n with \n would be a huge help!

1 Like

#55

This was a horrible decision. Ideally, macros should be able to to record and replay any command available vie menues or hot-keys. Maybe this could be solved through scripting but I agree with others that this is overkill. Plus, I don’t want to learn a new scripting language, preferring to use SED from shell.

I switch to Notepad++ on windows when I need macros and have just downloaded Textmate II to my personal Mac book pro and use a third option on Linux. I’d prefer to use the same editor across all my machines regardless of operating system.

I’m uninstalling Sublime on all my plateforms. Sorry guys, you should really reconsider your choice.

Don Rau
Clearwateranalytics
Boise Idaho

0 Likes

#56

I still live in hope that a ‘record and playback anything’ macro facility will find its way into Sublime. It’d probably require some heavy lifting under the hood, because macros are presently implemented more or less for batching TextCommands together, an early part of Sublime’s internal design. Those unfamiliar with ST’s Python API won’t be clear on what macros can and can’t do - and there’s plenty they can’t.

Ideally, at least anything that affects the state of a buffer should be recordable into a macro. That includes cursor movements, S&R, indentations, selections etc… There might be a few exceptions, one example being code folding.

Before Sublime, I used Brief and then Crisp, both of which had ‘record everything, no-brainer’ macro facilities which could be either learnt or hand-coded. For a number of editing situations I still need to fall back to other editors because I can’t mirror a repeat a sequence of actions in a macro, and going the route of building a Python extension is the proverbial sledgehammer.

With full featured macros, effortless huge file support, proper column selection and syntax aware folding added to the core, I could quite see Sublime being the first and last editor I would ever need, except maybe vim for ssh sessions. Further, I think that would expand its reach and sales beyond coders and towards anyone who needs a robust, swiss army knife editor with native performance in their technology workflow. Just my 2p.

0 Likes

#57

I would also like to see find (and replace) in Macros, but a workaround is to copy/paste to a different text editor (notepad++ or emacs), use their well developed macros, then copy/paste the result back to the sublime text editor. clunky but it works for me, and I can use the powerful emacs macros

0 Likes

#58

Deathaxe python script above totaly resolves this, and in addition gives a great way forward for more ST automation.
So if, like me, you came here looking for a solution - scroll up and use it. no need for a new ST feature.

For the record - here is how you use it from within a macro:
{
“args”: {
“pattern”: “^whatever you want(ed)?”,
“replace_by”: “What you need\1”
},
“command”:“find_replace”
}

0 Likes

#59

Hey @deathaxe,
your script runs fine at first look.
When using a “.” as the search/find pattern I discovered strange beaviour, killing parts of the text expected to be the remains.

Adding the flag “LITERAL”, limit the code now to replace almost all occurences of “.” but still killing some text at the start of the orginal.

Finally I discovered that you swapped two arguments in the line with the “find()” function.

in your code change the line after the “while True:” statement

from

        found = self.view.find(pattern, self._flags(flags), start_pt)

to

       found = self.view.find(pattern, start_pt, self._flags(flags))

and you are fine.

@deathaxe please edit your example above if possible!

Thanks for you work!

0 Likes

#60

Good catch. Unfortunatelly I looks like I can’t edit the post anymore.

So here’s the fixed version:

import sublime
import sublime_plugin


class FindReplaceCommand(sublime_plugin.TextCommand):
    """The implementation of 'find_replace' text command.

    Example:

        view.run_command(
            "find_replace", {
                "pattern": "the",
                "replace_by": "THE",
                "start_pt": 100,
                "flags": ["LITERAL"]
            }
        )
    """

    FLAGS = {
        "LITERAL": sublime.LITERAL,
        "IGNORECASE": sublime.IGNORECASE
    }

    def run(self, edit, pattern, replace_by, start_pt=0, flags=[]):
        """Find and replace all patterns.

        Arguments:
            edit (sublime.Edit):
                The edit token used to undo this command.
            pattern (string):
                The regex pattern to use for finding.
            replace_by (string):
                The text to replace all found words by.
            start_pt (int):
                The text position where to start.
            flags (list):
                The flags to pass to view.find()
                ["LITERAL", "IGNORECASE"]
        """
        while True:
            found = self.view.find(pattern, start_pt, self._flags(flags))
            if not found:
                return
            self.view.replace(edit, found, replace_by)
            start_pt = found.begin()

    def _flags(self, flags):
        """Translate list of flags."""
        result = 0
        for flag in flags:
            result |= self.FLAGS.get(flag, 0)
        return result
0 Likes

Variable substitution ignoring `g` flag?
#61

hi @deathaxe
when I try to replace \n with ',\n', then this code will run forever, because from start point begin() it will find the same \n . How about start_pt = found.begin() + len(replace_by) ? what do u think ?

1 Like

#62

For the deathaxe script, is there a way to use backreferences in replacements? The self.view.replace method takes the replacement as a string and and says nothing more about it as far as I can tell.

Taking the example from omri’s post, "replace_by": "What you need\1" for me just causes an error for bad escaping. Escaping the backslash makes the .sublime-macro valid, but the replace then uses literal backslashes.

Not doable? Am I missing something? Working example?

0 Likes

#63

Changelog (Build 4107) 20 May 2021
Text Commands

  • Macros now record Find commands

Nice - Thanks! … but with a macro such as:

F3 (Find Next)
Ctrl+Shift+K (Delete Line)

… when nothing is found, the current line is deleted for each Playback without notice until you realise what’s happening :face_with_raised_eyebrow:

Ctrl+Z, Ctrl+Z, Ctrl+Shift+Z :grimacing:

0 Likes

#64

Macros are plain lists of commands being executed after each other. There’s no control flow to stop in the middle of anywhere if something strange happens.

0 Likes

#65

I accept most of the blame :wink: . I could have put the find at the end and done the first F3, manually:

Ctrl+Shift+K (Delete Line)
F3 (Find Next)

I notice there is the usual feedback on the status bar ("Unable to find ") but, by that time, the later operations could need undoing.

But I wonder if this is an implementation consideration.
Clearly, the team originally excluded Find from macros for a reason (perhaps this reason?).
I’m cautious about trying to anticipate a user’s intentions but, surely, terminating macro playback at the point of “Unable to find” would be no worse than excluding Find operations altogether (prior to ST4)?

Either that or provide a “Find or Halt macro” checkbox in the Tools menu (Macro section) or a separate keybinding (Ctrl+Alt+F3 ?) for “Find or Halt macro playback” (Ctrl+Alt+Shift+F3 = reverse Find ?).

I hope someone can prove me wrong by providing any useful case where a macro contains a Find followed by any operation(s) not dependent on Find success. Then, I’ll shut up :relaxed:

0 Likes