Automate your code fixes
Stop fixing code by hand and automate it. In this post, we’ll show you how.
Why you should automate code fixes
There’s 3 reasons:
1 - Reduce RSI. Fixing code by hand requires a lot of typing. As a programmer, you already type too much, so anything that reduces your typing is good for the health of your hands.
2 - Automated fixers type faster. Don’t try to compete.
3 - Automated fixers are more accurate than you. You’ll miss cases, make mistakes. Automated fixers don’t.
Code Formatters
Most of the time, there’s a code formatter that already does the fix you want. Some are built into programs like atom or VSCode. Some are standalone which works well if you’re using vi. Some are configurable to adhere to variations of a specific standard. Here are some examples of stand alone formatters:
JavaScript: eslint
Python: autopep8 (use with -i)
Go: go fmt
Ruby: rubocop
C/C++: clang-format
Java: uncrustify
CSS: stylelint
HTML: tidy
Scheme: scheme-format (not yet complete)
JSON: json-formatter (jq -S '.')
XML: xmllint --format
YAML: align-yaml
How to use a code formatter
IDE
If your code formatter is built into an IDE, you’ll want to use one of two commands: “format every file in my project” and “format this file”. Ideally you’ll always format your whole project. But, sometimes legacy code isn’t up to par and can’t be changed. Then you’ll only want to format your file. But sometimes even that causes problems. In this case the best you can do is run your formatter on the change diff (as far as I know only clang-format can run on a diff and that’s CLI).
CLI
With the CLI, we’ll get “format this file” for free (and sometimes “format this diff”), but we need to write “format every file in my project.” This is very easy, just add a fmt target to your build tool. Here we’ll use make, but this works with any build automation tool like maven or npm. Then to format, just run the “format build”.
For example, let’s look at the formatter in json-toolkit.
fmt :
./run-formatter
It calls one program “run-formatter” which looks like:
#!/usr/bin/env bash
go fmt json-diff.go &
go fmt json-empty.go &
autopep8 -i csv-to-json &
autopep8 -i dsv-to-json &
autopep8 -i generate-json-diff-results &
autopep8 -i generate-test-results &
autopep8 -i json-sql &
autopep8 -i json-to-csv &
autopep8 -i json-to-dsv &
autopep8 -i json-to-logfmt &
autopep8 -i json-to-xml &
autopep8 -i json-to-yaml &
autopep8 -i logfmt-to-json &
autopep8 -i python-to-json-ast &
autopep8 -i xml-to-json &
autopep8 -i yaml-to-json &
wait
Normally these would all be in the makefile itself, but here I run all of my scripts in parallel. While this can be done within the makefile, it requires a hack, so I prefer to use a separate script.
Write your own autofixer
Sometimes though, standard code formatters don’t do what you need. Maybe you need to refactor some code or fix typos.
Sed
Sed is the easiest and most common tool to write a custom autofixer. If you’re unfamiliar with sed, check out code faster’s posts on mastering sed: part 1 and using sed for find and replace.
Want to change all tabs into spaces?
sed -i "s/\t/ /g" FILE
What about removing trailing spaces from a file?
sed -i "s/ *//g" FILE
If we want to do this on all files, we just need to wrap it in a for bash loop:
for FILE in $(find -type f); do
sed -i "s/ *//g" $FILE
done
If we want to handle an arbitrary list of files passed on stdin, this works too
for FILE in $(cat); do
sed -i "s/ *//g" $FILE
done
One reason why sed is so powerful is that it’s so easy to use sed in a program. This makes it more powerful than find and replace feature built into an IDE.
Regular Expressions
Regular expressions are very powerful. If you need a custom auto fixer, first see if your problem can be reduced to a regular expression problem that sed can solve. Only when it’s clear regular expressions won’t do should you look beyond.
Ex
ex is a file editor that can be scripted. This means by writing custom scripts, we can use ex as an autofixer. I have a soft spot for ex because ex once fixed 1000 lines of code for me. ex is similar to sed as both are descended from ed, but ex has more commands and better geared towards editing files. For example, if you need to switch the 10th and 15th lines of a file, in ex, the script is:
" quote is for ex comments
10m15
" Now the 14th line was the 15th line and we want to make it the 10th line, so we put it after the 9th line
14m9
wq
In sed, it’s doable, but ugly:
# From https://stackoverflow.com/questions/29853735/unix-one-liner-to-swap-transpose-two-lines-in-multiple-text-files
sed -ri '10,15!b;10h;10!H;15!d;x;s/^([^\n]*)(.*\n)(.*)/\3\2\1/' f1 f2 fn
To use ex as an autofixer on a file:
cat script | ex - FILE
To use this on an arbitrary list of files passed on to stdin.
for FILE in $(cat); do
cat script | ex - $FILE
done
Fun fact: ex is vi in command mode
If you type “man ex” in the terminal to bring up the manual for ex, you’ll see the vi manual. Why? Because vi and ex are the same program. Originally Bill Joy wrote ex then tacked on a visual mode that could be invoked with “vi”. Most commands in vi that begin with a colon, like :s/find/replace, are actually ex commands within vi.
General purpose programming language
If sed and ex can’t express the edits you want to make, you can always use a full programming language like python to handle the edits. Conceptually the input is a string and the output is a string, so any general purpose language is up to task.
Conclusion
We’ve seen here various ways to autofix code. We can use premade code formatters, sed, ex, or python. Next week, we’ll look into tools to generate custom code. If you don’t want to miss out, just click “Subscribe now” below