Hi, As you noticed I put important in the topic. I personally consider scripting one of the most important features that has to be implemented before GRUB 2 can be used in distributions.
It's also one of the features that we all have to talk about before we determine it will not be changed. After GRUB 2 is being used by everyone it will be hard, if not impossible, to make changes that make different GRUB 2 versions incompatible. So it is important that most active developers read my ideas about scripting and what I currently implemented. As you might have noticed, I wrote this in little time and thus it will be a bit chaotic and it is not well written. But I hope I can start this important discussion this way. Another thing I want to discuss soon is using "cd" and "pwd" commands to change the current directory instead of what we have now. I would like to make this change as well. I'm looking forwards to your ideas, questions, suggestions, criticism and bug reports. :-) -- Marco ========= Variables ========= In GRUB 2 there are two types of variables. The difference is like in bash: the scope. Variables either have a local or global (exported) scope. Initially all new added variables have the local scope. By using the export command they can be made global. Some variables have a special purpose and will be created by GRUB. These are: - root: The active disk/partition (rw, global) - prefix: The pathname used to load grub.cfg and the modules (rw, global) - platform: Set to the platform, eg. EFI, IEEE1275, PCBIOS, etc. (ro, global) - processor: Processor architecture GRUB was compiled for, eg. PPC, x86 (ro, global). - debug: Print debugging messages for certain parts of the code, or all messages when set to all. (rw, global?) - pager: When set to `1', wait for a key when the bottom of the screen was reached. (more will be added, like variables to read time/date, random, etc) To include a file two commands can be used. The first is source, which does not change the scope. The second is `configfile' which opens a new scope. Variables can be used like in bash. You can use set to set or list variables. Explicit assignments (`foo=bar' instead of `set foo=bar') is possible. You can include variables in command lines by using the `$' prefix, for example $foo. To use it to concatenate variable contents and text, you can use the ${foo} syntax. Sometimes you want to use the `$' in commands (for example, multiboot lines for the Hurd) without meaning a variable, in that case you can use single quotes for escaping (for example, '$foo'). ==> Currently unimplemented: The export command, special variables other than root, prefix, debug and pager. Concatenating with variables is currently broken. ========= Functions ========= Functions can be created as follows: function funcname { code } After that they can be called just like any other command. Arguments can be passed to functions. In the function body they can be accessed as in bash ($1, $2, etc). ==> Currently unimplemented: Function arguments. ==> Idea: Exporting functions to be full featured commands that can be tab completed, documented, etc. This way functions can be implemented by scripts instead of C code. ==== If ==== The if command is also quite similar to the if command in bash. It has the following syntax: if command ; then commands fi OR: if command ; then commands else commands fi The command that follows the if contains the condition that is tested for. You can use any command and check the return status like this. The most useful command to use here is the `test' (or `[') command. It is similar to the test command in bash, although it can not check for certain filesystem bits like file protection and certain filetypes. ==> Currently unimplemented: The test command (although it is almost finished). ============ Menu entries ============ Menu entries are added with `menuentry' (or its alias `@'). It's important to notice this is not a command. Because it's part of the scripting syntax, it can have unique features. A menuentry is like a function, especially because it can have arguments! Syntax: menuentry "Entry name" [arguments...] { body } Make sure the entry name is properly escaped, otherwise spaces can not be included and will be seen as separator. The arguments will become semi-variables like #1, #2, etc. These can be used so one menuentry can be used as a template for a lot of menuentries. This can best be explained with an example: (inside loop that sets i = 1...x) @ "Partition $i" $i { linux /vmlinuz root=/dev/hda#{1} } This will set #1 to $i (it's the first argument). The menuentry command is executed for i=1...9 and will generate 9 different menu entries. This is useful for automatic generation of menu entries. ==> Currently unimplemented: Arguments for automatic generation of menuentries. ==> Discussion: Perhaps I will change the #1 into $1, although this is not really a variable. ===== for ===== The for command can be used to iterate over a set of data. I don't like the idea of implementing this *exactly* like in bash. Personally I am thinking of the following syntax: Iterating over files: for x in (hd0,3)/foo/* ; do commands ; done The commands will be executed for each file in the directory. Iterating over disks: for x in (*) ; do commands ; done Iterating over partitions: for x in (*,*); do commands ; done An alternative syntax which I think is more natural could be: foreach x in files ; do commands ; done foreach x in disks ; do commands ; done foreach x in partitions (hd0) ; do commands ; done foreach x in modules ; do commands ; done The foreach syntax makes it possible to add named iterators with arguments. In that case modules can be written that add new iterators. Perhaps even scrips can be used for this. I don't like the idea of using the standard output of files for this, because I am afraid this will get messy and tricky. ==> Currently unimplemented: All of this. =========================== Other language constructs =========================== Other language constructs can and will be implemented. Like: elif, while, case, select, etc. ==> Currently unimplemented: All these constructs. =============================== Commands useful for scripting =============================== - echo: Prints text. - cmp: Compares files. - configfile/source: Including other files. - search: Search for files, labels, etc. and set a variable. - test: Test certain conditions. ==> Currently unimplemented: Echo can't "beep". ================ Error handling ================ Every command can return an error value. This error value will be available as $?. This variable will be checked by if, while, etc. In scripts all parsing errors will be non fatal so the system is not left unbootable. Unparsable menu entries will be added, but will not be executable, only the editor is available. One special purpose variable $ERROR will be added. It will contain the error strings when $? is set to non-zero. In that case you can do error handling in scripts. After every command an error is printed by default. You don't want this to be silent, otherwise users can not detect errors. But it should be able to set error handling to silent because a certain script or function does its own error handling. This can be done by setting $ERRORS=0 (default it is set to 1). ==> Currently unimplemented: $ERROR, $ERRORS, a lot of this logic is far from perfect. _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel