Wednesday, April 10, 2013

Emacs tip: Use 'view-lossage' to answer the question "How did that happen?"

Does it ever happen that you are thumping along in emacs, and suddenly you are in a mode or buffer that you never knew about before?  You must have unintentionally hit some keystroke that caused the change, but what was it?

You can find the answer by typing C-h l (that's a little "L"). This runs view-lossage, which shows the last 100 characters typed.

For instance, this morning I was suddenly staring at a blank buffer called "ChangeLog". What is that thing? To find out, I typed C-h l. A *Help* buffer opened with a few lines of symbols. Here are the last couple lines:

C-s F I X M E C-a C-n C-n C-n C-n C-n C-n C-n
C-n C-x 2 C-x o C-x V a r C-x u C-h l

You start reading the lossage at the end.  So, at the end I can see the C-h l from invoking view-lossage.  Right before that, an undo (C-x u) to get rid of the typing I had just done into the unknown ChangeLog buffer.  Right before that, C-x V a r.  Ah, I meant to search for "Var", but I must have hit C-x instead of C-s.  This is the culprit.

So what do those keys do?  It opened a new buffer, but did it have some other harmful side-effect I want to know about?  Hit C-h k to start the describe-key function, and start typing C-x, v, a.  Before I could type the 'r', the *Help* buffer showed up and explained that I had entered the keystroke for vc-update-change-log, a function that seems like it was more useful back in the days of RCS than today, but which doesn't harm anything else.  Anyway, mystery solved!

There tend to be two situations in which I call view-lossage.  Number one is where I think, "Hmm, I don't know what I did, but it might be useful."  For that case, view-lossage lets you explore that functionality.  That was the case this morning with ChangeLog; I was curious about it but it turned out not to be useful to me.  Number two is where I think "I don't ever want that to happen again".  In that case, figure out the offending keystroke, and then disable it in your .emacs file, like this:

(global-unset-key "\C-[\C-[") ;; prefix-command
(global-unset-key "\C-x\C-p") ;; mark-page
(global-unset-key "\C-x\C-n") ;; set-goal-column

Those are typos I've made before that have annoying effects, so I just completely disable those keystrokes  (mark-page is especially nasty: it sets the mark at the end of the file, and moves the point to the beginning of the file, so there's not always an easy way to jump back to where you were in the file).


Stumble Upon Toolbar

Friday, January 25, 2013

C++ Private Inheritance

For a long time I believed private inheritance was such an arcane feature that it should be avoided. In my C++ Coding Standard, 8.2 stated "Use only public inheritance." Here was my rationale:

You might find private or protected inheritance useful to save a few lines of code somewhere. But I claim you should just duplicate the lines of code, rather than couple together classes which are so different conceptually that public inheritance can't be used. They might be structurally the same today, but if they are conceptually different, that structural similarity may change over time and give you a huge headache.

I think that rationale is pretty good, but now I've decided it might be worthwhile to use private inheritance in some cases. For instance, it might make sense to inherit from some STL container class, and promote some of its lookup functions or subtypes to "public" with "using" declarations. Like this:

  class Foo : private std::map<int, Bar *> {

  public:
    typedef std::map<int, Bar *> Base;
    using Base::key_type;
    using Base::data_type;
    using Base::value_type;
    using Base::const_iterator;
    using Base::begin;
    using Base::end;
    using Base::empty;
    using Base::size;
    using Base::find;

The likelihood of the structural change mentioned above is very low in this case, and the "using" declarations -- which I'll admit I didn't know could be used that way when I first wrote the standard -- allow you to reuse worthwhile parts of the base class in a very clean and foolproof manner. Later if you realize there's another bit of functionality you want to expose publicly, you only have to write a one-liner, not a wrapper function. Meanwhile, things you might not want exposed -- like operator[]() -- stay out of the interface.

But the clincher for me is that you had better not inherit publicly from a class like std::map.  Why?  Because it doesn't have a virtual destructor.  What if someone -- for whatever reason -- ends up with a pointer to a std::map which is actually one of your Foo objects, and wants to delete it?  Only the map destructor will be called.  If ~Foo() was supposed to delete its values, that won't happen.  Similarly, public inheritance means that someone could take a pointer to a Foo, and then use map's copy constructor or assignment operator to make a simple pointer copy of the Foo, perhaps unintentionally.  Then if the original was deleted, and deleted its values, the copy would hold stale pointers.

Interestingly, I didn't seem very worried about that situation when I annotated the standard.  I wrote that you might sometimes break 8.4 -- "Destructors of base classes must be pure virtual (but implemented)." -- giving this bad advice:

If you have a memory-sensitive class where subclasses will not be used polymorphically (or do not require polymorphic destruction), you can disregard the rule and get rid of the virtual table pointer.

That seems ridiculous now.  That is actually exactly the use case for private inheritance:  you want to reuse some code, but not polymorphically.

This all came to the fore today when I considered making a class 'public std::pair', so it could model an Edge in a Boost Graph Library edge_list<>, which requires 'first' and 'second' members (at least in the iterator class you instantiate edge_list<> with).  But recently a friend of mine had twitted me on another class I wrote that inherits publicly from an STL container, so I started to think about these issues.

I'm still not sure how I'll implement my Edge class -- except that it won't be public pair -- but I see that I need to change the coding standard someday soon, to reflect the reasonable usage of private inheritance.


Stumble Upon Toolbar

Wednesday, September 19, 2012

Don't "Namespace" Filenames

When I first started this blog, I wrote up a rant about directory names that mislead about what their contents are. At the same time, I complained about adding unnecessary morphemes to directory names, things like "db" or "model" or such-like.

I've recently become annoyed with the habit of -- for want of a better term -- "namespacing" directory names and file names. I'm not saying not to use good namespace discipline in source code. What I mean is having a directory structure like this:

  zoo/
    zoo_iface/
      zoo_cmds.hpp
      zoo_cmds.cpp
      ...
    zoo_model/
      zoo_cage.hpp
      zoo_animal.hpp
      ...

Why does everything have to start with "zoo"? Look at it this way: if that was how we named people, then everyone's last name would be part of their first name and also part of their middle name. Instead of calling someone Mary Jane Smith, we would know her as MarySmith JaneSmith Smith. Some people make it even worse by prepending the full directory name onto the file name -- like "zoo_model_cage.hpp". Poor Mary Jane would be MaryJaneSmith JaneSmith Smith.

Of course, a source file name may be dictated by its contents -- you're following our C++ standard, right? -- so my ire is directed at redundant directory names more than filenames.

This principle doesn't have to stop at source files.  It boggles my mind that raw bug testcases where I work start their life with names like this:

  /home/bugs/prod1_bugs/comp2_bugs/bug6003.tgz


For crying out loud, I know this is a directory full of bugs, can't we just call each bug something like:

  /home/bugs/prod1/comp2/6003.tgz


?


Stumble Upon Toolbar

Tuesday, September 11, 2012

Disabling Auto-Indent in Emacs

I have to edit a C++ file at work whose indentation is so screwed up that any punctuation key I type ends up changing the indentation of the line I'm working on to something that is way out of line with the text right around it. For sanity's sake I have to M-x set-variable c-syntactic-indentation nil when I'm working on that file. The c-syntactic-indentation variable does not start out buffer-local, meaning that for the sake of the one stupid file, I have turned off the very useful feature of syntactic indentation for every file I have open in that session. So, if you are ever going to set it temporarily, make sure you have this line in your .emacs file:

  (make-variable-buffer-local 'c-syntactic-indentation)
 
While you're at it, don't you want a shortcut for the set-variable? I amused myself greatly this morning as I tried to think what shortcut I would assign this action to. The obvious mnemonics I polled with C-h k were taken: I have C-c TAB set to indent-region, C-c ; to comment-region, and C-c { set to a function to insert a skeleton class definition.  What to do?  I finally hit upon C-c (, and lo-and-behold I had already set that keystroke to toggle c-syntactic-indentation, sometime in the distant past! Here's the code:

  (global-set-key "\C-c("
                  '(lambda ()
                     (interactive)
                     (setq c-syntactic-indentation (not c-syntactic-indentation))
                     (message "c-syntactic-indentation set to %s"
                              (if c-syntactic-indentation "t" "nil"))))


Stumble Upon Toolbar

Friday, June 1, 2012

Emacs: Scroll Other Window Up

It often happens that I have two related files open in one emacs frame, and I want to scroll around comparing them.  Of course to scroll back and forth in a single buffer, C-v scrolls you down, and M-v scrolls you up. (In a perverse bit of emacs jargon, C-v's function is called "scroll-up", since the text moves "up" relative to the fixed window -- even though every human wanting to look lower in the file thinks and says "scroll down, scroll down" -- and M-v's function is called "scroll-down".)

To keep two files synchronized as you peruse them, the power tool to use is M-x ediff-buffers, which sets up an interactive diff session to step through the diffs. Within ediff, a simple lowercase "v" scrolls lower in both files at once, and uppercase "V" scrolls higher. Don't forget M-x ediff-revision as a handy tool for comparing a version-controlled file to its latest revision, or for comparing two different revisions interactively.

Ediff is great, but sometimes it is too heavy-handed for the eyeballing I'm trying to do. For one thing, if one of the files contains a large section that is missing in the other, scrolling both files at once means striding through the section in one window while inching down a line at a time in the file that lacks it. Also, navigating ediff can be tedious if there are a great number of changes or reordered chunks, and once your diffs no longer line up sensibly, ediff's highlighting is simply a nuisance.

So there are the old standbys C-v and M-v, plus there is the handy M-C-v, which scrolls lower in the other window. That is, if I have a.txt and b.txt open in a single frame, and the cursor is in a.txt, then M-C-v will show a lower chunk of b.txt, to keep up with C-v in a.txt. Until today, whenever I wanted to move higher in b.txt, I didn't know of a single keystroke to do that, so I always just switched windows and used M-v. I could do C-u - M-C-v, but I never liked that.

Turns out there is a keystroke to scroll higher in b.txt without switching windows: M-C-S-v -- same keys as scrolling lower, plus the shift key. Now, M-C-v is a pretty ergonomic companion to C-v. I lean the base of my left hand on the Ctrl key, hit V with my left index finger, and keep my thumb poised over the Alt key to choose which window to scroll. The shift key just does not fit in with this scheme. With some effort, I can hold it with my left pinkie, but it's not comfortable. So my new solution is to tie that command to C-c M-C-v. True, it's not a single keystroke, but unlike the C-u solution above, it's all in the left hand, and close together without being cramped. The .emacs line is:

  (global-set-key "\C-c\M-\C-v" `scroll-other-window-down)

Yes, the command to go higher in the file -- to scroll up as we humans say -- is "scroll-other-window-down".


Stumble Upon Toolbar

Thursday, January 12, 2012

gcc error: invalid use of member (did you forget the `&' ?)

Every time I have gotten the above compilation error, it has nothing to do with a missing ampersand. Instead, it is missing function-call parentheses:

  if (you_go && use->yourMember) { // WRONG!
    this->isInvalid();
  }

  if (i_go && use->myMember()) { // Oh yeah, the parens.
    continue;
  }

So don't use your member invalidly.


Stumble Upon Toolbar

Friday, March 11, 2011

Don't Avoid No-ops

A form of spurious case analysis that seems to come up a lot in the code I have to work on right now falls under the category of "avoiding a no-op". Well, don't add cruft to your code just to avoid a no-op.

Here's the one that I see hundreds of:

  if (ptr != NULL) {
    delete ptr;
  }
Instead of:
  delete ptr;
But the line that caused me to post this today was this:
  if (!isalnum(str[i]) && (str[i] != '_')) str[i] = '_';
Why complicate the if condition just to make sure and not overwrite an underscore with an underscore? In reading through this code I paused to consider when an underscore could occur, and whether something special had to happen, only to read a little further and see that someone was guarding against a no-op. Good lord, just perform the no-op so I can read this more easily:
  if (!isalnum(str[i])) str[i] = '_';


Stumble Upon Toolbar