📄 commands.txt
字号:
1998-09-24 Emil Brink Gentoo Command Architecture II1. INTRODUCTIONThis document describes a plausible alternative command architecture forgentoo, the GTK+ file manager I've been poking around with somewhatlately.2. THE OLD ARCHITECTUREThe current command architecture is a three-tier thing; there are threebasic components used to perform actions. These are (in order of increasingconceptual size): 1. Built-In Commands 2. User Commands 3. Command SequencesLet's have a look at each of these three kinds of components in turn:2.1 BUILT-INSA built-in command is a named entity that exists within gentoo, as analways-present basic part of it. Built-ins are accessed by name; eachbuilt-in has a unique name. Examples of built-in command names are Quit,DirEnter, SelectRE and FileDefault. All built-in commands have namesthat begin with a capital letter, and have capital initials in any sub-sequent words. The names never contain whitespace or underscores.2.2 USER COMMANDSA user command is a lot more complex in appearance than is a built-in.As their name sort of implies, user commands are defined and implementedby the user, using external programs (such as shell commands and generalapplications). A user command has a name, by which it is referenced. Italso has a definition, i.e. a string telling which external program isto be envoked, and with which arguments. Special codes can be used insidethe definition in order to have gentoo substitute special data (such asnames of selected files, directory paths to panes, etc). There are alsoa number of flags for each user command, that control various aspectsof the command's execution.2.3 COMMAND SEQUENCESA command sequence is a very dumb thing; it's just a list of commands,that gentoo executes one by one in turn (or in parallel, but that isreally just a special case:). The sequence has no name. You connect acommand sequence to an action (such as a file style action or a button)by explicitly defining the command sequence when defining the style,button or other thing.Once a sequence is defined, you cannot use it from somewhere else withoutsimply defining a duplicate of the same sequence.The ONLY thing you can bind to an action is a command sequence; thereis no way to just put a "bare" command reference in a button.3. PROBLEMSThere are a few problems with the present command architecture, mainly: 1. Since most actions only need a single command, it's in- convenient to first define it as a user command and THEN define a short sequence containing jus the command. 2. On the few occasions when you really want more than one command in a sequence, you create something complex that can't be reused. That is dumb. 3. It's done, and needs no more twiddling to work. :^)4. NEW ARCHITECTUREHere is a proposed (i.e., I'm not sure I'll ever get around to imple-menting this, but I sure want to) new architecture.The core idea here is KISS, at least sort of. To make a complex thingsimple, it's often a good idea to see that can be removed. Try to dothat to the current way things works, and you might hit a wall directly,since (at least to me) it seems as if everything is necessary. Youcan't remove the built-ins, since they're what make gentoo tick in thefirst place. Removing the user commands looks bad too, since you'llwant the ability to use external programs. And of course, you needcommand sequences to allow packaging multiple commands into a unit.If you feel like this, then I'm happy, because that means that myoriginal design doesn't seem all that stupid to you, after all. :)Unfortunately, it does to me, now... Here's the new deal: 1. Keep the built-ins, of course. 2. Remove the user-commands (wait!) 3. Redefine the command sequences.Details follow.4.1 THE BUILT-INSReally no change here, except that I might make it possible for built-in commands to accept general arguments, thus allowing the shortcutsto be reimplemented as ordinary commands (e.g. "DirEnter {$HOME}"). Nice!4.2 THE USER COMMANDSI want to get rid of the concept of named user-commands altogether.See below.4.3 COMMAND SEQUENCESThe big change will be in the command sequences. Currently, a sequencecan be thought of as a comma-separated list of command names to execute(for example: "ActivateOther,DirFromOther,DirEnter,ActivateOther,UnselectFirst"). This is very simple, and works pretty well. It is notvery flexible, though. The proposed solution (?) I have goes likethis: 1. Make the sequences named (makes them reusable). 2. Free form format, with "inlined" user commands.The latter point means that it should be possible to define a sequencelike this: "xv {fp}; UnselectFirst; xv {fp};", to take a silly example.Note how this simply dumps the idea of named user commands, throwingthem directly into the sequence.4.4 PROPOSED CONFIG FORMATSince sooner or later, any new format must be expressed as a serialdata stream in the config file, I might just as well sketch a little onthat, too.What we have is a set of named sequences, each sequence consisting ofany number (from 1 and up) of rows. Each row has a definition string,which might consist of just about anything, a type (I still like to keepbuilt-ins clearly separate from anything else), and some amount ofother, type-specific, data (for external commands, that would be thevarious flags). Here's a sketch of how we might represent this inthe config (stuff in parentheses are comments):<Commands> (The main commands node) <Command> (A command (i.e. a sequence)) <name>show_image</name> <CDef> <CRow> <type>1</type> (Type 1: external program) <def>"xv {fp}"</def> (Definition; call 'xv') <EFlags> (Flags for external command) <general>4712</general> (Some general flags; background etc) <before>0</before> (The classic before and after <after>0</after> flags) </EFlags> </CRow> <CRow> <type>0</type> (Type 0: built-in) <def>"UnselectFirst"</def> (Just a call of a built-in) </CRow> </CDef> (End of 'show_image' definition) </Command></Commands> (End of all commands)4.5 PROPOSED INTERNAL FORMATKnowing how something will look in the config is all fine and nice,but the config file is only that - a file stored on disk. While gentoois running, I would like a somewhat more straight-forward storage format.Executing commands is something done very often in gentoo, and althoughI'm sure we could parse the entire config from scratch everytime andstill not think it's sluggish, I would know that it were and hate it. :)Here's a proposed way of representing these things internally, usinga bunch of simple C structures and some of that wonderful glib glue:typedef enum { CRTP_BUILTIN, CRTP_EXTERNAL } CRType;typedef struct { /* Extra info for external commands. */ guint32 gflags; /* General flags. */ guint32 baflags[2]; /* Before and after flags. */} CX_Ext;typedef struct { /* A command "row". */ CRType type; /* The type of the row. */ GString *def; /* The row definition string. */ guint32 flags; /* Flags common to all types. */ union { /* Type-specific row info. */ CX_Ext external; /* Extra info for external commands. */ } extra;} CmdRow;typedef struct { char name[CMD_NAME_MAX]; /* Name of this command, really. */ guint32 flags; /* Flags for this command. */ GList *row; /* List of CmdRow definition rows. */} Command;The defined commands will then be represented in memory as a bunch ofCommand structures, hashed into a table for quick and easy access.4.6 FEATURESHere are some things that I find particularly neat about this wayof doing stuff, and that really make me itch to start hacking onit:4.6.1 ExtensibleThe above defines two types of command definition rows; built-ins andexternals. Of course, it would be easy to extend this to support more,perhaps another kind of external command (such as a Guile program) oreven some other kind of internal action. Just define a CRType and hackaway.4.6.2 CompatibleOne of the most troublesome/hairy parts of command execution in thecurrent version of gentoo is the continuation of a command sequence,i.e. stopping it in the middle and then continuing at a later time(after the death of a synchronous child). The architecture describedabove should be very compatible with the current way of representingan interrupted sequence, which is just a pointer and an index. In fact,since the individual rows of the command are in a standard GList, I canjust use g_list_nth() rather than my own (pretty complex) stuff.4.6.3 FlagsThe 'flags' field makes it possible to implement the "repeat" featurein a much cleaner way (I won't even mention how it's done using today'sdumb sequences - just let's me say that it's UG-LY!).4.6.4 FlexibilityNotice how a row's definition is always just a GString, rather thanbeing dependant on the type of the command? This makes it possible toadd arguments to built-ins in a very natural way; just type them afterthe command name! I'm not 100% convinced that I want this (only ~99.9),but I sure like leaving the door open. Built-in commands will still beexecuted by just looking their name up in a hash table, of course.5. PROBLEMSThe single biggest "problem" with all of the above is that it is moreor less a full rewrite of large parts of gentoo. But then again, thisfeels a whole lot more like the Right Way of implementing the commandsthan does the old stuff...6. UPDATE!After writing the above, which kind'a served like a planning session,I tore out the entire old command subsystem and rewrote it as describedhere. It was a 3,000+ line rewrite. Now it just plain rules!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -