ratpoison-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RP] Some thoughts about command parsing


From: Gergely Nagy
Subject: [RP] Some thoughts about command parsing
Date: Thu Sep 13 09:07:06 2001
User-agent: Mutt/1.3.20i

Hello again!

I was travelling to my ex-workplace for some papers today, so I had
about 3 hours of idle time, and guess what? I was pondering about the
One True WindowManager, more specifically, a generic argument parsing
thingy for ratpoison.

My first idea was to get the whole command, split it up by each
whitespace, and put the result in a char **foo vector, and set argc to
the number of elements (of course, foo[0] would be the name of the
command itself, see later). However, after some thinking, I dropped
this idea, because it would make the life of cmd_bind harder, for
example.

Just imagine `C-t :bind f exec foobar --some-option baz'. This would
be split up into `bind' `f' `exec' `foobar' `--some-option' `baz', and
cmd_bind would need to combine it into `exec foobar --some-option
baz'. This would be a waste of time and resources.

So, what's next?

When I have time, I code in Perl a lot, and that Language gave me an
idea (don't ask why and where I got this, I just got Enlightened :):
lets have a function, that will split up a command to as many pieces
as requested (or fewer, if there aren't enough arguments). What would
this buy us? Lets see:

First of all, this way each command could request the number of
arguments it needs: bind could say: `I want two arguments', while
another, not-yet implemented command could say that he wants ten.

Our little function would get the string to split, and then it would
start to split it up. When it reaches the maximum chunk count minus
one, it would copy the remaining stuff to the last chunk. For example,
in cmd_bind's case, we'd write something like this:

   struct rp_args *args;

   args = split_commandline ((char *)data, 2);

Then, provided that rp_args has two fields: argc and argv, we'd have
this (if command is the same as above):

     args->argc   : 2
     args->argv[0]: bind
     args->argv[1]: f
     args->argv[2]: exec foobar --some-option baz

I think this is pretty convenient, since we have a generic parser,
which can split up the commands into at most as many pieces as we
want, we'll have argv[0], with the name of the command (this needs
other changes as well), and so on. I hope you see the benefit too, I
can't really explain it right now :)

Anyway, it seems I can't really describe the idea, so the code will
have to speak for itself (I'll probably code it up tomorrow).

Now, let's discuss our second topic: argv[0], with the name of the
command in it. Why the hell is it useful?

Just take a look at cmd_def*pos in actions.c: they all do the same,
the only difference is that they set a different member of the same
struct. They could be written as follows:

char *
cmd_def_pos (int interactive, char *cmdline)
{
  struct rp_args *args;
  int pos;

  args = parse_cmdline (cmdline, 1); /* we take an "x y" arg. */

  if ((pos = pase_winpos (args->argv[1])) < 0)
    {
      message ("Unknown position");
      return NULL;
    }

  if (!strcmp (args->argv[0], "defwinpos"))
    defaults.win_pos = pos;
  else if (!strcmp (args->argv[0], "deftranspos"))
    defaults.trans_pos = pos;
  else if (!strcmp (args->argv[0], "defmaxsizepos"))
    defaults.maxsize_pos = pos;
  else
    message ("Cannot handle this command"); /* Just in case; this
                                               means an error in our
                                               default tables */

  return NULL;
}

I find this more readable, and more compact than the current
implementation. Not to mention that it doesn't duplicate common
code. Albeit, the strcmps might impose some slowdown, but that
shouldn't be measurable, methinks :)

One thing to note: I used an unmodified parse_winpos here, it could be
altered to not do the splitting itself, and then we could pass two
arguments to it, which would be even more convenient. I'll do that in
my implementation.

What do you think?

-- 
Gergely Nagy \ mhp/|8]

Attachment: pgpcYR4SIGn0P.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]