Some Emacs Notes (mostly hide-show)
I spent most of yesterday troubleshooting someone else's code and I found these commands useful (among others - these are just the ones that I had to look up).
At one point, for instance, I thought that two class names looked the same, so I guessed that whoever wrote the code probably lost track of the classes that they had defined and duplicated (at least) one of them. To check I entered:
M-x occur class
Which brought up a list of lines that had the word 'class' in them and found that they had indeed duplicated that class definition. The argument 'class' is a regular expression so if there were other places where the word 'class' was used (e.g. in a nested class or a comment), you could add a start of line character:
M-x occur ^class
This would only bring up lines that started with the work 'class'.
If, for example, you had these class definition:
After you folded it you would see:
To enable hide-show for the buffer you're in:
M-x hs-minor-mode
But in my case I want it to always be on when I'm editing a python file so I added this to my ~/.emacs.d/init.el file:
(defun turn-on-hideshow () (hs-minor-mode 1))
(add-hook 'python-mode-hook 'turn-on-hideshow)
I don't know why but emacs doesn't seem to have a way to automatically associate minor-modes with file-extensions so the work-around is to first define a function that turns on the minor mode (called 'turn-on-hideshow' in this case) and then add it to the hook of the major-mode ('python-mode-hook' in this case). Once you have hideshow working, you have a few options available to you (see the wiki) but I only use three of them most of the time.
The main trigger for 'hs-minor-mode' is C-c @ which you follow with the actual command. For instance, to hide (fold) everything that isn't flush-left:
C-c @ C-M-H
which translates to control-c, @, control-alt-shift-h ('H' is for hide).
The opposite (show all the hidden text) is:
C-c @ C-M-S
The only other command that I use a lot (so far) is toggle block:
C-c @ C-c
What this does is toggle the block where your cursor is currently located. A block is the line that is flush left and all the lines that follow it that are indented. So, if you have multiple classes and functions defined, each one of them would be a block. If the block you're at isn't folded, then entering C-c @ C-c will hide the indented lines and if they are already hidden then it will un-hide them.
To jump to the previous paragraph:
M-x {
To go to the next paragraph:
M-x }
C-c @ C-M-H
Then I noticed the duplicate class names so I listed all the classes that had that name:
M-x occur class <class name>
Occur gives you the line numbers so you can jump right to the line (although if the line is within a folded block you have to un-fold it first) so I created two windows:
C-x 2
Then I jumped to the starting line of the first definition in the first window (line 5 in this example) and un-hid it:
M-g-g 5
C-c @ C-c
Then navigated to the other window and jumped to the starting line of the second definition (line 50 in this example) and un-hid it:
C-x o
M-g-g 50
C-c @ C-c
Inspecting the definitions revealed that they had the same attributes but were assigned different values so I had no way of knowing which was the class definition to keep and the person who wrote them was on vacation so I decided not to fix it (I needed a different class in the module so this didn't directly affect me).
Occur
One problem that I ran across was that there were around two dozen class definitions, all of which were similar so the bugs that were in one tended to be in all the other classes as well. I found that using the M-x occur command was useful for looking at all instances of certain lines, so I could search for things that were common among all the class definitions (occur is aliased by the list-matching-lines command).At one point, for instance, I thought that two class names looked the same, so I guessed that whoever wrote the code probably lost track of the classes that they had defined and duplicated (at least) one of them. To check I entered:
M-x occur class
Which brought up a list of lines that had the word 'class' in them and found that they had indeed duplicated that class definition. The argument 'class' is a regular expression so if there were other places where the word 'class' was used (e.g. in a nested class or a comment), you could add a start of line character:
M-x occur ^class
This would only bring up lines that started with the work 'class'.
Hide-show
This is an emacs mode that I keep rediscovering so I figured I should write it down. This mode enables code-folding (since I program in python this means hiding code that is indented.If, for example, you had these class definition:
class Test(object):
def __init__(self, x):
self.x = x
class TestTest(Test):
def __init__(self, y, *args, **kwargs):
super(TestTest, self).__init__(*args, **kwargs)
self.y = y
After you folded it you would see:
class Test(object):
class TestTest(Test):
To enable hide-show for the buffer you're in:
M-x hs-minor-mode
But in my case I want it to always be on when I'm editing a python file so I added this to my ~/.emacs.d/init.el file:
(defun turn-on-hideshow () (hs-minor-mode 1))
(add-hook 'python-mode-hook 'turn-on-hideshow)
I don't know why but emacs doesn't seem to have a way to automatically associate minor-modes with file-extensions so the work-around is to first define a function that turns on the minor mode (called 'turn-on-hideshow' in this case) and then add it to the hook of the major-mode ('python-mode-hook' in this case). Once you have hideshow working, you have a few options available to you (see the wiki) but I only use three of them most of the time.
The main trigger for 'hs-minor-mode' is C-c @ which you follow with the actual command. For instance, to hide (fold) everything that isn't flush-left:
C-c @ C-M-H
which translates to control-c, @, control-alt-shift-h ('H' is for hide).
The opposite (show all the hidden text) is:
C-c @ C-M-S
The only other command that I use a lot (so far) is toggle block:
C-c @ C-c
What this does is toggle the block where your cursor is currently located. A block is the line that is flush left and all the lines that follow it that are indented. So, if you have multiple classes and functions defined, each one of them would be a block. If the block you're at isn't folded, then entering C-c @ C-c will hide the indented lines and if they are already hidden then it will un-hide them.
Paragraph Navigation
This is one of those things that you learn when you first go through the emacs tutorial, but somehow I always forget it - emacs will jump between paragraphs (it uses newlines so it doesn't work quite right for code, but works for expository text).To jump to the previous paragraph:
M-x {
To go to the next paragraph:
M-x }
How I Used It
I don't want to share the code (since it wasn't mine) but in a nutshell what I faced was a file with a couple-dozen class definitions (this was a django-factory-boy module so each model (database table) had two classes, a straight factory and a fuzzy version), so the first thing I did was fold all the classes to make it easier to get a high-level view:C-c @ C-M-H
Then I noticed the duplicate class names so I listed all the classes that had that name:
M-x occur class <class name>
Occur gives you the line numbers so you can jump right to the line (although if the line is within a folded block you have to un-fold it first) so I created two windows:
C-x 2
Then I jumped to the starting line of the first definition in the first window (line 5 in this example) and un-hid it:
M-g-g 5
C-c @ C-c
Then navigated to the other window and jumped to the starting line of the second definition (line 50 in this example) and un-hid it:
C-x o
M-g-g 50
C-c @ C-c
Inspecting the definitions revealed that they had the same attributes but were assigned different values so I had no way of knowing which was the class definition to keep and the person who wrote them was on vacation so I decided not to fix it (I needed a different class in the module so this didn't directly affect me).