CategoriesAndroid StudioSoftware DevelopmentTips and Tricks

Regex as a Steroid for Find and Replace in IDE

This is a long story about a small trick I learned about using Regex with Find and Replace in the IDE.

Understanding Our Small Problem

I was writing a small python script to push make some requests to an endpoint for seeding my database.

I had my data in a json file so it was as simple as reading the json array and making a POST request with each JSON object.

Now while writing my function to convert the json event into the request Payload, I just copy pasted the Json object and made necessary changes, however python wasn’t happy about the “” to be used as the keys for my dictionary.

So what I essentially had to do was to convert all the keys from “key_name” to ‘key_name’ notice the change from ” to ‘.

Since this payload didn’t really have a lot of keys it would have taken me less than 2 minutes to do it by hand. But I realised, this is not the first time I am doing this and probably also not the last time.

So I decided to find a more efficient way of doing this.

Evolving our Regex Based Solution

The first thing that came to my mind was Find and Replace.

What I could have done is replaced all the double qoutes (“) with single qoutes (‘) but this is bad as I might screw up the script by replacing double qoutes where they might actually be needed.

I believe a lot of developers overlook the support of Regex in modern IDEs and Text Editors.

Leveraging the power of Regex matching with Find and Replace could help us solve this problem very easily. Most of the time I use Regex101 to build my regex patterns.

But this time, I just turned to the IDE and wrote the simple pattern that I was looking to match, which is \”([a-zA-Z]+)\”:

Don’t worry if you don’t have a lot of experience with Regex, I’ll break it down for you.

Decoding the Regex

Regex Pattern
  • \” -> Will try to match a double quote character.
  • ( -> marks the beginning of a capturing group
  • [ ] -> specifies a range of characters you want to match
  • a-z -> is the range of characters between a (ascii index 97) and z (ascii index 122)
  • A-Z -> is the range of characters between a (ascii index 65) and z (ascii index 90)
  • + -> is a quantifier that will try to match the previous character or range at least ones and then as many times until there is no longer a match.
  • ) -> marks the end of a capturing group
  • \” -> Will try to match a double quote character.
  • : -> Will try to match a colon character.

I can imagine some of you might be wondering what is the use of a capturing group here?

The capturing group actually will help us preserve the key name.

For example if the string was “username”, my goal is to modify it to ‘username’. So in order to preserve the key itself, I will capture it into a group and later use this while replacing the strings.

Another thing that might have caught your attention is the : (colon) why do I need to match this?

Well my python file has strings like

response = requests.request("POST", url, data=json.dumps(payload), headers=headers)

or

url = "http://" + BASE_URL + "/tags/"

and I don’t want to replace them with single quotes.

So I found that adding a colon at the end will make sure I am only finding the keys I am actually interested in modifying.

Now if you actually run the find command it will start showing you the results

Now to replace the matched strings, lets open the replace tool by hitting Cmd + R

And add this regex there

\’$1\’:

What this will do is the following:

  • it will add a single quote
  • then add the capturing group number 1
  • then add a single quote
  • then add a colon

You remember we added a Capturing group using these parenthesis ( ) ?

That is what helped us preserve the key name. Capturing groups are 1-indexed so this might be something you’d want to make a note of.

And you can refer to Capturing groups by a $ sign followed by the capturing group number.

Since we only had one capturing group we wrote $1.

And now you can see that IntelliJ is even showing us a preview of replace action will be.

Now I can finally hit Replace All and get the job done.

In The End, It Does Matter…

In the end I’d like to conclude with the fact that it is, these extra steps that we take in practice to solve problems that help us learn new things. Learnings compound over time. It is easier to learn things by solving problems rather than just by reading stuff.

CategoriesAndroidAndroid StudioSoftware Development

Android Studio always modifying codeStyleSettings.xml – Fixed

Yesterday a colleague of mine started experiencing a weird issue with their android studio. Whenever they’d build the code, a change would be written to codeStyleSettings.xml file automatically.

The change at the first glance was clearly unrelated to something they had been working and hence they weren’t able to figure out what could be the cause of this issue.

What did the change look like?

<Objective-C-extensions>
  <option name="GENERATE_INSTANCE_VARIABLES_FOR_PROPERTIES" value="ASK" />
  <option name="RELEASE_STYLE" value="IVAR" />
  <option name="TYPE_QUALIFIERS_PLACEMENT" value="BEFORE" />
  <file>
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
  </file>
  <class>
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
  </class>
  <extensions>
    <pair source="cpp" header="h" />
    <pair source="c" header="h" />
  </extensions>
</Objective-C-extensions>

Clearly it wasn’t something related to our code since we aren’t doing anything with Objective-C in our android project. This made me want to check the android studio config on that machine, to see if some preferences were changed by mistake, or through an update or any other means.

Quickly searching for objective-c, I found that there were changes being written to the Inspections in the IDE. However, the dev denied making any such changes.

What do you think was the next obvious step for me? Google :]

Turns out, this was an old issue that someone asked about, on StackOverflow 3 years ago, and this, was the top rated and accepted answer that led us to the solution.

The <Objective-C-extensions> Section is added by the Android NDK Support Plugin. Which was added in 1.3 and is activated by default. 
If you have activated this plugin it adds the Section to your codeStyleSettings.xml. Otherwise it will be removed.

Answer by devtribe

Even though the dev had not activated this plugin on their own, maybe an update introduced this change and started causing this weird behaviour.

Here are the steps to fix the problem:

Step 1: Open Preferences in your Android Studio. Shortcut on Mac OS is Command + , (comma) and on Windows is Control + Alt + S
Step 2: Goto Plugins and find the Android NDK Support plugin
Step 3: Uncheck the box to deactivate this plugin, As soon as you do that, a warning dialog will appear asking you to disable Android APK Plugin, Click OK
Step 4: Once deactivated, click on Apply and restart your Android Studio!

Now you can remove the file from your git change log if it appears there, restart Android Studio and the problem would be fixed.

Warning: The solution requires you to disable two plugins which you might want to use at a later stage, so keep that in mind before you do that.