Adding basic quoting to your use of GNU Readline

August 25, 2013

Suppose that you have a program (or) that makes basic use of GNU Readline (essentially just calling readine()) and you want to add the feature of quoting filename expansions when it's needed. Sadly the GNU Readline documentation is a little bit scanty on what you need to do, so here is what has worked for me.

(The rest of this assumes that you've read the Readline programming documentation.)

As documented in the manual (eventually) you first need a function that will actually do the quoting, which you will activate by pointing rl_filename_quoting_function at. Although the documentation neglects to mention it, this function must return a malloc()'d string; Readline will free() it for you. As far as I can tell from running my code under valgrind, you don't need to free() the TEXT argument you are handed.

You must also set rl_filename_quote_characters and rl_completer_quote_characters to appropriate values. To be fully correct you probably also want to define a dequoter function, but I've gotten away without it so far. In simple cases Readline will simply ignore your quote character at the front when doing further filename completion; I think you only need a dequoter function to handle the case were you've had to escape something in the filename.

With a sane library this would be good enough. But contrary to what the documentation alleges, this doesn't seem to be sufficient for Readline. Instead you need to hook into Readline completion in order to tell Readline that yes really, it should quote things. You do this by the following:

char **my_rl_yesquote(const char *init, int start, int end) {
    rl_filename_quoting_desired = 1;
    return NULL;
}

/* initialize by setting:
   rl_attempted_completion_function = my_rl_yesquote;
*/

Your 'attempted completion function' exists purely for this, although you can of course do more if you want. Note that the need for this function and its actions is in direct contradiction to the Readline documentation as far as I can tell. On the other hand, following the documentation doesn't work (yes, I tried it). Possibly there is some magic involved in just how you invoke Readline and some unintentional side effects going on.

(On the other hand I got this from a Stackoverflow answer, so other people are having the same problem.)

Note that a really good job of quoting and dequoting filenames needs a certain number of other functions, per the Readline documentation. I can't be bothered to worry about them (or write them) so far.

I was going to put my actual code in here as an example but it turns out it is too embarrassingly ugly and hacky for me to do it in its current state and I'm not willing to include cleaner code that I haven't actually run and tested. Check back later for acceptable code that I know doesn't explode.

(Normally I clean up my hacky 'it finally works' first pass code, but I was rather irritated by the time I got something that worked so I just stopped and put the whole thing out of my mind.)

Update: my example quoting function is now in ReadlineQuotingExample.

Written on 25 August 2013.
« My personal view of Fedora versus Ubuntu on the desktop
On classifying phish spam as malware »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sun Aug 25 01:07:37 2013
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.