home *** CD-ROM | disk | FTP | other *** search
-
- Mi-Shell Reference Manual
- Jean Michel
- Version 1.10 --- 26 March 1992
-
-
- Introduction:
-
- MSH is a ``shell'' which provides a convenient and configurable way to
- browse through directories and execute commands on files and sets of files
- by a ``point and shoot'' interface. In contrast to many popular shells,
- MSH is designed to be particularly useful to a ``power user;'' there is
- no limit to the number of shortcuts in everyday work she can implement
- with it: an arbitrary sequence of actions (which is written as an ``MSH
- script'') may be assigned to each keyboard key, and may depend on the
- environment (like the file currently pointed to, or its extension, etc...).
- Of course, MSH is also useful to the average user.
-
-
- Installation:
-
- Installation of MSH is simple. You only have to copy MSH.EXE to
- some directory in your PATH (the directories which are scanned by MS-DOS1
- to look for commands), and copy the script files (with extension .MSH)
- to the same directory. You should then modify the file CONFIG.MSH to
- indicate your display type, the drives you can access, whether you own
- The Berkeley Utilities or not, which directory to use for swap files, which
- editor and browser you want to use, etc... In the file there is a series of
- lines of the form:
-
- | in the line below, replace "c_blue.msh" by the name
- | of one of the available files describing attributes:
- | c_mda.msh for monochrome displays
- | c_pcga.msh for plasma cga displays
- | c_blue.msh, c_blue1.msh,
- | c_blue2.msh, c_white.msh various possibilities
- | for color displays
- |
- "c_blue.msh"loaddefs | load blue color
- | set attributes
-
- you should do at it says, e.g. replace c_blue by c_mda if you have
- a monochrome display. You can define your own colors for MSH; see the
- appendix on attributes.
- You now modify the following two lines to define your available drives:
-
- "CD" fixed_drives! | define your fixed drives
- "AB"floppy_drives! | define your floppy drives
-
- Similarly, there are these 3 lines in the file:
-
- true delta!
- true berk!
- true berk_cpmvrm!
- ----------------------------
- 1 MS-DOS is a trademark of Microsoft Corporation
-
- If you do not own DELTA, you should replace true by false on the
- first line and similarly for the second and third if you do not own
- The Berkeley Utilities. The third line refers to whether you want to use
- cp, mv and rm or DOS's copy and delete commands for these functions.
- Finally, there are lines reading:
-
- | next line defines the place for "magic" swap files
- (prog_dir)tmp_dir!
- | put swap files in same directory as MSH.EXE
-
- They specify the directory to use for swap files (see ``Technical highlight
- no. 2''; used when MSH cannot swap itself to extended memory). This
- should be a virtual disk or a fast hard disk if you have one. You can set
- tmp_dir to the empty string ("") to disable swapping to disk.
- Also, MSH does not provide a built-in editor: the idea is rather to
- let you use your own. If you do not have one, we include MWE.EXE, a
- multi-window editor which was developed as a demo of the power of TextLib,
- a keyboard and screen management C Library distributed by OPENetwork.
- Similarly, you may use your own browser instead of the built-in one (it
- will be slower). Of course, you must specify what it is to MSH; so, in
- CONFIG.MSH you must adapt the lines which say:
-
- "mwe "editor!
- "more "browser!
-
- to specify what is your editor and browser; for instance, if you use
- the mediocre but widespread Wordstar as an editor, and the excellent
- public-domain browser list by V.Buerg, you may change the above lines to:
-
- "ws "editor!
- "list "browser!
-
- Some people have such a good editor, or like their bad one so much, that
- they will use it as their browser. If your editor or browser does not
- work with the simple syntax ``edit filename'' or needs extra arguments or
- parameters after the filename, you can still manage, but you will have to
- make more complex modifications to CONFIG.MSH.
-
- Starting to use the default configuration
- You can then start MSH just by typing its name. The initial display
- you get should be: a menu bar at the top above two panels, each containing
- a display of the files in your current directory, and a list of available
- drives. All this is completely configurable. We describe here the
- behavior of MSH when you don't modify the CONFIG.MSH file.
- We support extended video modes and extended versions of ANSI.SYS. The
- initial number of lines of a panel will be half the number of total lines
- of your display(e.g. in 43-lines EGA mode, you will get 21 lines, and 25 in
- the 50-lines VGA mode instead of the usual 12 in a 25-lines mode; if you
- have a 132-columns mode you will get 3 panels, and 1 panel in a 40-columns
- mode). If you have a VGA or EGA card, you can ask MSH to first switch the
- screen to given number n of lines by giving the option -ln on the command
- line (the letter ell); for instance msh -l50 asks MSH to switch the screen
- to 50-line mode before starting. The only values of n currently understood
- are 25, 43 and 50.
-
- The first line of a panel contains a ``pattern'', i.e. a wildcard
- describing all files in the current directory at the left (e.g.
- c:\dos\*.*). This is highlighted if the panel is the active panel. At
- the bottom of a panel are titles for the various columns of the display
- (Name.ext, size, time) which are highlighted according to the current sort
- order of the panel.
- Most of your interaction with MSH is via what you type on the command
- line. MSH monitors all your keystrokes and decides what to do with them
- according to your own instructions given via the CONFIG.MSH file (the
- default configuration sets things so that you can also execute Mi-Shell
- script instructions directly from the command line with the key AltX).
- MSH when started always tries to locate the file CONFIG.MSH in the
- directory where MSH.EXE is located, unless you give it an explicit filename
- as argument. Two tutorials are on-line when you hit the F1 key to help you
- get started.
-
- The Mi-Shell script language:
-
- The configuration of MSH is done by its reading upon start the file
- CONFIG.MSH. This file is entirely in the MSH script language. Any text
- following a non-quoted | up to the end of a line is a comment and is
- ignored. The rest of the text represents instructions in the MSH script
- language, which is a small Forth-like stack language.
- As we proceed to describe the language, you can find some useful
- examples which might help in the section ``quick start at modifying
- CONFIG.MSH''.
- The only elements of the language are " which delimits character
- strings, brackets () which delimit blocks of code, and identifiers which
- are either words formed from the characters a--z A--Z 0--9 or dot (.)
- or underscore (_) or dollar ($), or symbols constituted by any other
- single character. Identifiers represent primitive or user-defined actions
- (their value is then a block of code), or variables holding character
- strings, excepted that identifiers starting with a digit are interpreted as
- character strings as if they were quoted. This is to allow you to write
- numbers without having to surround them with " (negative numbers like "-1"
- still have to be quoted). A number is just a particular string whose
- content is interpretable as a number, and all string operation apply to it;
- only the arithmetic operations try to interpret their string arguments as
- numbers. Below are some strings:
-
- "abc", "you can put '\"' in a string", 3, "3".
-
- The last 2 strings are the same. Below are some identifiers
-
- foo, bar, foo_bar, +, !, f31.
-
- The language is a stack language like FORTH. The stack contains
- either character strings or pieces (blocks) of code. In the subsequent
- descriptions [top] represents the stack top, [top+1] the next element,
- etc...; push something is the action of pushing something onto the stack.
- Actions typically read one or more values by popping them from the stack
- (reading [top] always unstacks it) and return possible results by pushing
- them on the stack. Some actions are predicate-like: the logical value
- false is represented by the empty string and true by any other string.
- The variables false and true are primitives and contain the values "" and
- "true" respectively. Variables which hold the value true or false will be
- called boolean in what follows.
- A character string is written "string" where internal `"' must be
- quoted by preceding them with \; a character string may span several lines
- and contain embedded carriage returns. Merely writing a character string
- pushes it onto the stack. Other identifiers cause their corresponding
- actions to be executed or their value to be pushed when encountered, except
- that a sequence of actions (or character string denotations) between `()'
- is pushed onto the stack as a piece of code instead.
- A character string or a piece of code may be assigned to an identifier
- by the action !; e.g., "hello" "H"! or ("")"false"!. In BASIC, this would
- be written as H = "hello" or as
- false = "". As a special syntactic convention, the form name! is
- equivalent to "name"!, so the above examples may be written "hello"H! and
- ("")false!.
-
- We should mention that some variables are ``system variables'': like
- primitives, they are defined by the system. Some of them can be set by the
- system as well as the user, and when the user sets them some sytem-defined
- action results. An example is cwd, the current working directory: setting
- its value will change the current directory.
- Also, as a special facility, a variable name beginning with a `$'
- represents a MS-DOS system variable (such as PATH or COMSPEC); the name
- must be in uppercase letters to be recognized as a system variable.
- Assigning to such variables will modify the MS-DOS environment. For
- instance:
-
- $PATH ";\mydir"& $PATH!
-
- can be used to modify the PATH. Beware! Only the local copy of the
- environment owned by MSH will be modified (which means that you will lose
- your modifications to the environment when leaving MSH; we might provide a
- way around that in future versions).
- Some identifiers represent the name of keys, and they are called
- whenever the corresponding key is pressed. The definable keys and their
- names are:
- Function keys F1--F10 ShiftF1--ShiftF10
- CtrlF1--CtrlF10 AltF1--AltF10
- Control keys CtrlA--CtrlZ
- Ctrl Break is always a ``break'' key, used to interrupt
- actions (like get out of loops)
- ``Alt'' keys AltA--AltZ Alt0--Alt9 AltMinus AltEqual
- Other keys Home End Left Right PgDn PgUp Down Up
- Delete Insert BackSpace
- CtrlHome CtrlEnd CtrlLeft CtrlRight
- CtrlPgDn CtrlPgUp
- ShiftDown ShiftUp ShiftLeft ShiftRight Esc Tab BackTab
- Enter CtrlEnter
- GreyPlus GreyMinus GreyStar CtrlPrint
- We now proceed to list the primitive actions, arranged by category.
-
- ``Language'' functions:
-
- drop Do nothing with [top] (and so just unstack it).
- dup Duplicate [top].
- pick [top] should be some number n. If these are the objects on
- the stack, starting from the bottom:
- O(n), O(n-1) ... O(2) O(1) n
- then after the command the stack will look like:
- O(n) O(n-1) ... O(2) O(1) O(n)
- so that 1 pick is equivalent to dup.
- swap Exchange [top] and [top+1].
- roll [top] should be some number n. If objects on top of stack
- are:
- O(n), O(n-1) ... O(2) O(1) n
- after the command they will be:
- O(n-1) ... O(2) O(1) O(n)
- so that 2 roll is equivalent to swap.
-
- stacksize push as a number the size of the stack.
- not Push false if [top] is not false, true otherwise.
- = If [top]=[top+1], push [top] else push false.
- & push the catenation of [top] and [top+1].
- match If [top] matches [top+1], push [top] else push false.
- cutfirst Cuts [top+1] at [top], that is look for first occurence of
- string [top] in [top+1], and replace [top] and [top+1] by the
- part of [top+1] after [top] and the part of [top+1] before
- [top] (the first may be empty if [top] does not occur in
- [top+1]).
- cutlast Like cutfirst, but looks for last occurence of [top] in
- [top+1].
-
- length push the length of the string [top].
- substring extract from [top+2] the substring which starts with the
- [top+1]th character and ends with the [top]th character, and
- push it on the stack.
- if If [top+1] is not false execute [top] else do nothing.
-
- ifnot If [top+1] is false execute [top] else do nothing.
- ifelse If [top+2] is false execute [top] else execute [top+1].
-
- while While execution of [top+1] does not yield false, execute
- [top].
- # Interpret the string [top] as a piece of code and execute it.
- @ Interpret [top] as an identifier name and replace it by its
- value. If the value is a piece of code, it is ``uncompiled''
- as a character string.
-
- isdefined Interpret [top] as an identifier name. Push true if this
- identifier has been assigned a value, false otherwise.
- ! Interpret [top] as an identifier name and assign [top+1] to
- it.
-
- + Push [top+1]+[top](interpreted as numbers).
- - Push [top+1]-[top](interpreted as numbers).
- * Push [top+1]*[top](interpreted as numbers).
-
- / Push [top+1]/[top](interpreted as numbers).
- < Push true if [top+1]<[top](interpreted as numbers), false
- otherwise.
- le Push true if [top+1]<=[top](interpreted as numbers), false
- otherwise.
-
- > Push "true" if [top+1]>[top](interpreted as numbers), false
- otherwise.
- ge Push "true" if [top+1]>=[top](interpreted as numbers), false
- otherwise.
-
- debug System variable. If "true", MSH is in ``debug'' mode:
- before any identifier is executed, a window pops up showing
- it and the current state of the stack.
-
- Panels, menus, windows and mouse support:
-
- MSH lets you manipulate several kinds of windows:
- - Panels, wich are ``directory browsers''. You get two of them in
- the default configuration. You can move them around, change their
- attributes, what they display, keys associated to them, etc...These
- are ``permanent'' windows (they don't disappear when you have finished
- interacting with them). Permanent windows have numbers (``handles'')
- associated with them on creation. You may use these numbers to
- reactivate them (put them in front, ready to receive your keystrokes)
- later (windows can also be activated by clicking on them with the
- mouse).
- - Menus, which are actually general ``hypertext'' windows where fields
- in the window have actions associated to them. They can be either
- permanent (they have then numbers associated to them) or temporary
- (they disappear when you make a choice).
- - Message, choice and dialog windows. The error windows that the system
- displays sometimes are of a similar kind. These are temporary windows.
- A message just displays some text. A dialog window displays some text
- and waits for your input. A choice window allows you to give a Yes/No
- answer. A menu could do the same job but this provides a simpler
- solution.
- At present, mouse support is limited to actions done on clicks and
- double clicks. More complex interaction (like drags) are not yet
- implemented, mostly because of the complexity of the necessary language
- support to describe them.
-
-
- Panels functions:
-
- panel.install Creates a new panel. Only one panel displaying
- nothing (with number 1) exists at the start. Other
- panels must be created with this command. One
- argument must be given on [top], the initial selection
- pattern of the newly created panel. The current
- panel is set to the created panel. Other attributes
- of a panel are set/modified with the following system
- variables. panel.install pushes one result, the
- number assigned to the panel.
- panel.pattern System variable. Represents the `pattern' of the
- current panel (the selection pattern displayed at the
- top of the panel). Setting this variable causes
- the panel to be refreshed by reading from disk the
- list of files matching the pattern (the father and
- subdirectories of the current directory are always
- displayed). As a special facility, this can be
- assigned a pathname composed of the pathname of a
- ``.zip'' file + a pattern. The panel will then
- display the list of all files inside that zip which
- correspond to the given pattern. We might add support
- for other kinds of archives (.lzh, .arj, .arc, .zoo)
- in the future.
- panel.type Returns the type of the current panel: "" for
- ordinary panels, ".zip" for a zip archive.
-
- panel.sort System variable. Represents the sort order of the
- current panel. It can be assigned the following
- values:
- "N" --- sort the panel by name;
- "S" --- sort the panel by size;
- "T" --- sort the panel by date;
- "E" --- sort the panel by extension. Sorting by extension
- keeps as a secondary key the previous sort, whatever
- it was. This is reflected in the highlighted titles
- at the bottom of the panel.It also means that in the
- case of an extension sort, the value of panel.sort is
- actually one of "EN", "ES" or "ET".
- panel.size Boolean system variable which controls whether the
- file size is displayed for each file of the current
- panel.
- panel.attrs Like panel.size, controls whether the read/write/system--
- /hidden attributes are displayed.
- panel.date Like panel.size, controls whether the last modified
- date is displayed.
- panel.time Like panel.size, controls whether the last modified
- time is displayed.
- panel.sec Like panel.size, controls whether the last modified
- time is displayed up to the second.
-
- panel.on Boolean system variable. Controls whether the current
- panel is on. When off, the panel won't be displayed;
- this is useful to have temporarily an unimpeded view
- of the screen behind the panel (in addition to the
- panels, the menu bar can be shut off by uninstalling
- it; this allows the use of MSH as a ``silent''
- background task).
- panel.rc System variable representing the number of rows and
- columns of the current panel. When read causes 2
- values to be pushed on the stack, first the number of
- lines and then the number of columns. Similarly it
- should be set by pushing 2 values on the stack (e.g.
- 12 40 panel.rc!).
-
- panel.startrc System variable. Represents the start row and start
- column of the current panel (the coordinates of the
- top left corner).
- panel.nbfiles push the total number of entries of the current panel.
-
- panel.att Function taking 4 arguments representing the video
- attributes used to display the pattern. They should
- be given in ANSI format and represent:
- Normal --- the normal attribute for files in a panel;
- Current --- the attribute of current name, the file
- pointed to by the cursor;
- Selected --- the attribute of selected files;
- Selected + Current --- the attribute of current name
- when it happens to be a selected file.
-
- current.name push the filename of the entry pointed by the cursor
- in the current panel (this entry will be called
- `current name' in the subsequent descriptions).
-
- current.isdir push false if current name is not a directory,
- otherwise push current name (usable as a predicate).
-
- current.size push the size (in bytes) of current name.
-
- current.time push the last modified time of current name. This
- time is encoded as an integer by the formula:
-
- 2x(seconds+
- 32x(minutes+
- 64x(hours+
- 32x(days+
- 32x(months+
- 16x(years-1980))))))
-
-
-
-
- current.selected System variable whose value is true or false. Setting
- it to true selects current name; this highlights
- it and marks it as ``selected'' which means that
- current.selected will return true until it is again
- deselected by setting current.selected to false.
-
- current.pos System variable which represents the position of the
- cursor in the current panel relative to the total
- number of files. Setting this variable moves the
- cursor. Values outside of the interval [0,panel.nb-
- files-1] are mapped to 0 or panel.nbfiles-1.
-
-
- Mouse actions:
-
- User-defined mouse actions on a panel are provided as follows: when a
- mouse event on the panel is detected:
- - It is activated if it was not active (and panel.on_activate (which
- should contain an action) is executed).
- - A two-part name is built and is executed (it should contain an action);
- - The first part of the name describes the event:
- LeftClick, LeftDbleClick, RightClick, RightDbleClick, MiddleClick,
- MiddleDbleClick.
- - The end part of the name describes the area of the panel where the
- event occured:
- N --- On the word ``name'' at the bottom of the panel.
- E --- On the word ``ext''.
- S --- On the word ``size''.
- T --- On the word ``time''.
- UA --- On the up arrow of the scroll bar.
- DA --- On the down arrow of the scroll bar.
- Entry --- On an entry. In that case before executing the name the
- number of the entry is pushed.
-
- Menu functions:
-
- The only function proper to menus is menu.install. The way a menu
- works is by executing actions (pieces of code) associated to fields in its
- window (``menu selections''). When a menu is active, the cursor keys move
- between menu selections. The currently highlighted selection is executed
- when pressing the key Enter or when clicking with the mouse on it. An
- Escape or clicking outside a selection field quits the menu without any
- selection being done. The arguments to menu.install describe completely
- the menu. They are in order:
- - A list of actions (pieces of code) to be executed for various menu
- selections.
- - A string, the text of the menu window. Fields which should operate as
- menu selections are delimited by % in that string (a % can be put in
- the menu by doubling it: %%). The fields are matched to actions in
- order. There should be exactly as many actions as there are fields.
- - An action which is executed when the menu is exited without any
- selection made (often the empty action () is suitable). This will
- occur when the user has activated a menu and then hits ESC.
- - The coordinates of where to put the upper left corner of the menu
- window (a "-1" means center the menu in that direction).
- - Three video attributes given as ANSI strings, to use for displaying the
- menu:
- Normal --- the attribute for normal text in the menu window;
- Selection --- the attribute of a menu selection;
- Highlighted --- the attribute of the highlighted menu selection;
- - A boolean value wich determines if the menu window should have a
- border.
- - A boolean value wich determines if the menu should be permanent.
- For a permanent menu, menu.install returns a value, the number assigned
- to the menu.
-
-
- Permanent Windows Control:
-
- Two functions control permanent windows:
- window.activate Takes as argument the number of the window to activate
- (panel or menu). An active menu is recognized by
- having a higlighted selection. An active panel has
- a highlighted title (and if any files are displayed,
- current name is highlighted). When activating a
- panel, the action panel.onactivate is executed. This
- can be set by the user; in the default configuration
- what it does is attach to the directory of the panel.
- An active window is put on top of the others.
-
- window.uninstall Takes as argument the number of the window to delete;
- deletes that window (menu or panel).
-
- It is sometimes convenient to give consecutive numbers to a series of
- panels or menus (the functions next_panel and previous_panel of the default
- configuration do that). The number given to a newly created window is
- the first available number, so this can be arranged by just creating the
- windows consecutively when there has been no deletions.
-
- Other Windows:
-
- message Display [top] as a message with title [top+1]. This message
- is left displayed until any key is typed. If the text of the
- message does not fit on the screen, it is shown screenful by
- screenful until the end. This can provide a primitive kind of
- browser.
-
- flash Display [top] as a message with title [top+1]. This message
- is left displayed for the number of milliseconds specified by
- [top+2].
-
- ok Display [top] as a message and ask confirmation with a Yes No
- choice. Replaces [top] by false in case of non confirmation
- (so may be used as a predicate).
-
- input Display [top+1] as a message and ask for input in a field of
- length [top]. The input is pushed on the stack.
-
- getkey Display [top] as a message with title [top+1]. Return as a
- character string the name of the first key typed.
-
- alertatt System variable which can only be set. Its value represents
- (in ANSI format) the color attribute to be used for the above
- windows. (``alert'' is the name for the temporary ``pop-up''
- windows of MSH: the ones mentioned above, the warnings and the
- debug window).
-
-
-
- Command line:
-
- cmd.del Delete the current character in the command line.
-
- cmd.end Go to the end of the command line.
-
- cmd.home Go to the beginning of the command line.
-
- cmd.left Go one character left in the command line.
-
- cmd.right Go one character right in the command line.
-
- cmd.wordleft Go one word left in the command line.
- cmd.wordright Go one word right in the command line.
-
- cmd.clear Reset to zero the command line.
-
- cmd System variable representing the command line. Reading
- it pushes the command line contents. Setting it writes
- [top] to the command line; but note that the text is
- added to the command line where the cursor is in it.
- Call cmd.clear first to replace the command line contents
- by new contents.
-
- cmd.imode Boolean system variable representing if the command line
- is in insert mode.
-
- Other:
-
- read Read the file whose name is [top] and push as a string its
- contents.
- write Writes (creates or appends) to the file whose name is
- [top+1] the string [top].
- unlink removes file whose name is [top].
- capturescreenGrabs the contents of the screen as a string and push it
- on the stack.
- progpathname push the pathname of msh.exe.
- cwd System variable holding the name of the current directory.
- Setting it attaches to the directory whose name is [top].
- linescols System variable holding the total number of lines and
- columns on the screen. It may be used in conjunction
- with panel.rc and panel.startrc to program a setup for the
- screen.
-
- execute Send [top] to command.com to be executed.
- magic System variable. If not false, should specify a directory
- where MSH will swap itself out of memory before sending
- any command to MS-DOS for execution if it cannot swap
- itself to extended memory. As a special convention, if it
- starts with a `*', it means that swapping to XMS is not
- desired. See ``Technical highlight no. 2''.
- page Call the built-in browser. It takes 9 arguments: the
- name of the file to browse followed by the coordinates
- of the window for the browser (start row, start column,
- number of rows, number of colums) and by the list of video
- attributes to use in the browser:
- Browser window --- the attribute of the window of the
- browser.
- Browser highlight --- the attribute of the status line and
- of highlighted text in the browser.
- Empty --- the attribute used when showing empty space in
- the browser.
- Tab --- the attribute used when showing tabs in the
- browser.
-
- beep As its name says.
- time push the current time (in the same format as
- current.time).
-
- timer MSH has a ``timer'' which allows you to do some actions
- at regular times (which may be used to show a clock) or
- after some delay (which may be used to set an alarm).
- [top] should contain the action to do (as a piece of
- code) and [top+1] a number specifying how many ticks (1=17
- sec.) from now this action should be done. To do an
- action repeatedly, you can write an action which contains
- a call to set the timer with itself, e.g. after (f 1000
- (g)timer)g! a call to g will execute f repeatedly every
- 1000 ticks.
-
- reinitmouse With some versions of the Microsoft mouse driver and
- some mouse programs, the mouse driver in MSH may become
- inactivated when returning from execute. This command
- reinitializes it (it is not done systematically since it
- takes 1 to 2 seconds).
- mouse.click System variable. Holds the interval between the 2 clicks
- of a mouse double click. By default nn is 3 which means
- 3 ticks (ie 3/17 sec.). You may want this to be a bit
- slower if you are not a Mac user ...
- quit Quit MSH.
-
-
- A quick start at modifying .MSH files:
- The first thing you might want to do is add to EXT.MSH instructions
- to deal with other types of files, recognized by their extension. For
- instance, I use Knuth's TeX text-processing language, which produces
- device-independent output files ready to be printed or viewed on the
- screen; what I want to do when I point to such a file, say foo.dvi,
- and order MSH to act by pressing the Enter key, is to see what's
- in it, i.e. call my previewer (called view) with a command such as
- view foo.dvi. What I did in order to get this is add a line to the
- series of lines in EXT.MSH which end by extension_something (a typical one:
- (current.name pager)extension_cfg!) saying:
-
- ("view "current.name & execute)extension_dvi!
-
- how does this work? When enter is pressed, by a mechanism described
- below, MSH sees that the command line is empty and decides to execute the
- identifier extension_xxx where xxx is the extension of current name. It
- is the line above which gives a definition to the identifier extension_dvi.
- The final ! is the assignment operator which assigns to extension_dvi
- what's on the stack. What is there is the code in brackets at the
- beginning of the line, which has been pushed by the simple virtue of
- appearing there. What does this code do? First, it pushes the
- string "view " on the stack, then current name, then catenates [top] and
- [top+1](operator &); now [top] contains "view foo.dvi"; finally execute
- sends that string to MS-DOS to be executed; you can watch the whole thing
- in action by doing the following steps:
- - Position cursor on foo.dvi and make sure the command line is empty.
- - Press AltD. If your configuration is the default one, this make MSH
- enter debug mode.
- - Press Enter. You will then see the debugger window, which includes a
- view of the stack. Press s to step through the code of extension_dvi.
- - Press g (go) when in debug window to leave debug mode.
-
- Let us now have a more elaborate text explanation by looking at the
- code which is executed when pressing Enter. The code is the following
- lines in KEYBIND.MSH:
- (cmd
- (execsave)
- (act_on_cur)
- ifelse
- )Enter!
-
- We first put the contents of the command line on the stack (cmd). To
- understand what happens next you have to notice that the rest consists
- of 2 blocks of code followed by ifelse. That's a perfectly ordinary
- if construct, excepted that control structures don't always look nice in
- reverse polish notation. The way ifelse works is: it expects 2 blocks of
- code on the stack, and, above that, a value which is false (empty string)
- or not (non-empty string), and execute one or the other piece of code based
- on that value. The net effect here is to execute the first piece of code
- if the command line is non-empty and the second otherwise.
- The first piece is a definition:
-
- (cmd dup cmdlist nl&swap&cmdlist!execute
- cmd.clear refresh)execsave!
-
- it recalls again the command line, duplicates it, uses one copy to store in
- the circular list of commands cmdlist (where previously typed commands are
- kept, separated by newlines (the content of the variable nl), for reuse if
- recalled by the user), and executes the other copy; then clears the command
- line and calls refresh; this last is itself a definition that you can find
- in STDDEFS.MSH:
-
- (cwd panel.pattern filepart makename panel.pattern!)
- refresh!
-
- The purpose is to refresh the display in the current panel, which might
- be necessary since the executed command may have destroyed files and/or
- changed directories. To do that, we first get the current directory's name
- on the stack, then catenate to it the filename part of the wildcard of the
- current panel (usually "*.*", but it may be set to something else), then
- put that as the pattern to select files in the current panel. filepart and
- makename are also definitions that we don't show here.
-
- Let's look now at what we do if the command line is empty:
-
- (current.isdir
- (current.name cwd! refresh)
- ("extension_" current.name extension)
- ifelse
- )act_on_cur!
-
- We have again an if which tests if current name is a directory or
- not. current.isdir is a predicate, which as all predicates, by convention
- returns one of the strings "" (false) or "true". If current name is a
- directory, we attach to it (current.name cwd!) and refresh. Otherwise, we
- construct an identifier extension_xxx where xxx is the extension of current
- name and execute that (#). extension is defined as follows:
-
- ("."cutlast swap drop)extension!
-
- we cut the name into its part before the "." and after it, and drop the
- part before it.
- The other thing I want to do with dvi files is turn them into HP
- LaserJet output, which I do with dvihp.exe, and that second type of action
- was associated with the CtrlEnter key.
-
- Technical highlight number one: long command lines and The Berkeley Utili-
- ties:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- MSH supports (almost) arbitrarily long command lines for programs which
- recognize its conventions (like The Berkeley Utilities). For instance, if
- you use the BERK.MSH configuration with cp, mv, rm enabled, and select a
- lot of files and press F6 (move), you will be asked to confirm a very long
- command starting with mv, and if you agree mv will correctly move the whole
- list to the next panel. This is quite advantageous compared to looping
- on mv of each file, since mv is loaded only once, so the job is done
- much faster. You may wonder how this is possible, since MS-DOS limits any
- command line to 127 characters. We do this by a simple trick, which is
- understood by all The Berkeley Utilities, and which you may make your own
- programs understand! When the command line is greater than 127 characters,
- we send only the first 127 to dos; but before that we put the rest in a
- buffer, preceded by its length as a 2-byte integer, and we add to the
- MS-DOS environment a variable CMD@=xx, where xx is the adress (as a long
- decimal integer) of the buffer. The called program has just to check if
- that variable exists, and if it is the case catenate to its command line
- the rest of the command line gotten from the address that variable holds.
- Here is some sample code which does just that; this should help you write
-
- your own.
-
- #include <stddef.h>
- #include <stdlib.h>
- #include <string.h>
- #include <malloc.h>
- #include <dos.h>
- /* this program prints the command line under MSH,
- adding the extra part at the end of the normal command.
- This version gets the psp by the TURBO C built-in
- variable _psp. You have to get it another way
- if you use another compiler. */
- int main()
- { unsigned cmdlen=*(char far *)((((long)_psp)<<16)+0x80),
- extralen=0;
- char *com;
- int far *extra;
- char *s=getenv("CMD@");
- if(NULL!=s && (extra=(int far *)atol(s)))
- extralen=*extra;
- com=malloc(cmdlen+extralen+1);
- movedata(_psp,0x81,
- FP_SEG((char far *)com),
- FP_OFF((char far *)com),cmdlen);
- if(extralen)
- { extra++;
- movedata(FP_SEG(extra),FP_OFF(extra),
- FP_SEG((char far *)(com+cmdlen)),
- FP_OFF((char far *)(com+cmdlen)),
- extralen);
- }
- com[cmdlen+extralen]=0;
- printf("command=<%s>\n",com);
- return 0;
- }
-
-
- Technical highlight number two: large memory for your commands:
- MSH, like a few advanced products, can let your commands use almost
- all available memory in the system when executing. In order to do that,
- MSH swaps itself out of memory, writing most of its image to disk or
- to extended memory (if available) and leaving only a small (8K) image in
- memory. If you have no (or not enough) extended memory and cannot swap to
- a virtual disk (in low or expanded memory) this swapping takes some time so
- you may want to disable it. It is under control of the variable magic: if
- magic is false (the empty string), its default value, no swapping to disk
- is done. Otherwise magic must contain the name of the directory to be
- used for swapping (you may specify ``.'' for the current directory, but
- we don't recommend it since you will then have problems on a diskette; you
- should specify some directory on your hard disk or a virtual disk). If you
- want to run a program which requires the use of all your extended memory
- (this happens to be the case for Borland's BC++3.0 on my machine which has
- only 2megs), you may want to disable swapping to XMS: this is done by the
- special convention of starting the variable magic with a `*'.
-
- Command line options:
-
- In addition to the -l option explained above, there is another possible
- option on the command line:
- -m Disables mouse. If for some reason, you have a mouse but want MSH not
- to use it, use this option.
-
-
- How to add your own primitives coded in C to msh:
-
- Read the file TOOLKIT.DOC which is in the toolkit.
-