Refactoring Code in Sublime Text 3

2

Currently I do this with Find All (Cntrl+F old_var, alt+enter new_var), but this replaces words in my comments and strings.

A comment in this answer suggested the PyRefactor plugin which requires rope. These tools seem to have defaults that are too heavy-handed for my purposes. I just want to refactor variable names in stand-alone python scripts with Sublime Text 3.

So in a script like

# Where did my hat go?
hat = 0
print(hat)
print("hat")

The hat variable (not in strings nor comments) can be replaced with something else at the touch of a hotkey. No need for a special project folder/configuration, and nothing changed across multiple files. Unfortunately, Find All hat -> llama does...

# Where did my llama go?
llama = 0
print(llama)
print("llama")

EDIT:

I appreciate @Toto's regex solution, but I'm not fluent in that yet and would like a method that works more consistently and is easier to remember. Is there a plugin (or can I write one?) that identifies all the globally defined and stated variables (arguments in function calls, etc), and allows for a simple Find and Replace?

Wassadamo

Posted 2018-09-12T19:05:42.127

Reputation: 175

1You can likely use a regex to see if the line starts with # – var firstName – 2018-09-12T19:15:05.883

Have you thought about using an IDE that makes refactoring like this much easier? I used to be loyal to Sublime, until I discovered JetBrains IDEs. – DrZoo – 2018-09-13T19:10:37.010

Answers

1

  • Ctrl+H
  • Find: (?:^(?<!#).*\K|(<?!"))\bhat\b(?!")
  • Replace: llama
  • check Regular expression
  • check Whole word
  • check Wrap
  • Replace all

Explanation:

(?:
    ^       : beginning of line
    (?<!#)  : negative lookbehind, zero-length assertion that makes sure we don't have # before
    .*      : 0 or more any character
    \k      : forget all we have seen until this position
  |         : OR
    (?<!")  : negative lookbehind, zero-length assertion that makes sure we don't have " before
)
\b      : word boundary to not match chat, remove it if you want to match chat also
hat     : literally
\b      : word boundary to not match hats, remove it if you want to match hats also
(?!")   : negative lookahead, zero-length assertion that makes sure we don't have " after

Given:

# Where did my hat go?
hat = 0
chat = 0
print(hat)
print("hat")
print(chat)

Result for given example:

# Where did my hat go?
llama = 0
chat = 0
print(llama)
print("hat")
print(chat)

Before:

enter image description here After:

enter image description here

Toto

Posted 2018-09-12T19:05:42.127

Reputation: 7 722

1what about "red hat", or "red " + hat? Both will be replaced but they shouldn't – Máté Juhász – 2018-09-13T11:19:35.637

1@MátéJuhász: "red hat" is not replaced and "red " + hat becomes "red " + llama isn't that wanted? – Toto – 2018-09-13T11:39:17.617

ok, that's clever, what about "red hat and gloves"? – Máté Juhász – 2018-09-13T12:07:12.860

1@MátéJuhász: Of course, it will not work in this case :( for such case the regex will become unreadable. This is showing the limit of regex when parsing non regular language. – Toto – 2018-09-13T12:12:41.830

Can always count on regex to the rescue. Unfortunately this case doesn't work either: "hat ate the hw" becomes "llama ate the hw". – Wassadamo – 2018-09-13T18:59:54.337

@Wassadamo: True it doesn't work for any string like "blah hat blah". I don't know if it exists a plugin that does the job. I think the best way is writing a proper parser. – Toto – 2018-09-14T12:07:24.220