Tuesday, March 13, 2012

Choosing Emacs as a Text Editor with Macro Capabilities

I had a project that called for a text editor with macro capabilities. I went searching for one. This post describes how that turned out.

I started by trying Notepad++. It did have a simple macro recording capability: just select Macro > Start Recording. The particular application I had in mind involved a search for certain text. This couldn't be done in Notepad++. Its help file said, "Currently (v.5.4.3), macros cannot save Find(/Replace) operations."

So I looked for alternatives. Wikipedia offered a longish list of them, but without detailed feature information. I found a Lifehacker article that suggested Emacs as a second-best after Notepad++. I hadn't used Emacs since 1982. Last time I'd tried, maybe around 2005, it had been intimidating. Was I ready to invest time to become competent in Emacs? Lifehacker called it "primarily a text editor for serious programmers." Lifehacker said an alternative with comparably good macro capabilities was Vim or, less intimidatingly, Cream.

I looked at Cream. I saw that it had a keyboard macro capability (Shift-F8 to record, F8 to play). I downloaded and installed it and tried its macro features. It may have saved the macro somewhere, at least temporarily. But it didn't give me an option to save it permanently or assign it to a function key. There didn't seem to be a way to auto-run a macro on startup or file opening. This tool seemed to be rather extremely different from something like Emacs.

What I was really looking for, and what I found at this point, was the Extra Features table in Wikipedia's comparison of text editors. There, I found a column, "Macro Language." I didn't necessarily need a whole language, but I had missed not having something along those lines, which I had used extensively in certain DOS programs (especially WordPerfect and Paradox) in the 1990s, and had never gotten back to after switching to Microsoft Office. If I relied on Wikipedia's comparison to steer me to a text editor that definitely had a macro language, newline conversion capability, large file support, and graphical shell integration, for no cost in a Windows environment, then my candidates seemed to be AkelPad, ConTEXT, GNU Emacs, PSPad, Vim, and XEmacs.

I had missed some things about the Emacs world, and was inclined in that direction. Wikipedia and WikiVs articles on the choice between Emacs and Vim did not change that feeling. After browsing a discussion or two of the choice between GNU Emacs and XEmacs, I decided I preferred the former. But then it developed that there were quite a few other versions of Emacs. I was tempted to go with MicroEmacs, as I thought it might be simpler. The JASSPA version seemed to be most actively developed.  But then I decided that, to avoid bugs and have deep support in complex problems, it made more sense to go with the most mainstream version, and that seemed to be GNU Emacs.

I downloaded and installed the most recent GNU Emacs from Softpedia (apparently released within the past few months), though possibly I should have gone to the official download site. I say "installed," but actually it seemed to be pretty much a portable. Looking through the two accompanying "read-me" files (one of which was not formatted for use on Windows machines), I saw that they advised putting it into a folder whose directory path contained no spaces. There were a few installation options. One was to run the file called Emacs\bin\addpm.exe. Another was to create a shortcut to Emacs\bin\runemacs.exe. There was also the option of running a REG file to make some changes. The file as they gave it to me contained just a couple of lines that added a context menu option, "Open with Emacs." The entire contents of the REG file were:

Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\AllFilesystemObjects\shell\Open With Emacs\command]
@="C:\\emacs\\bin\\emacsclientw.exe -n -a \"C:\\emacs\\bin\\runemacs.exe\" \"%1\""
The read-me seemed to say that I could add some formatting options to that REG file, specifically:
[HKEY_LOCAL_MACHINE\SOFTWARE\GNU\Emacs]
"Emacs.Background"="Black"
"Emacs.Foreground"="Wheat"
"Emacs.ScrollBars"="OFF"
"Emacs.MenuBar"="OFF"
"Emacs.ToolBar"="OFF"
"Emacs.Geometry"="125x43+0+0"
But when I tried to add those keys and values to the registry manually, I didn't see that they were making any difference. I wondered if they were perhaps intended for the text version as distinct from the GUI version; the latter seemed to have its own menu-driven configuration options.

That seemed to be all there was, by way of preliminaries. Going into the actual Emacs program, the read-me files recommended starting with Emacs > Help > Tutorial. The opening screen contained a link to the tutorial and also to a Guided Tour and to the Emacs Manual. The tutorial was contained within Emacs and didn't seem to be available online. The Guided Tour and the Emacs Manual were available online. There were also other tutorials out there. Examples included a Rice University PDF that only seemed to be available from a University of Illinois website, a University of Chicago tutorial, and a GNU Emacs 101 for Beginners webpage. There were other help sources as well, including the GNU Emacs FAQ for MS Windows, the help-emacs-windows listserv, and two Usenet groups (gnu.emacs.help and comp.emacs).

The GNU Emacs for Beginners page, and others, had some tips. One was to start with the menus and worry about the "keybindings" (i.e., the Ctrl- and Alt- multi-key options) later. Another was to use Ctrl-] (i.e., control - right bracket) to kill funky processes, if the program started to seem out of control. Also, they said, "Meta" was the old (still used in Emacs) name for the Alt key.

The University of Chicago tutorial seemed to have been written for non-GUI users. I read it partway nonetheless. It was talking about key combinations. It said they were written in shorthand, as C- (for Ctrl-) and M- (for Meta- (i.e., Alt-)). Sometimes it would apparently be necessary to use Esc instead of Alt, but in those cases (unlike C- and M-) you'd just tap it, not hold it. You'd do your work in a buffer, not directly in a file; the changes in the buffer would then be written to the file. C-x commands would do things on the environmental level (e.g., open files, save your work, manipulate windows). Control combinations had to be entered sequentially, lifting off the Ctrl key and then hitting it again as needed.  For example, C-x C-e did not mean C-x-e.  The Rice University thing (dated 2002) also had information about these key combinations.

It looked like the best sources of information would be the FAQs, the Emacs Manual, and the Guided Tour, which was actually more like an introduction to general concepts.  The manual included in Emacs itself seemed to be the same as the online manual.  The included tutorial was actually just a long (maybe 15-page) single-spaced text file.

I wasn't sure I needed all that right now.  I went looking for information on macros specifically.  So that started my education in Emacs:  Ctrl-F (or should I say C-f) would not do a Find; instead, it would move the cursor Forward one space.  To find the part of the tutorial that talked about macros, I needed to use C-s (i..e, search forward) or perhaps C-r (i.e., reverse).  There wasn't a search box per se; there was a search line on the bottom of the screen.  Nothing on macros in the tutorial.  The online Guided Tour said F3 would start recording a macro and F4 would stop and would also do playback.

So, OK, I would open a file of the kind that I wanted to edit; I would go to its end, since I was looking for the last occurrence of a certain text string (specifically, "Content-Disposition: attachment;"); I would do a C-r to back up to that last occurrence; and then I would need to know how to delete everything after that point.  So here were the steps to get that far:
  • Opening the file:  Menu > File > Open
  • Going to its end:  C-end (just like in Word)
  • Searching for last occurrence of text:  C-r.
  • Text to search for:  I could have typed in the "Content-Disposition: attachment;" string that I was searching for, but could I paste it into the search?  Ctrl-V didn't work, at least not without customizationA search led to an indication that the customization itself could be relatively easy, though there were multiple preparatory steps.  First, I had to have an "init" file.  It could be called _emacs and it had to be in my Home directory.  To find Home, I typed C-x C-e (insert (getenv "HOME")) and saw that it printed, in the text of the file I was looking at, this location:  C:\Users\Ray\AppData\Roaming.  (I had to give it a minute after the C-e before it brought up the "Eval" space at the bottom of the screen.  Once it did that, I could type the (insert (getenv "HOME")) part.)  In Windows Explorer, I created a new _emacs file (not _emacs.txt) in that folder, opened it with Notepad, put (setq x-select-enable-clipboard t) into it, and closed it.  I closed and restarted Emacs.  Ctrl-V still did not work to paste contents of the Windows clipboard into Emacs.  I noticed this in the lower half of the Emacs screen: Warning (initialization): `_emacs' init file is deprecated, please use `.emacs'. I tried to change _emacs to .emacs, but Windows Explorer said, "You must type a valid file name."  So I left it as _emacs and, ultimately, I just typed in the "Content-Disposition: attachment;" text that I was looking for.
  • Marking the start of the text to be deleted:  I wanted to delete everything from "Content-Disposition: attachment;" on to the end of the file.  In Emacs-speak, this was called "killing" a "region."  First, I had to set the "mark" at one end of the region.  I probably could have done that already at the end of the file, but I wasn't thinking that way.  I was at "Content-Disposition: attachment;" now, so I set the mark by hitting C-space.  The bottom line in Emacs gave me a gratifying little confirmation:  "Mark set."
  • Marking the end of the text to be deleted:  the deletion would apply to everything between "mark" and "point."  Point seemed to mean just the location of the cursor.  So I just hit Ctrl-End to go to the end of the file.  I saw that all this text was now highlighted.
  • Deleting the selected text:  to kill the region, I just hit Delete.
  • Saving and closing the file:  Menu > File > Close.  I got a dialog telling me that a buffer had been modified and asking if I wanted to kill anyway.  I said yes, and then I reopened the file to see what happened.  My change had not been saved, so I redid it, and this time I did save first.  I used the key commands instead of the menu pick:  C-x C-s.  Then I quit with C-x C-c.
Now I wanted to be able to automate those commands in a macro.  That called for another sequence of steps:
  • Create the macro:  I opened the next file that needed the treatment just described.  I hit F3 and went through those steps, ending with the file save.  Then I hit F4 to end the definition.  I got a confirmation at the bottom:  "Keyboard macro defined."
  • Name the macro:  I just wanted to call it Macro1.  It seemed that several macro-related commands started with C-x C-k.  To name the macro, I typed C-x C-k n Macro1 followed by Enter.  It didn't give me a confirmation, or maybe I missed it before I hit Enter, which may have been unnecessary.
  • Bind the macro to a specified key:  in case I wanted to be able to run Macro1 by just hitting a key (instead of using its name), I typed C-x C-k b 1.  This command would "b"ind the last keyboard macro (i.e., the one I had just defined) to key 1.  To run it, I could hit C-x C-k 1.  The same approach would work if I wanted to assign macros to C-x C-k 2 through 9 and A through Z (capital letters only).  That is, (a) the binding process would be this simple, for 1-9 and A-Z, and (b) those particular key combinations were safe to use (i.e., were not already spoken for).  I got a confirmation:  "Keyboard macro bound to C_x C-k 1."
  • Save the macro in a file:  to make Macro1 available if I stopped and restarted Emacs, I had to "visit" the file where I wanted to save its definition.  I decided to call this file "Macros."  There was a menu option to visit a new file.  I tried C-x C-f Macros [Enter].  It defaulted to putting this file in the directory where I had last been working (i.e., where the files I was editing were located).  I decided this was OK for now; I could move the Macros file later if I wanted to keep it after this job was done.  It confirmed:  New file.  Now, to save Macro1 in Macros, I typed M-x insert-kbd-macro [Enter] Macro1 [Enter], where M- meant Alt-.  The top pane showed a bunch of mostly numbers.
  • Test the macro:  I closed Emacs.  The confirmation line asked if I wanted to save Macros.  I typed y.  It closed.  I reopened Emacs and typed C-x C-k 1.  The bottom line said, "C-x C-k 1 is undefined."  I typed M-x load-file [Enter].  It volunteered to load something from my Emacs program folder.  That wasn't where I had saved the Macros file.  So I would apparently have to type the full path name.  Once I did type D:\Folder\Subfolder\Subsubfolder\Macros, I got a confirmation:  Loading ... done.  I made sure the next file to be fixed was visible and that's where the cursor was, and then I tried C-x C-k 1 again. Still undefined.  I tried F4:  "No kbd macro has been defined."  It wouldn't accept C-x C-k e Macro1.  I moved the file to D:\Folder and renamed it to Macros.el.  This made no difference.
  • Correct my mistakes:  eventually I came to understand that I should have named the macro (C-x C-k n Macro1) and then saved it by opening C:\Users\Ray\AppData\Roaming\_emacs and then typing M-x insert-kbd-macro [Enter] Macro1 [Enter].  So I hit F3, re-ran the sequence of steps, hit F4, and then named and saved it in that way.  Or, I should say, tried to save.  When I typed M-x insert-kbd-macro [Enter], it prompted me with "Insert kbd macro (name)," and when I typed Macro1, it said, "No match."  I opened another file to edit, hit F4, and it ran.  But it ended in the _emacs file, so maybe I hadn't hit F4 to end it at the right time.  I went through the F3 paces and so forth, another time, with another file.  This time it seemed to work:  the _emacs file in the bottom pane of the two-pane Emacs window now contained some codes.  I saved _emacs.  But, oops, I hadn't assigned it to a key.  I opened another file to edit, hit F4, and observed that the macro failed to run.  I must have screwed something up.  I went through the F3 process again.  This time I hit F4 several times at the end.  I typed C-x C-k n Macro1a [Enter].  I bound it to the 1 key by typing C-x C-k b 1.  I saved it to _emacs by clicking in the bottom pane, where _emacs was still open, and typing M-x insert-kbd-macro [Enter] Macro1a [Enter].  This added more text to _emacs, identical to what I had added before except it referred to Macro1a instead of Macro1.  I manually deleted the extraneous Macro1a lines and saved _emacs.  I opened another file to edit and hit C-x C-k 1.  The macro didn't work.  It went to the end of the file and stopped.  I suspected the reason was that, at file's end, I had hit C-f (i.e., the Windows Find combination), intending to tell it to search backwards, and had gotten an error message:  I was supposed to search with C-r from the file's end (not with C-f).  Apparently the error message terminated macro recording.  So I went through the steps again, starting with F3.  This time, there was a larger amount of code saved in _emacs, in the bottom pane, and it included references to desired steps like "delete) and "(menu-bar) file save-buffer."  I manually edited _emacs again so that Macro1 (not Macro1a) would be associated with all these nice lush codes.  I opened another file and hit C-x C-k 1.  This time, it got to approximately the point where it should have started deleting, and stopped there with an error on the bottom line:  "After 0 kbd macro iterations: Keyboard macro terminated by a command ringing the bell."  I suspected this, too, was due to an error during macro recording, though not one that I would have expected to matter.  After hitting C-r, I had told Emacs to search backwards for Content-d.  That's as far as I got:  a small d, instead of D as in Disposition.  Typo.  But the macro had recorded it literally, which it would not have done when recording a keyboard macro in Word.  I wondered if I could please make it through a F3 macro recording session without any typographical errors.  Trying again with F3, I got another Macro1a saved in _emacs.  And this time, by God, it worked.  C-x C-k 1 did exactly what it was supposed to do, right down to the final step of saving the edited file.
That worked.  I had a text editor with macro capabilities.  And I could tell already that it was going to be sweet, special, loving, but also nasty, and sweaty, and sometimes hostile and ugly . . . oops, familiar rant, wrong context.  Point is, I was coming home.

1 comments:

raywood

A later post contains a refined statement of how I got Emacs to work on a similar problem.