home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-01-31 | 57.1 KB | 1,385 lines | [TEXT/ALFA] |
-
- Writing New Modes, Menus and Packages
-
-
- created: 97-03-03 11.44.50
- last update: 31/1/1999 {2:03:41 pm}
-
- Author: Vince Darley, some pieces by Tom Fetherston and Pete Keleher
- E-mail: <darley@fas.harvard.edu>
- mail: Division of Engineering and Applied Sciences, Harvard University
- Oxford Street, Cambridge MA 02138, USA
- www: <http://www.fas.harvard.edu/~darley/>
-
-
- Introduction
-
- If you're writing or modifying any mode, menu or extension (collectively
- known as packages) related Tcl code for use with Alpha, you should read this
- document. It also tells you how to make use of some of the features of
- Vince's Additions in your mode. These instructions pertain to all versions
- of Alpha greater than or equal to 7.1.
-
- There are two basic types of package which Alpha uses: modes, and
- features. A mode helps with editing a file for a particular purpose:
- web pages use 'HTML' mode, C++ code uses 'C++' mode, LaTeX documents
- use 'TeX' mode,… There are about 20 such modes currently available.
- Features are of three types: menus, extensions and ordinary features.
- A feature adds functionality to Alpha either globally (a 'global
- feature') or just for particular modes (a 'mode feature'). Menus are
- one type of feature used to extend Alpha. Most modes add a menu which
- is automatically attached to that mode. Other menus are often useful
- globally. It's up to the user to decide when each feature/menu is
- active. Mode-authors can of course set the defaults for their mode.
- Examples of globally useful menus are the filesets menu, the eudora
- menu and the electric menu. When you create a new menu for Alpha, you
- have the option of suggesting that it is attached to particular modes,
- or that it is suggested as global, or that it is global only. General
- features are organised in the same way, but don't create menus.
- Finally, an extension is a simple form of feature which is either
- globally active or off (it either doesn't make sense or isn't
- particuarly useful to turn extensions on and off in a mode-dependent
- way). Examples of extensions are the printer choices sub-menu, or the
- bib-engine (used to interact with BibTeX). Note: a 'menu' is
- something which sits in Alpha's menubar, at the top level. A feature
- or extension can create submenus which sit inside top level menus, but
- these are not 'menus' in the same sense. The main distinction is that
- menus must be registered with 'alpha::menu' or 'addMenu', whereas
- submenus need no special registration.
-
- For the impatient reader: here's how to write a very simple feature
- which contains one new procedure and one new key-binding (to that
- procedure). Just create a file which looks like this:
-
- # (auto-install) --- this line will cause Alpha to try to install
- # this pkg when this file is opened outside of Alpha's folder hierarchy
-
- alpha::feature myPackage 0.1 {C C++} {
- # no global initialisation required
- } {
- # activation script
- # bind the 'x' key to my procedure (not a good idea ;-)
- Bind 'x' myProcedure
- } {
- # deactivation script
- unBind 'x' myProcedure
- } uninstall {this-file} maintainer {
- "My Name" my@email http://webpage..
- } help {
- Binds the blah-key to 'myProcedure' which carries out...
-
- This package is only designed to do something useful in
- C and C++ modes.
- }
-
- proc myProcedure {} {
- # do some cool stuff
- }
-
- Save this file on your desktop (say), and open it. You'll see Alpha
- automatically opens an installation dialog, puts this file in the
- right place if you agreed to the installation, and rebuilds its
- package and tcl indices so that this package can be used next time
- you restart Alpha (actually with a simple package like this, you can
- use it straight-away). By default this package declares it is useful
- for C and C++ modes, although the user could choose to activate the
- package globally or individually for any set of modes.
-
- Important note: if you're writing a mode, menu or package, you should
- know about the 'package index'. Alpha keeps a cache of all startup
- information, so that if you edit your 'alpha::mode ...' statement, and
- quit and restart Alpha, the changes will not take effect. You must
- tell Alpha to rebuild the package indices before quitting.
-
- Alpha provides lots of cool facilities to help you write useful
- packages, whether they are modes, menus or extensions. This
- document describes those facilities.
-
- Guidelines for future Tcl 8 compatibility
-
- This section is only useful if you're concerned about making
- future transitions easier, and has no relevance for writing
- code for Alpha 7.1 at present. However, since Alpha will be upgraded
- to Tcl 8 for the next major release (no date yet!), knowing some of
- this may save you trouble later. It will also help you to understand
- how to write code which works efficiently with Tcl 8, making maximum use of
- the potential speed improvements there.
-
- When Alpha upgrades to Tcl 8, some changes to your code may be necessary,
- unless you pay attention to a few simple details. First, any proc which
- contains '::' is a procedure defined inside a namespace. Tcl 8 requires
- you to declare namespaces in advance. Hence unless Tcl 8 knows about
- namespace 'A', say, defining a procedure 'proc A::blah ...' is an error.
- You should therefore include the line 'namespace eval A {}' at the
- beginning of the file defining all the 'A::' procedures. (Alpha 7.1 will
- ignore these namespace commands so your code works either way)
-
- The second guideline concerns the way namespaces actually work.
- Assume you have defined two procedures 'A::open' and 'A::list'.
- Let's say:
-
- proc A::list {} { open [file join $HOME Help Changes] w ; ...}
- proc A::open {} { return [list a b c] }
-
- Then both of these procedures will fail (and may crash Alpha) if
- running Tcl 8. This is because inside the procedures we're in the 'A'
- namespace and this means commands are checked first to see if they
- exist inisde that namespace. Therefore command 'open' in A::list is
- not the global Tcl command 'open', rather it is the procedure A::open
- (obviously not what was intended above). Similarly 'list' in A::open
- is in fact the procedure A::list. There are two ways to resolve this:
- (i) write 'list' as '::list' inside the proc (and 'open' as '::open'),
- or (ii) ensure the tail end of your procedures do not clash with any
- global Tcl commands. The first option will not work in Tcl earlier
- than 8.0, which means you'd have to supply two different definitions
- of the procedure and use 'if {[info tclversion] < 8.0} ...' to create
- the correct one. The second option will work without modification,
- and is therefore somewhat preferable.
-
- By following these two guidelines, your code should continue to work
- without any changes _at all_, when Alpha upgrades (except that your
- code will run 2-10 times faster!).
-
- If you're really concerned about maximum efficiency in Tcl 8, make
- sure you always use '{}' with both 'if' and 'expr'. This speeds things
- up with Tcl 8 due to some technical aspects of the way the Tcl compiler
- works (see http://www.scriptics.com for details). For example don't
- write 'if [expr 1+2 == 3] ...' but rather 'if {[expr {1+2 == 3}]}'.
-
- A very important pointer for speed in Tcl 8 is that lists are very fast.
- This means using 'lappend', 'lindex' etc is very quick. There is one
- small point you should obey: never use 'if {$myList == ""} {...}' to see
- if a list is empty. Instead use 'if {![llength $myList]} {...}'. Until
- Tcl implements some good optimisation in the internal compiler (which it
- may never do), the former expression will slow your code down hugely when
- the list isn't empty.
-
- The behaviour of [file tail] has changed slightly between 7.5 and
- 8.0; with 7.5 [file tail a:b:] was "", but 8.0 returns "b". Try to write
- code which doesn't depend on this distinction.
-
- Declaring your package to Alpha
-
- A package must contain, preferably as its first non-comment line (this
- is important), a statement like this:
-
- alpha::mode NAME VERSION ...
-
- alpha::menu NAME VERSION ...
-
- alpha::feature NAME VERSION ...
-
- alpha::extension NAME VERSION ...
-
- (The other parameters to these commands are explained below). The name will
- identify your package, and for modes must be at most 4 characters long.
- It should not contain any spaces (this limitation may be lifted in a future
- version of Alpha). The version is a string of the form 1.0.1, or 2.3b1 or
- 1.4.530.1.3a5. Modes, menus and extensions take different arguments for the
- remainder of the 'alpha::' declaration line, but each ends in a script which
- Alpha scans and stores for you (Alpha scans all installed files for
- package declaration lines and caches this information so that at startup,
- no files need be read). For modes and menus, this script is executed
- automatically at startup. For features, there are initialisation and
- activation/deactivation scripts. An extension is a simpler form of a
- feature which only has a single initialisation script (used the first
- time it is activated). Package initialization occurs in the order: modes,
- menus and finally extensions.
-
- IMPORTANT: The declaration command must not be wrapped in any 'catch'
- statements. This is necessary to allow Alpha to rebuild package
- indices rapidly (note that it is no longer required to be at the
- beginning of the line). If you wish to write backwards compatible code,
- try something like:
-
- if {[info commands alpha::extension] != ""} {
- alpha::extension ...
- } else {
- # initialize in some old way for Alpha 6.x
- }
-
- Your package will not function properly if you don't obey the above
- guidelines. Alpha itself is considered a package, with a version
- number, so that your code can request a particular version of Alpha.
- Alpha's version number also has a patchlevel which will be updated
- with each Tcl-only patch release. Hence you can write:
-
- alpha::package require Alpha 7.1b1
-
- For the first Alpha 7.1 beta release, and
-
- alpha::package require Alpha 7.1p1
-
- If your package actually requires some fixes from the first patch
- release after the final 7.1 release. You can similarly require
- particular versions of other packages. You should 'require' as old a
- version as possible, so that you don't force users to upgrade
- unnecessarily.
-
- Note that with the advent of the new alpha:: commands, it is no longer
- necessary to place modes, menus and packages in their separate directories:
- they can go anywhere on the auto-path. However it is more convenient to
- store them separately most of the time.
-
- The developer utilities package
-
- You will want to download this package, since it helps with a number
- of developer-related tasks:
-
- • distribution archival, compression, and uploading
- • colouring and hyperlinking Help files (like this one)
-
- For anyone helping with Alpha's core distribution it also allows:
-
- • colouring Alpha's manual, commands, readme and changes files
-
- ===============================================================================
-
- Writing New Modes
-
- To add a mode to Alpha, a file (usually ending with 'Mode.tcl') must be
- created and placed in the ":Tcl:Modes" directory.
-
- The file should begin with a construct of the following form:
-
- alpha::mode Perl 1.3 dummyPerl {*.pl *.ph *.pm} {
- perlMenu electricBraces electricReturn
- } {
- addMenu perlMenu •132 Perl
- }
-
- This command is very, very important.
-
- alpha::mode <mode> <version> <dummyProc> <suffixes> <mode-features> <script>
-
- defines a new mode. When trying to switch to the Perl mode, Alpha will
- attempt to execute the function 'dummyPerl'. The suffixes allow Alpha to
- automatically determine the correct mode of a newly opened file. In this
- case the script contains the single command:
-
- addMenu <mname> ?<name>? ?<pertains to modes>?
-
- which defines a new menu, with 'name' the visible name of the menu (names
- which start with '•' indicate Alpha should use an icon resource with the
- given number. Icon number 132 is the Perl camel icon). This menu can be
- used in any mode, although by default, it is only attached to Perl mode.
- 'mname' is actually a variable which contains (will contain) the real menu
- name (in this case '•132'). The third argument usually contains a
- single mode with which this menu is distributed. Its use is mainly so that
- Alpha knows that this menu belongs primarily to this mode, so that if the user
- asks for information on the menu, Alpha knows to respond with
- information on the mode instead (curiously Alpha wouldn't otherwise
- know).
-
- Perhaps the MOST important part of the above code is the existence of the
- 'dummyProc'. When this proc is called, the result must be that all of
- the mode's preferences are declared. In other words, the dummyProc
- should normally be in the same file as the mode's 'newPref' declarations.
- This is important because almost directly after that call, Alpha expects
- all of the mode's preferences to be stored in the ${mode}modeVars array,
- which will only be true if all of the newPref commands have been evaluated.
-
- Here is an example from Diff mode:
-
- alpha::mode Diff 1.0 diffMenu {*.diff} {diffMenu} {
- addMenu diffMenu •288
- menu::insert Utils submenu 0 compare
- menu::insert compare items end "windows" "files…" "directories…"
- } uninstall {
- removeFile "$pkg_file"
- removeFile [file join ${HOME} Tools "GNU Diff"]
- } maintainer { "Vince Darley" darley@fas.harvard.edu http://... }
-
- The 'uninstall' and 'maintainer' sections are optional, and explained later.
- Here is a more complex example for Python mode:
-
- # ◊◊◊◊ minalmalist mode set-up ◊◊◊◊ #
- alpha::mode Pyth 0.2 dummyPython {*.py *.pyc *.pyi} PythonMenu {
- addMenu PythonMenu
- #To set the mode from a unix-like "#!python" first line
- set unixMode(python) {Pyth}
- }
- # dummy proc to load this mode.
- proc dummyPython {} {}
- # dummy proc to load the code to make the PythonMenu
- proc PythonMenu {} {}
- # rest of mode's code follows...
-
- #Lets the automatic comment insertion/continuation
- # routines function with this mode.
- set Pyth::commentCharacters(General) "\#"
- set Pyth::commentCharacters(Paragraph) [list "## " " ##" " # "]
- set Pyth::commentCharacters(Box) [list "#" 1 "#" 1 "#" 3]
-
- The package declaration should contain all code which is necessary to
- recognise a given file as belonging to that mode (hence the use
- of 'unixMode' for python), which will then make Alpha call the
- dummyProc which will auto-load the entire file. Other information,
- such as the 'commentCharacters' entries above should not go in the
- package declaration.
-
- Notice that there are two types of 'dummy' proc: each menu Alpha uses
- should have a proc of the same name associated with it. This proc is
- called by Alpha _each_ time Alpha tries to insert the menu into the
- menubar. The proc can be empty (as above), or could actually do
- something if desired. The second kind of dummy proc is the 'mode'
- dummy proc, given in the 'alpha::mode' command. Here it is called
- 'dummyPython'. Alpha calls this proc each time it switches to Pyth
- mode. Again the proc can do something if desired, but will usually
- be empty. If both procs are empty, as above, one can of course
- just use one proc (called PythonMenu in this case), and replace the
- alpha::mode line by:
-
- alpha::mode Pyth 0.2 PythonMenu {*.py *.pyc *.pyi} PythonMenu
-
- The only advantage of this approach is that it saves a small amount
- of memory (you can delete the 'dummyPython' proc from the file). Note that
- this only holds true for modes whose Tcl code is in one file.
-
- Multi-file modes
-
- Modes that consist of more than a single file should no longer use a source
- statement that assumes that the other files for the mode will be in
- $HOME:Tcl:Modes. The best solution is to use Alpha's standard auto-loading
- capability which will source a file when it needs a procedure which is
- contained in that file. If you must use 'source' manually, you can use
- 'file dirname [procs::find someProcInThisFile]' to get the current
- directory. Your other files should also be there.
-
- A convenient way of implementing your multi-file loading is to create
- procs with the same name as the file at the beginning of each file.
- Then to load the file you just do 'catch "filename"'. For example
- if there is a proc defined 'proc perl5.tcl {} {}' at the start of
- the file "perl5.tcl", then I can auto-load that file by having the
- following code in "perlMode.tcl" (note: actual code differs slightly):
-
- if {[catch perl5.tcl]} {
- alertnote "Problem loading 'perl5.tcl'"
- }
-
- Remember, you don't necessarily need to source all your mode/pkg's files in
- one go. Tcl is designed to source files for you when they are needed (when
- a procedure contained in one of them is called). Hence you only need to
- source files which are required immediately (to set up some data, variables,
- menus etc.) and not everything else. It is usually best to have a single
- file which contains all the initialization code, and let any other files be
- auto-loaded as necessary.
-
-
- Use of the term "electric"
-
- Through out the documentation and in actual proc names, you will see the use
- of the word "electric", so a note on its usage might be helpful.
- "Electric" is used in the sense of "automatic, power assisted behaviour", it is
- intended to save time, keystrokes, and brainpower. Such behaviour is usually
- invoked by certain keystrokes (determined by various preference settings).
-
-
- Mode procs
-
- The following procs are either required or desired for a mode to be
- fully functional within Alpha.
-
- Marking Proc's: (provide indexes into code via '{}' and "M' pop-ups)
-
- <mode>::parseFuncs -- (not every mode provides this one)
- <mode>::MarkFile
-
- Info providers: (drive & support access to source or file related info)
-
- <mode>::DblClick -- usually provides term specific help
-
- <mode>::optionTitlebar -- provides menu to access related files
- <mode>::optionTitlebarSelect -- action for menu selection above
-
- electric behaviour: (these assist formatting & and save on keystrokes)
-
- <mode>::carriageReturn -- this, supported by the following two, help
- -- to keep indentation standard (indirectly
- -- called by a carriage return.
- <mode>::indentLine -- indents a line, usually by calling next proc,
- -- and then inserting spaces/tabs as appropriate.
- <mode>::correctIndentation -- allows smart-paste package to function
-
- -- These provide electric behaviour for '{', '}', and ';' respectively.
- -- Their use is primarily for languages that use '{' and '}' for code
- -- blocks, and ';' as the line terminator. They are indirectly called
- -- by the key they correspond to, and then, only if a corresponding mode
- -- preference flag has been defined and set to one.
- -- (see 'Electric braces and semicolons below)
-
- <mode>::electricLeft
- <mode>::electricRight
- <mode>::electricSemi
-
- Have a look at a standard mode like Tcl or C++ to see what these
- should do. <mode>::correctIndentation must not fail (the correct
- indentation always exists for a line, so Alpha expects the proc to
- return a number and not signal an error).
-
- Hooks
-
- Do not do all that 'rename saveHook mySaveHook'... stuff. Use
- 'hook::register' instead. See the file "hook.tcl" for details, but all
- you need to do is add lines like these:
-
- hook::register saveHook modified "C" "C++"
- hook::register saveHook modified "Pasc"
- hook::register saveHook htmlLastModified HTML
- hook::register savePostHook codeWarrior_modified "C++" "C"
- hook::register savePostHook ftpPostHook
- hook::register saveasHook htmlLastModified HTML
-
- Here's the general form
-
- hook::register 'hook-name' 'your proc' 'mode' ?... 'mode'?
-
- If you don't include a 'mode', then your proc will be called no
- matter what the current mode is. Avoid this unless absolutely
- necessary. Here are the current hooks:
-
- activateHook changeMode closeHook deactivateHook modifyModeFlags
- quitHook resumeHook saveasHook saveHook savePostHook suspendHook
- openHook
-
- There's also a 'mode::init' hook which will be called the first
- time a mode is started up. Note that at that time, the mode exists, but its
- variables have not yet been made global, and its menus have not
- yet been inserted into the menu bar.
-
- There's also a 'startupHook' which is called when Alpha starts
- up, but after all other initialization has taken place, a 'launch'
- hook which is called when Alpha launches another application
- (register with hook::register launch yourproc $sig).
-
- Smart mode lines
-
- If your mode will want to be able to use the first line of a file to
- determine what mode a file should be opened up in, you need to tell
- alpha what word in the first line should trigger that mode:
-
- set unixMode(python) {Pyth}
-
- A good place to do this is in the body of the your mode's package
- declaration "alpha::mode … {…" statement (see example for Python above).
- Note that the presence of the word itself is not sufficient; it must be of
- the form '#!\usr\..\python' as is common on Unix (where it tells the shell
- with what application to run the script)
-
- Note that there is already built in support for opening a file in a given
- mode if the first line contains:
-
- -*-<mode_label>-*-
-
- e.g.:
-
- -*-Tcl-*-
-
- Also, if the first line contains:
-
- (nowrap)
-
- then you will not be asked if you want to see such a file in paragraph
- format simplly because the lines have gotten so long alpha thinks they
- might be from an application that maintains a paragraph as one long line
- and does its own wrapping internally.
-
-
- Mode creator types
-
- If your mode wants to declare itself as a default for files with a
- particular creator, (so any file with that creator opens up in that mode)
- you need to tell Alpha with an entry whoses format is like this:
-
- set modeCreator(<4_char_creator_code>) <mode_label>
-
- e.g.:
-
- set modeCreator(McPL) Perl
-
- A good place to do this is in the body of the your mode's package
- declaration "alpha::mode … {…" statement.
-
- Comment characters
-
- If your mode will want to use the standard Alpha comment/uncomment
- block procedures, file headers, ... you need to tell Alpha what
- characters are used for comments. Rather than redefining
- the procedure 'commentCharacters', you should just define the following
- variables:
-
- set ${mode}::commentCharacters(General) [list "*" "//"]
- set ${mode}::commentCharacters(Paragraph) [list "/* " " */" " * "]
- set ${mode}::commentCharacters(Box) [list "/*" 2 "*/" 2 "*" 3]
-
- where the values shown are for C++ mode. If you do this then there is
- no need to mess with the commentCharacters procedure. (In general it
- is best if your mode does not need to redefine procedures in Alpha's core).
-
- Paragraph definitions
-
- Paragraph filling. You can set the variables:
-
- set ${mode}::startPara {^(.*\{)?[ \t]*$}
- set ${mode}::endPara {^(.*\})?[ \t]*$}
-
- to customize your mode's paragraph definition. The above example's regular
- expressions (third 'word') are for Tcl code.
-
- Alpha uses these to determine what it should act on when it is requested to
- re-wrap, make a selection or navigate with respect to paragraphs.
-
- Note that currently the wrapping routines take no notice of code formatting
- rules and are limited utility outside of the 'Text' mode. The only proc's
- that use these are found in "textFill.tcl".
-
- Electric braces and semicolon
-
- If your mode uses electric '{', '}', ';' (i.e. characters that end the
- current line and indent the next one automatically) you need to define
- a few procedures: '${mode}::electricLeft', '${mode}::electricRight'
- and '${mode}::electricSemi' which will be called automatically (you do
- NOT need to bind anything to the keys). If you do not define these
- procedures, Alpha will use a default electric procedure which works
- pretty well for C, Perl and Java code.
-
- Of course the user needs to turn on the electric functionality for
- your mode. (Activate by default by including 'electricBraces' in
- your list of mode features in the alpha::mode command).
-
- Do not bind to '{', '}' or ';' if you want these to be electric. Alpha
- will automatically call your mode's procedures if they are named
- correctly.
-
- Option-click-titlebar menu
-
- If your mode has a specific 'opt-titlebar-click' menu, you need to
- define the procedures:
-
- proc C++::OptionTitlebar {} {
- # returns list of items for the menu
- }
- proc C++::OptionTitlebarSelect {item} {
- # carries out the mode-specific action when 'item' is selected.
- }
-
- Electric code templates
-
- If you mode wants to insert text into the window which contains template
- stops (usually bullets '•' in Alpha), so that the user can move from
- one to the next using the standard Alpha template packages (Alpha comes with
- a basic one, and more sophisticated ones build upon the same
- infrastructure), the you should insert template text with:
-
- elec::Insertion "blah blah •• blah blah"
-
- This is a simple example with a single template stop. Template stops are
- noted with a pair of bullets (even though only one appears in the text).
- You can place between the pair of bullets some more information about the
- template stop, for instance:
-
- elec::Insertion "while \{•condition•\} \{\r\t•while body•\r\}\r••"
-
- would be useful to insert a typical Tcl 'while' loop. The template
- packages can prompt the user with the explanatory text making code
- entry a little bit easier.
-
- The 'elec::Insertion' routine works just like 'insertText' except it treats
- any item •PROMPT• as a template stop called 'PROMPT'. This procedure takes
- a variable number of arguments, just like 'insertText'. It has one further
- side-effect. If there are any stops in the block, then the cursor is
- positioned at the first such stop. Hence you don't need to do this: set p
- [getPos] ; insertText "blah..." ; goto $p ; nextTabStop Instead you just do
- 'elec::Insert "blah..."'. Note that the procedure 'nextTabStop' no longer
- exists. Use "ring::+", "ring::-" etc. to move amongst tab stops. The
- basic Alpha distribution contains only basic template support. Install
- Vince's Additions to extend this support to persistent stops, with
- user-prompting in the text or status bar,... You don't have to change your
- code to take advantage of the features of V'sA. It comes for free if you use
- 'elec::Insertion' etc.
-
- If you wish to use electric templates, avoid binding anything to the 'tab'
- key or the 'j' key (also opt-tab, cmd-tab,…). Such bindings may conflict
- with the electric bindings.
-
- To use electric templates, you'll want to add electricTab to your
- list of default mode-features (or you can leave it for the user to
- activate). If your mode never wants the Tab key to indent, then
- define a dummy '<mode>::indentLine' proc which is empty:
- 'proc <mode>::indentLine {} {}'.
-
- Electric return
-
- This allows pressing return to indent correctly for the following line
- so you may begin typing immediately. To use this simply list this
- package in your mode's 'mode-features' list and, do _not_ bind to the
- return key.
-
- Automatic indentation
-
- Two variables are associated with a window's indentation scheme:
- 'indentationAmount' and the window's tab-size (which can be read
- with 'getWinInfo' or 'text::getTabSize'). If you are writing a custom
- indentation routine, the procedure 'indent::setup' will be useful
- to handle all these choices for you. Look at the relevant section
- of "globals.tcl" to see what that procedure sets up for you. Most
- people user either tab-size = indentation-amount = 4 spaces, OR
- tab-size = 8, indentation-amount = 4 spaces. These cases are quite
- different, and it's nice if your mode allows the user to work with
- their preferred setup.
-
- The marks menu
-
- Each mode has a procedure <mode>::MarkFile which is called to create the
- popup 'M' menu of marks. There is a global flag 'quietlyClearMarks'
- which is set to 1 which dictates that the marks should be rebuilt
- without prompting the user as necessary. You can add a mode-pref
- to over-ride this if you want.
- Just what text-patterns are used to trigger the formation of a 'namedMark'
- (kept in the resource fork), its name, text position and extent, and the
- order in which they are present in the menu, is all determined by the
- <mode>::MarkFile your procedure.
-
- For computer language editing modes, the common convention was to create an
- index by routine names for each routine defined in the file, and to present
- it in alphabetical order. The more current convention is to either
- hardwire, or present the user with the option of listing the routine names
- in the order in which they were defined in the file, indented under the
- name of the code section in which it was defined.
-
- The Tcl mode is a good example of the above, by default the defined Tcl
- proc's are presented in alphabetical order. However if you check the
- 'StucturalMarks' flag in Tcl's mode preferences, you get an index with the
- above format (after regenerating the index via the 'MarkFile' menuitem).
- If you organize your Tcl code into sections of logically or functionally
- related proc's, and then give them a short header by using the
- 'InsertDivider' option under the Tcl Menu, you have an index that can be
- used to quickly get to a procedure when remember its position or
- functionality more than you do its exact name.
-
- Of course, it is still often the case that you remember the name and just
- want to get to it quickly via an alphabetical index, so modes that use the
- above scheme usually provide an alphabetical listing via the '{}' popup,
- which is located right above the 'M' popup (see next topic).
-
- Power User tip: cmd-clicking anywhere in a window's titlebar (except the
- exact center), or in the "bevel'ed frame" will give you the same menu as
- the 'M' popup. Using the sides of the window lets you access a particular
- area of the menu quicker as you can cmd-click in the approximate location
- of the index you want to go to. Additionally, if the window is flush
- against the lefthand edge of your monitor, it is easier to 'crash' your
- cusor into that edge and summon up the mark menu than it is to hit a eight
- inch square button.
-
- The '{}' popup menu
-
- This popup menu can be put to whatever use the mode author wants. If your
- are useing the scheme mentioned in the above section, it is good to use
- this popup to present an alphabetical listing of the routines. Some modes
- add extras such as indicating the number of arguments a routine expects
- (see Tcl), whether a argument is a 'reference' or a 'value' pass (see the
- M2, i.e. modula mode) or anything else that might be useful. Languages that
- use multi-part (qualified) identifiers may name the first part of a group
- of indentifiers and indent the rest of the identifiers that share that
- first part under it.
-
- Power user tip: cmd-opt-<K> will put up a listpick dialog of the indexes
- under the '{}' popup, as this is usually alphabetical you can type the
- starting letters of the index you want to go to. (note: see 'Emacs Help'
- for some other tips to navigate any scrolling list dialog box.)
-
-
-
- <mode>Completions.tcl
-
- Each mode can have a completions file for use by the 'elecCompletions'
- package (part of Vince's Additions or available separately). To use
- this, place the appropriate definitions in a file called
- '<mode>Completions.tcl'. The installer will place such files in the
- 'Completions' directory automatically (provided you don't put them in
- a sub-folder of your distribution), and they will also be sourced
- automatically the first time a file opens in your mode. There is
- therefore no need for you to source the file yourself.
-
- ===============================================================================
-
- Writing new menus
-
- New menus are placed in ":Tcl:Menus", and contain a start-up
- section of much the same form as a mode or feature:
-
- alpha::menu ftpMenu 0.3 global "•141" {
- # One-time initialisation script
-
- # here we do nothing
- } {
- # Activation script
-
- # here we do the standard thing of calling the menu proc
- ftpMenu
- } {
- # Deactivation script
- }
- # proc ftpMenu to auto-load
- proc ftpMenu {} {}
-
- The 'global' parameter tells Alpha that this menu isn't associated with
- any particular mode (otherwise you can replace 'global' by a list of
- modes possibly including the global keyword, e.g. {global WWW HTML}).
-
- Older versions of Alpha used to call a procedure with the same name
- as the menu (here 'ftpMenu') automatically whenever the menu was to
- be inserted. The newer setup is a bit more verbose, but puts more
- control in your hands.
-
- NOTE: If all you want to do is add a submenu to an already existing
- menu, go to the section 'Adding Items to Global Menus': you don't
- need the 'alpha::menu' statement, but actually need to write a
- feature using 'alpha::feature'.
-
- A menu-package is a set of code which builds and handles a standalone menu
- which the user may choose as a global menu. Examples are the ftpMenu,
- filesetMenu, voodooMenu, internetConfigMenu, colorMenu and eudoraMenu (in
- fact this last item, since it has a mode associated with it, could in fact
- be rewritten as a mode with attached menu).
-
- Note: as of Alpha 7.1, you should use the command 'Menu -n ...' to build
- menus, not 'menu -n ...'
- ===============================================================================
-
- Writing new features or extensions
-
- An extension is a package which can be turned on once and then left
- alone. Something which requires turning on/off for different modes is
- a feature. In fact an extension is just implemented as a simple form
- of feature. A new extension must provide at the very least the
- following line, preferably as the first non-comment line of one of its
- files:
-
- alpha::extension 'NAME' 'VERSION'
-
- It is better, if possible, if the extension can provide a small script to
- carry out initialisation (which occurs when Alpha starts up, if the user
- has turned the package on). If provided Alpha will use that script
- rather than sourcing the entire extension file. This means Alpha will
- start up more quickly. Such a script is given by the following line:
-
- alpha::extension 'NAME' 'VERSION' 'SCRIPT'
-
- A feature is more sophisticated and takes arguments of the following
- form:
-
- alpha::feature 'NAME' 'VERSION' 'LIST OF MODES/GLOBAL' \
- 'INIT SCRIPT' 'ACTIVATE SCRIPT' 'DEACTIVATE SCRIPT'
-
- Here is an example from the 'bibtexEngine' package:
-
- alpha::extension bibtexEngine 1.8 {
- eventHandler GURL GURL GURLHandler
- }
-
- Here we didn't bother to turn the feature on and off, since its
- initialisation was so trivial, and it won't interfere with other
- modes at all. Here's a more complex example:
-
- alpha::feature latexMathbb 1.0 {TeX Bib} {
- newPref variable blackboardBoldSymbols "QZRN" TeX TeX::adjustMathbb
- hook::register mode::init TeX::adjustMathbb TeX
- } "" ""
-
- We didn't bother with activation deactivation, since the definitions
- don't take effect in other modes. The simple 'extension' and
- 'feature' commands make it very, very easy to extend Alpha's
- functionality without messing with the user's preferences file,
- without creating any '...+.tcl' extension files and without a complex
- installation process. Alpha simply maintains a database of all
- 'extension' scripts, and evaluates at startup all scripts for
- extensions which the user has activated.
-
- Writing new extensions (keyboard caveats)
-
- Writers of any package for Alpha should pay some attention to the
- problems which can arise with international keyboards. Some bindings
- are simply not available on some keyboards. For instance, on some
- keyboards, you need to use 'shift' to get the key '\' (unlike
- american keyboards where it is a single keypress). On such a keyboard
- there is no distinction between 'cmd-\' and 'shift-cmd-\'. There is
- no simple workaround for this problem.
-
- Possibilities are: (i) check the current keyboard definition and adjust
- bindings appropriately (based upon user feedback, presumably). (ii) let
- the bindings be user-definable either by using 'newPref binding' to
- define things, or by using a menu-scheme such as is used by HTML mode.
-
- Technicalities of different menu/feature/extensions
-
- Menus and features and extensions are all treated in the same way by
- Alpha. However each will have different associated information which
- will determine whether/in what section it appears in a dialog box.
- All this information is stored in the index::feature array.
-
- ...to be continued...
-
- ===============================================================================
-
- Package preferences
-
- Alpha stores preferences in three different places:
-
- 1) Global preferences are stored in the global->preferences menu, and
- are for variables/flags which maintain a value at the global scope.
-
- 2) Mode preferences are stored in the mode->preferences… item, and
- are for variables/flags which are stored in a mode array, but are transfered
- into global scope when that mode is active (and hence temporarily override
- any global preferences with the same names)
-
- 3) Packages may add to the global/mode preferences as they desire. They
- may also store preferences in their package array '${pkg}modeVars(…)'. Such
- variables/flags are never transfered into the global scope. Menu items to
- edit a package's preferences should be placed in the 'global' menu, unless
- they are global/mode prefs which should be added to Alpha's default
- routines for use by the standard Alpha dialogs. There is a standard proc
-
- package::addPrefsDialog Mypkg
-
- which you can use to add an item to the global menu which will bring
- up the standard dialog to edit the contents of your '${pkg}modeVars(…)'
- array.
-
- Adding to the core prefs dialogs
-
- If you wish to add items to any of the core preferences pages (Backups,
- Electric, Miscellaneous,...), you can do that like this:
-
- lunion varPrefs(Electric) var1 var2
- lunion flagPrefs(Electric) flag1 flag2
-
- All non-registered global preferences are added to the Miscellaneous page,
- so there is no need to do that automatically. Make sure you don't add
- too much to any of these pages, because they will become too large to
- display correctly!
-
- You can also add new core preferences pages. All you have to do is create
- a new 'flagPrefs' entry (Alpha uses the command 'array names flagPrefs' to
- list the different pages):
-
- lunion flagPrefs(NewPage) flag1
-
- Only add such pages if your package really does merit it; otherwise you're
- better off just add a new global preferences dialog in the global menu.
-
- Defining a package's flags and variables
-
- Preferences for a mode or package are defined as follows:
-
- # description of the preference
- newPref type name {val 0} {pkg "global"} {pname ""} \
- {options ""} {subopt ""}
-
- Define a new preference variable/flag.
-
- 'type' is one of:
- 'flag' (on/off only), 'variable' (anything), 'binding' (key-combo)
- 'menubinding' (key-combo which works in a menu), 'file' (input only),
- 'io-file' (either input or output)
-
- 'name' is the var name,
-
- 'val' is its default value (which will be ignored if the variable
- already has a value)
-
- 'pkg' is either 'global' to mean a global preference, or the name
- of the mode or package (no spaces) for which this is a preference.
-
- 'pname' is a procedure to call if this preference is changed by
- the user (no need to setup a trace). This proc is only called
- for changes made through prefs dialogs or prefs menus created by
- Alpha's core procs. Other changes are not traced.
-
- Depending on the previous values, there are two optional arguments
- with the following uses:
-
- TYPE:
-
- variable:
-
- 'options' is a list of items from which this preference takes a single
- item.
- 'subopt' is any of 'item', 'index', 'varitem' or 'varindex' or 'array', where
- 'item' indicates the pref is simply an item from the given list
- of items, 'index' indicates it is an index into that list, and
- 'var*' indicates 'items' is in fact the name of a global variable
- which contains the list. 'array' means take one of the values from an array.
- If no value is given, 'item' is the default
-
- binding:
-
- 'options' is the name of a proc to which this item should be bound.
- If options = '1', then we bind to the proc with the same name as
- this variable. Otherwise we do not perform automatic bindings.
-
- 'subopt' indicates whether the binding is mode-specific or global.
- It should either be 'global' or the name of a mode. If not given,
- it defaults to 'global' for all non-modes, and to mode-specific for
- all packages. (Alpha tests if something is a mode by the existence
- of modeMenus($mode))
-
- menubinding:
-
- menubindings are like bindings, but they don't have any automatic
- binding capabilities, and are restricted to key-sequences which the
- MacOS allows in menus. Here is an example of how one might declare
- the 'QuickFind(Regexp)' dynamic pair using a menubinding pref:
-
- declare the binding:
-
- «Alpha ƒ» newPref menubinding quickFind/quickFindRegexp <B/S
-
- edit it if we like with:
-
- «Alpha ƒ» dialog::getAKey quickFind/quickFindRegexp <B/S
-
- show the menu sequence if we like:
-
- «Alpha ƒ» menu::bind quickFind/quickFindRegexp -
- <S<E<B/SquickFind <S<I<B/SquickFindRegexp
- «Alpha ƒ»
-
- add it to a menu:
-
- «Alpha ƒ» eval menu::insert Search items end \
- [menu::bind quickFind/quickFindRegexp -]
-
- Have a look at the search menu. It has a new dynamic item at the bottom!
-
- Note that if you place a comment (one or more lines) just before the
- 'newPref' statement, it is scanned and stored by Alpha in a cache. It
- can then be used to explain to the user what each preference does when
- the user selects 'describe mode' or presses the 'Help' button in a
- preference dialog.
-
- Declaring help text for your preferences
-
- Alpha has the ability to extract descriptive text for your preference
- items automatically, provided they are declared using 'newPref', and
- that you follow these guidelines.
-
- If there is a comment (a line starting with '#') on the line/lines
- preceding the newPref command, Alpha will (when it rebuilds the package
- indices) store the text in that line/lines and use it to display helpful
- information for that preference. For example if you hit the 'help' button
- in a dialog, Alpha will display this information. Furthermore, in the
- forthcoming Alpha 8.0, this information will be used for balloon help in
- the prefs dialog related to your package/mode, provided you use the
- standard mechanisms for declaring your mode/menu/feature/extension and you
- use the standard preference mechanism supplied. The format of the comment
- lines is simple for all except basic flags (newPref flag ...). These will
- display a different help text in balloons depending on their state. There
- are four possible states, although Alpha only really uses the first and
- third such states at present. The first state is the 'unchecked' state,
- and the third the 'checked' state. You declare separate help text for the
- four possible states like this:
-
- # it is unchecked|it is dimmed|it is checked|it is checked and dimmed
- newPref flag myFlag ...
-
- In fact all help items have four possible states, although you will
- usually not notice the other possibilities. As you can see, Alpha uses '|'
- to separate the different pieces of text. Currently a typical help text
- for a checkbox item should probably just look like this:
-
- # To use a solid rectangular cursor, click this box||To use a thin
- # vertical cursor, click this box.
- newPref flag blockCursor 0
-
- Notice the syntax of the two messages. Apple's interface guidelines
- give some advice for balloon help which you should follow for two
- reasons: first, it's good advice for writing balloons, and second,
- Alpha assumes your messages are of the above form to use the text
- effectively both for balloons, and for descriptive text. Alpha will
- automatically convert the above to:
-
- Block Cursor: To use a solid rectangular cursor, turn this item on. To
- use a thin vertical cursor, turn this item off.
-
- which is used in the descriptive dialogs Alpha sometimes provides. This
- advice is of greatest importance for 'flag' preference items, since they
- require two separate on/off balloon help texts. Other items currently
- just expect one piece of text. Each text item should be no longer than
- 255 characters. The simplest balloon help methods impose this constraint
- (in principle it could be relaxed, by using the more complex help methods
- inside Alpha, but it doesn't seem necessary).
-
- A similar mechanism will soon be available for menus.
-
- Adding items to global menus
-
- Using 'addMenuItem' is a bad idea, since many menus are dynamically
- rebuilt and such items will be lost. Furthermore, addMenuItem does
- not work if you want to add dynamic items or sub-menus. Also
- creating a menu directly using 'Menu -n Name {list of items}' is
- generally a bad thing to do when using Alpha version 7.0 or newer.
-
- The solution to these problems is to use the following calls:
-
- menu::buildProc 'nameOfMenu' 'nameOfIts_build-proc'
- menu::insert 'nameOfMenu' 'type' 'where' 'menuItem' ?menuItem...?
-
- For technical reasons, if you use both types of call, always add the procs
- first. You can add any list of menuItems using the latter of these two calls.
- The first registers a procedure which will be called to build a given menu.
-
- Menus must be rewritten to support this new feature. Currently all
- global menus File...Config support it, and several modes: Tcl, Perl,
- TeX.
-
- menu::buildProc
-
- This proc registers a procedure to be the 'build-proc' for a given menu
- (tech note: just adds the build-proc to the "menu_build_procs" global array
- with the given menu's name as its index). The build-proc procedure can do
- one of two things:
-
- i) build the entire menu, including evaluating the 'Menu ...' command.
- In this case the build proc should return anything which doesn't
- begin 'build ...'
-
- If the proc returns anything beginning with 'Menu ..' that returned
- string is evaluated, but no insertions can take place.
-
- ii) build up part of the menu, and then allow pre-registered menu
- insertions/replacements to take-effect. In this case the procedure
- should return a list of the following (listed by index in the list):
-
- 0: "build"
- 1: list-of-items-in-the-menu
- 2: menu procedure to call when an item is selected. If nothing is given,
- or if '-1' is given, then we don't have a procedure. If "" is given,
- we use the standard 'menu::generalProc' procedure. Else we use the
- given procedure.
- 3: list of submenus which need building.
- 4: over-ride for the name of the menu.
-
- Here is an example of what gets returned by "menu::globalBuild", the
- build-proc for the menu named "global" (see Config:Global:):
-
- «Alpha ƒ» menu::globalBuild
- 0: build
- 1: {
- /p<U<BmenusAndFeatures…
- {Menu -n preferences {}}
- editPrefsFile
- (-
- compareWindowsPrefs…
- newDocumentPrefs…
- (-
- specialKeys…
- listGlobalBindings
- listPackages
- listAllBindings
- listFunctions
- (-
- rebuildPackageIndices
- }
- 2: menu::globalProc
- 3: preferences
-
- Note: the above output was reformated and numbered to make its structure
- explicit, also note that any additions to what you see in 'Config:Global:'
- are due to calls to "menu::insert".
-
- You must register the build-proc before attempting to build the menu (i.e.
- call menu::buildProc.
-
- Once registered, any call of 'menu::buildSome <name of your menu>' will
- build your menu.
-
- menu::insert
-
- nameOfMenu, type, where, then list of menuItems. Here, type can be, either
- 'items', or 'submenu'.
-
- Add given items to a given menu, provided they are not already there.
- Rebuild that menu if necessary.
-
- There are also procs 'menu::removeFrom' which does the opposite of
- this one, and 'menu::replaceWith' which replaces a given menu item
- with others.
-
- There is a difference between 'menu::insert Utils submenu 2 compare' and
- 'menu::insert Utils items 2 [list Menu -n compare {}]'. The former
- registers the submenu as a submenu which will be built automatically by a
- call to 'menu::buildSome' each time the parent menu is rebuilt, the latter
- does no such thing. You will, therefore normally wish to use the first
- form, but occasionally there will be situations when the latter would be
- better.
-
- Here is a simple example:
-
- alpha::extension compareWindows 0.1 {
- Bind 0x32 <X> compare::windowsInPlace
- Bind '1' <X> compareOpt
- Bind 0x32 <sX> compareNext
- Bind 0x12 <sX> compareOptNext
- menu::insert Utils submenu 2 compare
- menu::insert "compare" items end windowsInPlace
- }
-
- We first add a submenu after the second item in the Utils menu, called
- 'compare', and then add to the end of that compare menu. This code works
- whether the package is active at startup or not. Here is a more
- complex example:
-
- alpha::extension documentProjects 1.2 {
- alpha::package require elecCompletions
- alpha::package require newDocument
- menu::buildProc "Current Project" Docproj::currentMenu
- menu::insert global items end \
- "documentProjectPrefs…" "userDetails…" \
- "<E<SremoveDocumentTemplate…" "<S<BeditDocumentTemplate…" \
- "<SnewDocumentTemplate…" \
- "<E<SremoveProject…" "<S<BeditProject…" "<SnewProject…"
- menu::insert global submenu end {Current Project}
- newPref binding updateFileVersion "/f<U" Docproj
- menu::insert fileUtils items end \
- "showInFinder" \
- "(-" \
- "updateDate" \
- "[menu::bind DocprojmodeVars(updateFileVersion) -]"
- lunion elec::MenuTemplates "createHeader" "newDocument"
- menu::insert elec items end \
- {Menu -n functionComments -p menu::fileUtils {
- "/efunctionComment"
- "/e<IfunctionCommentSimple"
- "/e<OfunctionCommentWithAuthor"
- "/e<UfunctionCommentUpdate"
- }}
- set newDocument::handlers(documentProjects) Docproj::newHandler
- }
-
- The 'documentProjects' package adds items to many different menus,
- including the 'elec' menu (from the elecCompletions package).
-
- ===============================================================================
-
- Package testing
-
- The 'alpha::package' command is very similar to Tcl 8.0's standard
- 'package' command, but differs in a few respects. When Alpha upgrades
- to Tcl 8, this will allow both features to coexist happily. You can use
- 'alpha::package' to check/request the presence of other packages.
-
- alpha::package require NAME ?VERSION?
-
- Other sub-commands are 'exists' 'names' 'versions' 'vcompare' 'vsatisfies'
- 'forget' 'uninstall' and 'mode', 'menu' and 'package'. These last three
- mimic the usual alpha::mode alpha::menu and alpha::package commands.
-
- alpha::package require ?-extension -mode -menu? name version
- alpha::package exists ?-extension -mode -menu? name version
- alpha::package names
- alpha::package uninstall name version [this-file|this-directory|script]
- alpha::package vcompare v1 v2
- alpha::package vsatisfies v1 v2
- alpha::package versions ?-extension -mode -menu? name
- alpha::package type name
- alpha::package info name
- alpha::package maintainer name version {name email web-page}
- alpha::package help name version [file 'name'|text]
-
- Equivalent to alpha::mode, alpha::menu and alpha::extension
-
- alpha::package mode ...
- alpha::package menu ...
- alpha::package extension ...
-
- For extensions only:
-
- alpha::package forget name version
-
- ..
-
- ===============================================================================
-
- Installation
-
- There is a new install mode 'Inst' which adds the Install menu.
- Install mode is trigerred when a file's name ends in 'Install'
- or 'INSTALL', or when the first line of the file contains the
- letters 'install', provided in this last case, that the file
- is not in Alpha's Tcl hierarchy. This last case is useful so
- that a single .tcl file can be a package and be installed by
- Alpha using these nice scripts, without the need for a separate
- install-script-file. However once that .tcl file is installed,
- if you open it you certainly wouldn't want it opened in Install mode!
-
- So, single file packages should just include 'install' somewhere in
- their first line. Multi-file packages should include an install
- file. Call this file 'OPEN TO INSTALL' or something like that.
- When the user opens it, Inst mode is activated, and the user can
- use the install menu to install your package. If you wish the
- installation dialog to be activated automatically, include the
- text (auto-install) in the first line of the file.
-
- Most packages will _not_ need anything other than the existence of
- such a file. In fact a file called 'OPEN TO INSTALL' containing the
- single line '(auto-install)' will do the trick nicely.
-
- Alpha will scan the installation file directory and make a nice
- dialog with 'Easy install' and 'Custom install' options. Alpha
- knows where Modes, Menus, Completions, Bug fixes, Tools, Packages,
- Extensions, ... all go in the Alpha hierarchy.
-
- Package-specific installation over-rides
-
- You can over-ride the default behaviour by providing a 'xxx_install.tcl'
- file in the file directory. In such a case that file will be sourced.
- See "install.tcl" for some more information on how to over-ride the
- default behaviour. You will usually use the following procedure:
-
- install::packageInstallationDialog 'NAME' 'DESCRIPTION' ...
-
- Optional arguments are as follows:
-
- -ignore {list of files to ignore}
- -remove {list of files to remove from Alpha hierarchy}
- -forcequit '0 or 1'
- (forces the user to quit; default 0)
- -require {Pkg version Pkg version …}
- e.g. -require {Alpha 7.0b1p2 elecCompletions 7.99}
- -provide {Pkg version Pkg version …}
-
- and
-
- -SystemCode -Modes -Menus -BugFixes -Completions -Packages
- -ExtensionsCode -UserModifications -Tools -Home
-
- which force the placement/use of the following lists of files. To
- require an exact package version use:
-
- -require {Alpha {-exact 7.0b2} elecCompletions {-exact 8.1.2} ...}
-
- Also, rather than having separate 'OPEN-TO-INSTALL' and '*install.tcl'
- files, if the former file contains the text 'auto-install-script' in
- its first line, it will be used as a Tcl script, and sourced rather than
- opened. Ensure that first line begins with a '#' or an error will
- result. (You can open that file for editing, without triggering the
- install script if you hold down a modifier key).
-
- If you gave the -provide option, Alpha checks those items with what
- the user has already installed and warns if an item has already been
- installed and is not older than the one about to be installed.
-
- Uninstalling packages
-
- Each package should provide a 'alpha::package uninstall name version script'
- statement. When your script is evaluated, the global variable 'pkg_file'
- will be initialised to the full name of the file which contains the
- uninstall command. Therefore for a single file package, the following is
- normal:
-
- alpha::package uninstall developerUtilities 1.1 {removeFile $pkg_file}
-
- However, a much more convenient form of the above command is also possible,
- and most packages use it --- you may combine declaration and uninstall lines
- like this:
-
- alpha::extension developerUtilities 1.1 {
- # declaration script
- } uninstall {
- # uninstall script
- }
-
- i.e. there are two extra optional arguments to the 'package' command.
- Finally to be even simpler, if the command is 'uninstall this-file',
- then that is equivalent to {removeFile $pkg_file}, and if the command
- is 'uninstall this-directory', then that entire file's directory is
- removed. Make sure you don't use 'uninstall this-directory' for a
- single-file package, or you'll wipe out the entire package hierarchy.
- Similarly alpha::mode and alpha::menu commands may contain an optional
- uninstall script like the above.
-
- Disabling packages
-
- A package can add a script to be evaluated when the user disables the
- package. You do that with the additional command 'disable':
-
- alpha::extension developerUtilities 1.1 {
- # declaration script
- } disable {
- # disable script
- }
-
- Complex packages will probably not provide such a script. In such a
- case the user would have to restart Alpha to disable the package
- correctly.
-
- Tcl index files
-
- You probably know that Tcl uses 'index' files to find procedures which
- are called but not yet defined. Your installation directories may
- contain index files if you desire, but they are only installed if no
- current index file exists in the installation location. You cannot
- override this behaviour.
-
- ===============================================================================
-
- Vince's Additions Support:
-
- This is primarily for new modes.
-
- Source-Header files
-
- If your mode makes distinctions between 'Source' and 'Header'
- files, you should define these two variables
-
- newPref var sourceSuffices { .cc .cp .cpp .c .icc } C++
- newPref var headerSuffices { .h .hh } C++
-
- Completions
-
- If you mode is to use a variety of completion routines, define
- an array entry like this:
-
- set completions(${mode}) \
- {completion::cmd completion::electric completion::word}
-
- For the meaning of the list items, look at "elecCompletion.tcl". If
- all you need is the basic 'Command', 'Electric' and 'Word' completion
- routines, the above list will do the trick. You will then need to
- define a variable ${mode}cmds like this:
-
- set Ccmds { #elseif #endif #include class default enum for register return
- struct switch typedef volatile while }
-
- It MUST be in alphabetical order. For electric template insertions, you need
- to create an array with entries like these:
-
- set Celectrics(for) " (•init•;•test•;•increment•)\{\n\t•loop body•\n\}\n••"
- set Celectrics(while) " (•test•)\{\n\t•loop body•\n\}\n••"
- set Celectrics(switch) " (•value•)\{\n…case •item•:\n\t•case body•\n…default:\n\t•default body•\n\}\n••"
- set Celectrics(case) " •item•:\n…•case body•\ncase"
-
- Mode-specific completions
-
- If your mode has its own completion routines, they must be named
- ${mode}::Completion::Type, where 'Type' is an entry in the above
- list. You'll have to know a reasonable bit of Tcl to write your
- own routines like that. Look at C::Completion::Class for a relatively
- simple example.
-
- Electric menu templates
-
- ${mode}Templates is a list of names which are added to the electric
- menu's 'Templates' sub-menu. The real procs should be called
- 'file::${name}'.
-
- Vince's Additions summary
-
- That's it! Take a look at "scilabMode.tcl" as a simple example of a new mode
- which makes use of Vince's Additions.
-
- ===============================================================================
-
-