Moldable Emacs: remove unused React Native styles for a component with tree-sitter
These days I am working on mobile development with React Native. So I was cleaning up my change for opening a Pull Request and I had to refactor a style.js file for a component. This file contains all the style rules for the look and feel of the related React component.
I noticed that some of the style rules where not used in the related component. The situation looked somewhat like this:
import {StyleSheet} from 'react-native';
const style = StyleSheet.create({
used: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
notUsed1: {
flex: 1,
backgroundColor: colors.grayExtraLight,
},
notUsed2: {
alignItems: 'center',
position: 'absolute',
},
}
The issue was that there were a lot of rules in there and it would have been extremely boring to check one at the time. So I thought: this sounds the right job for my moldable-emacs!
The idea was basically to go through the style rules and remove the ones I could not find in the file importing them.
The playground is pretty simple:
(--> (me-by-type 'pair self)
(--filter (s-contains-p "{\n" (plist-get it :text)) it)
(let ((file-using-styles (with-current-buffer "TheComponentUsingTheStyle.js"
(buffer-substring-no-properties (point-min) (point-max)))))
(--remove (s-contains-p (concat "." (car (s-split ":" (plist-get it :text)))) file-using-styles) it))
(me-transit-node-texts it (lambda (text) ""))
me-change-nodes)
I run this from the Playground mold that I open while looking at the style.js file. You can see how it works in this video:
As a reminder, opening the Playground mold sets the self local
variable to a list of plist representing the tree-sitter parse tree.
So with me-by-type I am selecting all the tree-sitter elements that
have type pair. And picking the ones that look like a style rule (in
my case a squiggly bracket with a newline did the trick).
Now, assuming I had open the component file in a buffer, I just
--remove the style rules that are used (again for simplicity I
checked for ".<styleRuleName>"). That leaves me with the tree-sitter
elements that represent unused style rules.
Finally using me-transit-node-texts I remove the definitions of
all those elements.
The last thing I have to do is to also remove commas left in the style file and I am done. I didn't automate that bit because I used this only a couple of times and I could do that on the fly.
As you can see, tree-sitter is not just for code navigation/highlighting ;)
Happy editing!