Document id

Copyright © 1995-2007 Jari Aalto

License: This material may be distributed only subject to the terms and conditions set forth in GNU General Public License v2 or later; or, at your option, distributed under the terms of GNU Free Documentation License version 1.2 or later (GNU FDL).

This page contains manual pages from each Emacs tiny*.el module in alphabetical order. The tools initially started around 1994 and they include many Emacs related utilities ranging from Emacs path configuration, email, Gnus spam reply functions, diffing, patching, URL jumping, eating text and many more.

Note: you cannot download single files or install only a single file. the minimum requirement are all libraries tinylib*.el plus any individual utility package.

Generated documentation

This document is automatically generated from the Emacs lisp files with 2 small perl scripts. ripdoc.pl is available at http://cpan.perl.org/modules/by-authors/id/J/JA/JARIAALTO/ and the other is hosted at http://perl-text2html.sourceforge.net/

      % ripdoc.pl `ls ti*.el|sort` | t2html.pl > emacs-tiny-tools.html    

The perl program assume that the documentation sections have been written in Technical Text Format (you are looking at TF layout in this file). An Emacs minor mode for writing TF files is available in package tinytf.el.

Brief overview

There are plenty of packages to choose from and almost nobody uses them all in one emacs session, so here are some recommendations. The setup examples for many of these packages are available in the unpacked kit under rc/emacs-rc-tiny.el. Start with the top ten and add other packages that you find useful. The order of appearance is also the recommended installation order: "install this, see the docs, and go to next one..."

Top ten or so

Other packages

And more...which are not listed in these


Load-path.el --- Used for compiling Emacs lisp files

File id

Copyright © 1997-2007 Jari Aalto
$keywords: extensions $

This code is free software in terms of GNU Gen. pub. Lic. v2 or later

Description

This file part of the Tiny Tools Kit for Emacs: collection of various utilities.

Before compiling, this file is included via -l FILE switch and it defines correct load path in order to find the files that are needed in compilation. If your private directory is not in ~/elisp or ~/lisp then add new path to the place shown below.

Note for older 19.xx Emacs

If you're compiling with custom support, please include you custom directory to the list too. Like ~/elisp/custom

See the doc/README.txt for starter compiling instructions for the Tiny Tools kit.


Tiny-setup.el --- Tiny Tools configure center.

Preface, overview of options

This file will configure all Tiny Tool files. The alternative method is to look into each package individually and to follow instructions there to set up the files.

To use this file, see control function tinypath-setup for full description like this:

      M-x RET load-library RET tiny-setup RET
      C-h f tinypath-setup
      M-x tinypath-setup-display

      M-x tiny-setup RET                       Default 'all setup    

To setup all tools from $HOME/.emacs, use:

      (load "~/path/to/tinypath.el")   ;; Emacs autosetup, SEE THIS!
      (require 'tiny-setup)            ;; control center
      (tiny-setup 'all)                ;; configure all at once.    

Administration

This part should concern the maintainer only.

Autoload files

If loaddef files were not included in the package or if they were mistakenly deleted. The tiny-setup.el startup is not possible without the autoload files.

To generate autoloads recursively, call function tiny-setup-autoload-batch-update with the ROOT directory of your lisp files. The only requirement is that each directory name is unique, because the generated autoload file name contains directory name: tiny-autoload-loaddefs-DIRNAME.el

Compilation check

To check for possible leaks in code, ran the byte compilation function from shell by using XEmacs compiler. The Emacs byte compiler is not that good in findings all errors. See function tiny-setup-compile-kit-all.

Profiling

To check how much time each file load would take, see function tiny-setup-test-load-time-libraries. Here are results as of 2001-03-18 running Win9x/512Meg/400Mhz, Emacs 20.7

      Timing tinyliba,  took     2.025000 secs (autoloads)
      Timing tinylibb,  took     0.011000 secs
      Timing tinylibm,  took     0.977000 secs
      Timing tinylib,   took     0.982000 secs
      Timing tinylibxe, took     0.000000 secs
      Timing tinylibid, took     0.006000 secs
      Timing tinylibo,  took     0.005000 secs
      Timing tinylibt,  took     0.011000 secs
      total time is 4.027999997138977 seconds    


Tinyadvice.el --- Collection of adviced functions

Preface, Apr 1996

What you see here is a selection of adviced functions that have proven to be extremely useful. Some of them have been written by the author (if there is no author mentioned) and some of them have been collected form the emacs newsgroups.

Here is one example how to to fontify automatically, whenever compilation buffer runs:

      (add-hook 'tinyadvice-:compile-internal-hook 'my-compile-font-lock)

      (defun my-compile-font-lock  ()
        "Compile buffer fontifying immediately."
        (interactive)
        (let* ((buffer tinyadvice-:compile-internal-buffer))
          ;; According to buffer you could set up different font
          ;; keyword parameters, say for
          ;; *compilation*
          ;; *grep*
          ;; *igrep*
          ;;  My setup automatically turn on the lazy-lock too, see
          ;;  font-lock-mode-hook
          (with-current-buffer
           buffer
            (turn-on-font-lock))))    

Note: XEmacs

These advices are for Emacs and it would be a surprise if they worked in XEmacs. Use at your own risk. Send fixed XEmacs compatible advices to maintained if you try them.

These advises and Emacs releases

Many of these enhancements could have shipped with the Emacs itself. And there was a time when these were suggested to be added to the next Emacs release. For some reason the developers were not interested in the features at that time.

How to use this package

The best way is to load this package, print the whole file and read the comments about individual functions and how they change things.

Note on adviced file functions

If you set variable tinyadvice-:file-compress-support to no-nil then you can compress files on disk at wish and emacs packages that read/save data from/to files doesn't even notice that you have compressed them. This is very valuable feature if you are low of quota, e.g. you can now compress Gnus .newsrc.eld and gnus will read the .newsrc.eld.gz transparently. See write-file and find-file function documentation for full explanation of this feature.

Overview of features

In general, advices are activated only if Emacs release doesn't have similar kind of support.

Handling advices

If you have some other emacs version that is not supported in the tinyadvice-:advice-table you can modify the regexps in the list and try if the advice works in your emacs. If it does, please drop me a mail immediately and I update the regexp. If some advice annoys you, there is simple method how you disable advice(s).

      (setq tinyadvice-load-hook '(tinyadvice-install my-tinyadvice-load-hook))

      (defun my-tinyadvice-load-hook ()
        "Configure 'tiny tool's advices' to my taste."
        (interactive)
        ;; This diables two advices
        (tinyadvice-advice 'disable
           '(switch-to-buffer mouse-delete-other-windows)))
      (require 'tinyadvice)    

Disabling disturbing advice by hand

If some piece of advice disturbs or causes trouble in your current emacs session, you can deactivate it immediately. First you have to know the function name that generates problems. Say you used C-x C-b switch-to-buffer and you don't like the confirmation for non-existent buffers. You can disable this behavior by calling:

      C-u M-x tinyadvice-advice    

and giving the function name switch-to-buffer to it. To permanently turn it off in your emacs sessions, see previous lisp code.

Code note

You see this in the code:

      (when (tinyadvice-activate-p)
          (defadvice ..    

If emacs version is wrong, the advice is never actually assembled. You can't activate or deactivate this function with tinyadvice-advice.

Many thanks to, in no particular order:

Vladimir Alexiev vladimir@cs.ualberta.ca Kevin Rodgers kevinr@ihs.com Ilya Zakharevich ilya@math.ohio-state.edu Peter Breton pbreton@i-kinetics.com T. V. Raman raman@adobe.com


Tinyappend.el --- A simple text gathering to buffer utility.

Preface, March 1994

This package does nothing fancy, it gathers text from buffers with few key bindings. Later you can then peek on that buffer, arrange text etc. C-x a is handy when appending data to buffer, but it's annoying that you have to give "buffer name" all the time This one adds to buffer "*append*" automatically, creating one if it doesn't exist.

I'd strongly recommend you to keep transient-mark-mode (Emacs) on all the time, so that you can see if you're adding a selected region into the append buffer. If the region is not active, these functions normally add the current line to the append buffer.

Default bindings

My keyboard (HP-UX / X window) just happens to access these keys easily, so I chose them. Add function tinyappend-install-default-key-bindings to tinyappend-:load-hook if you want to use these key bindings.

      C-c =       Append to the end
      C-c -       Append to the beginning
      C-c _       underscore, Kill (empty) *append* buffer
      C-c |       Yank text from append buffer    


Tinybookmark.el --- Keep file in organized sections

Preface, feb 1995

Long ago I used little function I wrote that inserted section breaks, those that I call book marks. There was also folding.el to keep the code in separate sections. Findings things was easy when you just searched either book marks or jumped between folds. Next imenu.el was announced which provided X-pop up for book marks and adding support to it was the start of this package.

Overview of features

How to keep files organized

There are several tools to keep your code organized and they are at their best if you think how they can co-operate. There is folding.el and tinybookmark.el, which might seem to do double job, since they both divide code into more easily manageable sections. The key point is that when folding is used, one works within some special section and possibly want to hide all the rest of the code. But when jumping easily back and forth on the buffer, it us unfolded and TinyBookmark is used. Now, to confuse you more, there is also imenu.el which can be used to jump inside code. It can be configured so that it will pick all function names inside list, and when you want to go to specific function, just pick one from imenu.

To summarize:

How to use this package

There is following function that inserts book mark on the current line

      tinybookmark-insert    

There is also normal repeat function, that fills line with your pattern:

      tinybookmark-repeat    

Normally the usual book mark separator is the "." <dot> , which isn't so "noisy" as continuous '-' line. Normally you add some unused ID character, like '&' at front of real book mark, like this:

      (defun test ()
       (progn
        ..
        (goto-char ..
        ;; ^^^^^^^^^^^^^^^^^^^^^^^ sepratorInsideCode ^^^    

The How-to-use is book mark, because it has & on it, whilst the latter isn't – it is used inside code to make it more readable and The latter on is not included in imenu.

About the book mark identifier naming

When you name the breaks, keep in mind that when identifiers are sorted, the ones that start with big letters A-Z show up first, a-z come next. Allthougt it would be convenient to have all subwords in capital, it is usually better to start with lowercase letter, because it's easily unintentionally mix up/down case letters. Besides you have to reah out for shift to have uppercase.

      ............. breakName ...         ;prefered, starting low
      ............. BreakName ...         ;watch out for mixed case!    

it is also adviced that you choose some common beginning for the identifier, so that they get sorted nicely. If you define variables at the beginning of file it might be good idea to attach beginning letter like v- for variables before the real identifier name begins, like:

      ............. v-globals ...
      ............... v-hooks ...    

Of course, we can now use the uppercase letter trick to have them sorted first in the list, just change v- to V-. Generally you should think which ones do you use most, do you leave the variables alone when you have defined them and mostly work with new functions? Then the variables can stay at the end of list and there is no need for V- trick. but if you need to access variables often, then you might want to see variables first in the list. It's up to your decision how you name the variables and how you want to see them listed.

Breaks and sub-break naming

If you have very large file, you'll probably need major breaks, level one breaks and possibly level 2 breaks too. To keep the list well sorted, put the functions into bigger groups and name the sub-level breaks so that they have some common beginning in respect to the major break they belong to. Let's see an example where you're dealing with mail handling. Notice the CAPITAL letter.

      ;; ################################# &h-Header ###
      ;;  this is beginning block of header handling

      ;;  Some special function here to handle CC
      ;;  field, killing all recipients, or only
      ;;  some of them

      ;;  More detailed functions under h-cc, Not
      ;;  named, because there is only 2 small funcs
      ;;  easily found.    

Again there are couple of points to follow here. All the tricks are discussed already: the Big letter trick put's major break to the top of imenu list, common beginning keeps the subsections together.

Example breaks

Some book mark breaks are proposed here, but you can use whatever you like. Thumb of rule: be consistent, always use same convention in your files and consider the "level of noisiness" of your breaks, so that they build up nicely and the code is easy to read. Too many different breaks is not good idea, because they clutter the view fast, instead use variations on a theme: same break character but varying spaces and continuous character lengths.

Thumb rule: select 1-3 break chars, and never change them in you files; your files look alike. Vary the spacing, not the break characters.

These are 'noisy breaks' , Major section separators, pick only one and use it in your files, do not use all three!

      ##############################################################
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||    

less noisy breaks

      .`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`

      .^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^

      .:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:
      .~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~    

This is sub section break

      ................................................................    

This is even lighter subsection break (varying spacing)

      ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...    

'Draw one's attention' break: something special in this section

      --++-- --++-- --++-- --++-- --++-- --++-- --++-- --++-- --++--    

Internal break 1, inside function, long case statement etc.

      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^    

Internal break 2, to separate long case elements etc.

      ^^^  ^^^  ^^^  ^^^  ^^^  ^^^  ^^^  ^^^  ^^^  ^^^  ^^^  ^^^  ^^^    

Book Mark cache

So that imenu works fast, it is not desirable that the breaks are always parsed from scratch, because it takes time to scan the file for possible book marks. That's why the information is cached. If the break cache is empty, the breaks are gathered from buffer and stored to the cache and when you call the imenu, the cache is offered to it --> fast response time. When you add new breaks to the buffer [especially at the beginning of code development], you may want to call function tinybookmark-parse which will empty the cache and re-read all book marks. If you write lot of code the points that were cached do no longer represent exact points of book marks, because they have been sliding off their places. If you want always have updated book mark points, there is variable tinybookmark-cache-update which you can set to 'always, if you want the cache to be updated always prior showing X-menu. In large buffer this remarkably slows down the menu appering. See variable for more choices.

Automatic book mark detection

In order book marks to be detected in file, you may define following RCS identifier [see ident(1)] preferably at the beginning of your file:

      $BookMarkRegexp:<space>'REGEXP'<space>$    

Be careful so that the identifier is exactly in this form: pay attention to spaces and (') around the REGEXP. The regular expression tells what line can be considered as book mark and the book mark name is indicated in subexpression 1 [\\(.*\\)] , look at this file, how it is constructed. In order to find all book marks and build up the cache, it needs to widen the buffer in case the file is narrowed with some folding or outline editor. When the cache has been built the buffer's narrowing is restored, so you shouldn't even notice this. Of course you don't want to find book marks from your RMAIL file.

One word about the regexp construction, let's see regexp that matches the identifier:

      &+\\([^ ]+\\)    

Pay attention to using exclusive regexp, not just '.*' construction. When you use folding or outline editor the '.*' form is very ill behaving, because if the line being scanned is currently folded, IT WILL MATCH WHOLE folded section --> your identifier surely isn't that one. We can't unfold the sections during scanning, because if there are subfolds, what editor is on use .. it's too complex/slow to handle such situations. But using the exclusive list [^ ] will surely match the identifier, because it stops when it can find first space. This means that you can't use spaces inside the identifiers. Cat the words together.

If the BookMarkRegexp isn't defined in file

Then the programs tries to search for the default book marks. See function tinybookmark-regexp-default for more.

Message: Empty cache. Building...

Do you wonder why you get this message displayed, while you were sure that you the buffer had cache already? Don't be surprised. This is totally normal behavior: whenever you switch mode for the buffer the new mode kills all local variables, including cache information. Obviously the information must be restored when you call the hot list again. The cache could have been programmed to be buffer local, but in the present format only one cache s active at the time. This was simpler to implement and manage in the code.

About imenu

You definitely want to look at the documentation of imenu to find many more usages for it. It makes your day shine in X-display. You should also configure few variables for it, like:

      (setq imenu-max-items 20)    

Test run

Load this file and set those key bindings mentioned. Hit the mouse bindings and you're running book mark package. Since the break marks are used in commentary also, the list of book marks are not in their most informative form, I use following convention to name book marks;

      'v-'     variable topic
      't-'     text topic    

Design thoughts

Sooner or later someone wonders: "Can't we have sub-breaks listed nicely with indentation in front lines in X-popup?" Present answer "No", since it would require keeping track of the 'Main break' and then seeing if there exist sub-breaks. Immediately this leads to question "What is the main break?", and if we say main breaks start with "#|/%" character set we limit the use of breaks. Besides deciding what are sub-breaks, main-breaks with regexp may be too slow. Besides, the breaks are intended to to give an overview of the buffer. Please use imenu to find single functions if you don't feel like tapping couple of pgUp/pgDown after the point is positioned in the break section.


Tinybuffer.el --- Change buffers in current window.

Preface, May 1996

With this small package you can switch to next or previous buffer in a current window. If you only have small amount of buffers in buffer-list, this may be the fastest way to select a working buffer. In the other hand, if you have more than 20 working buffers, I'd recommend that you use exellent substring buffer switching utility instead: iswitchb.el which is included in standard Emacs distribution

If you have windowed environment and want to have hot list of your permanent buffers available, use imenu.el or tinyhotlist.el and you can select RMAIL; GNUS; VM; scratch buffers instantly.

Description

If you don't want default bindings, clear the installation with following command. This must be prior the 'require statement.

      (setq tinybuffer-:load-hook nil)    

To change buffers forward or backward, the default setup would install following key bindings:

In iswitch mode, the command prompt looks like following. The mode name is put last if buffer has and associated file name, so that filename gets as much display as possible.

          "TinyIswitch: my-lisp.el     ~/elisp/my-lisp.el <Emacs lisp>"
          "TinyIswitch: test           <dired> ~/tmp/test"
          "TinyIswitch: *Messages*     <fundamental-mode>"    

Have a look at tinybuffer-:ignore-regex which you can configure to ignore some buffers permanently.

Thanks

Original idea for this package comes from yic-buffer.el by choo@cs.yale.edu (young-il choo) 1990-08-07.


Tinycache.el --- Maintain a cache of visited files [compile,dired]

Preface, overview of features

This package is meant to be used with dired and compilation buffers. When you load file from either one, the file is "remembered". This way you can browse bunch of files easily and when you have finished you can flush the cache and get rid of all vieved files.

Dired description

When you load a file from dired with dired-view-file, the file is remembered. You can load several files for viewing and when you have finished, call tinycache-flush (Defaults to C-c k in dired) to remove all the remembered (cached) files from emacs.

This way you don't end up having files that you're not interested in any more. Using the cache makes browsing bunch of files very easy. Each dired buffer has it's own cache. The cache is also flushed if you kill the dired buffer.

Compilation cache description

Maintain also a cache of buffers visiting files via the next-error and compile-goto-error commands; each compile/grep buffer has its own cache. To kill the cached buffers manually, use C-c C-d (compile-flush-cache) in the compile/grep buffer; deleting the compile/grep buffer automatically kills the cached buffers. To disable the cache, set compilation-find-file-cache to a non-list value (e.g. 'disable).

After loading this file, every file that is loaded by calling some compile function, i.e. compile-goto-error, is cached if it is not in emacs already. I.e. when you fix some small errors in other files, you may not want to keep those files in emacs after you've done; remember, those got loaded during the calls to compile-goto-error. The easiest way to get rid of these extra files, that were not originally in emacs, is to:

      A. kill compilation buffer, C-x k *compilation*
      B. Call M-x tinycache-flush directly    

See igrep.el also how you can browse (grep) files easily and when you've done, you can call this package top get rid of those browsed files.

Cache minor mode indication – Controlling the cache flag

Mode line indication shows for loaded buffer

      "+C"    if file is loaded as cached.
      "+c"    If you have manually turned off the cache    

And for root buffer where the file were loaded, normally compilation or dired buffer, the mode line shows

      "+CN"  where N is number of files currently in the cache    

Sometimes you want to keep some file that belongs to the cache and you don't want to loose it when you execute M-x tinycache-flush or when you kill the root buffer.

For that purpose there is function tinycache-mode to turn off the cache for current buffer. When the cache mark says "+c" in the mode line, it tells you that the file will not be killed when you tinycache-flush is called.

Note: the root buffer's xx count is not updated when you kill buffer that was cached. So if the count says 10, and you kill 3 files that, the count will still still say 10. The count is updated only when you load some new file from the root buffer. At that time all the buffers cached are checked and the ones that do not exist any more are removed.

Buffer list commands

There are some additional commands added to buffer list which helps you to keep track of the cached files better. The "c" prefix is chosen for (c)ache related commands.

      C-c c m     mark all cached files
      C-c c d     mark as deleted
      C-c c u     unmark cached files.    

Dired mode commands

Similar to buffer list, there is some dired commands too

      C-c c k     tinycache-flush, remove all cached files from this dired
      C-c c m     tinycache-dired-mark
      C-c c u     tinycache-dired-unmark    

Thanks

Kevin Rodgers, his igrep.el gave me an idea for this. The original cache code from where this package evolved was written by Kevin under name compile-cache.el


Tinychist.el --- Command history save/restore utility

Preface, apr 1996

In newsgroup post to gnu.emacs.help there was discussion about saving and restoring emacs command history between session. Fred G. Athearn fga@maple.sover.net sent a help message to a person asking for it describing how to print out command-history and saving it into a file with C-x C-w. This little package tries to automate everything, so that when you load it, it will automatically load command history for the right emacs and when you exit emacs, the command history is saved to disk.

Overview of features

Default save file from -name parameter

The default save name of command history file is extracted from the frame parameter. It is quite customary that people have several emacs open in their X display, each one dedicated to specific task.

The key here is, that you should make a habit of naming your emacs by task when you start it:

      % emacs -name Mail &        # My mail emacs
      % emacs -name C++1 &        # My C++ project 1
      % emacs -name News          # for news reading    

This effectively sets the frame's name to "-name" parameter's value. But old emacs versions are a little picky about the order of command line options, please look at the info pages in which order you must specify additional arguments. (info pages, Node:Initial Options) For non-windowed environment, this trick doesn't quite work out of the box, because emacs doesn't accept the name option at all. Let's try to start fresh emacs to an xterm, not to separate frame and see what happens. Order of the options is important here.

      % emacs -nw -q -name Mail  &    

What happens, is that you get two new buffers: "-name" and "Mail", and this is not what we intended. If we ask the frame name in this emacs, it says "terminal" or something similar. What we do instead, is ,that we install our own command line handler in non-windowed emacs and then we're able to intercept the "-name" option and it's parameter. When the emacs is killed, we then again look at the cached "-name" option to derive the save file postfix. If you're interested in adding your own command line option, see function ti::add-command-line-arg in tinylibm.el

How it works

Your emacs must support kill-emacs-hook, so that the command


Tinycomment.el --- Smart comment setting utility

Preface, Sep 1994

In 1994-10-18 Era Eriksson wrote in gnu.emacs.help that he didn't like 'modes' because they redefined his tab key strangely. What he wanted was tab 8 in _every possible case_. He wrote: "..if mode messes with tab key, I don't want it". He also wanted his comments always to be positioned at column 56 (tab #7). The problem was that how he could he add comments with tab key, when the mode occied it already. He also always used to program using fundamental-mode; what a cool dude. As a result this package was born. The original lisp file sent to Era was posted under name general-comment.el.

What's this all about, short introduction

Let's see...You're in C/C++ mode, and want to switch to better mode before starting to adjust comments. But wait, the new mode doesn't know about C++-comments! Or if you're editing ~/.Xdefauls, there is no mode for it (at the time of writing), no-one to know the comment syntax. Boom. Now it's time to give this packet a run. It hooks itself directly to \M-; replacing any previous function. The packages defines comment syntax and position on the fly when it can identify the file name. If the file isn't known then it passes control to mode to handle the commenting. This is handy in temporary buffers that do not have filename: e.g. scratch buffer. Repetitive calls to M-; shift between comment classes: comment is adjusted according to previous one, or move it on the line.

Overview of features

Limitations

This isn't designed for modes that have comment-end, you get only '/* */' string e.g. in C-mode and no comment class shifting.

Examples

At the end of file there is simple general editing mode, which can be used for perl, shells, awk, C++ [sometimes]


Tinycompile.el --- Compile buffer additions. Minor mode.

Preface, mar 1997

When I was doing grepping over multiple files with igrep.el the results that were inserted into buffer were too long: There were 2-6 directory paths which occupied 40 characters and the actual grep hits were continued with \ character to the right. That was awfull to read. I couldn't get clear look at the grep results. I decided that there must be a way to clarify the results somehow, so I started writing this package.

Overview of features


Tinydesk.el --- Save and restore files between Emacs sessions

Preface, feb 1995

At work working with windowed system, Emacs stays open from day to day. In fact people seldom even logout, so Emacs and the files just wait there nicely and there is seldom a need for a sophisticated session saver.

But sometimes sometimes it may be necessary to visit lab next floor to see what's troubling a C++ program. There has to be a way to transfer the list of files that was being editing and bring them into lab where person can replicate the setup.

These functions save Emacs configuration into file, which can later be opened again in Emacs somewhere else. Later Emacs versions introduced "~/.saves*" files that you may find disturbing occupying your home directory with many files. With this package all the files are grouped in only one "state" state file, which can be reused.

Hopefully someone finds use for this also, although there exist much more better desktop savers, which save points, marks and modes.

Overview of features

      --  load single file on the line
      --  clear face properties from buffer, so that they don't
          disturb your view.
      --  parse files for loading.
      --  Show files that cannot be loaded.    

Quick start

If you're just eager to use the package, here are the basics. I suppose you have copied the installation setup as is.

Now, it all depends what you want to do after that. If you find more files to Emacs; or kill some unwanted buffers, you can re-execute C-x 4 s whenever you like. You can even edit the state file with C-x 4 e to remove some files that you don't want to include to that "project".

If you want to switch between projects; unload first the current project with C-x 4 u "state.c" and reload some other project with C-x 4 r, eg your current C++ project "state.cc"

Automatic one time session saver

Some people just want to save the session on exit and reopen it when Emacs starts again. I must say that this is not necessarily the best, because when you start Emacs for some quick job, you don't necessarily want it to load the saved session (loading all files take time considerably). Loading Emacs with -q is not the choice, if you still like to have your other Emacs goodies active.

Here is semi-automatic save and restore, put all these lines near the end of your $HOME/.emacs. The setup saves the state when Emacs exists and asks if you want to return to saved session on Emacs startup. (You did also copy the installation lines too...)

      (defconst tinydesk-:directory-location "~/elisp/config")

      (defconst my-tinydesk-session
        (concat tinydesk-:directory-location "/state.last-session"))

      (add-hook 'kill-emacs-hook 'my-save-session)

      (defun my-save-session ()
        "Save loaded files to state file."
        ;;  if you want to save dired buffers too.
        ;;  use (tinydesk-save-state my-tinydesk-session '(4))
        (tinydesk-save-state my-tinydesk-session) nil)

      (if (and (file-exists-p my-tinydesk-session)
               (y-or-n-p "Recover session "))
          (tinydesk-recover-state my-tinydesk-session))    

Face setup

This program uses some faces to catch your attention when you're working with the state files. I you restore state from a file and some file reference cannot be loaded, the state file will be shown to you and the problematic lines are highlighted. If you open the state file for editing, you can selectively load files. The mouse pointer will change and the text is again highlighted. To make the highlight work for you, you must set some colors like this

(set-face-foreground 'italic "LightBlue")

About saving the files

While you may save your session files with any name, here is one convention that you could use. Name every filename so, that they have common prefix:

      M-x tinydesk-save-state   ;; or any hotkey you have bound this to
      state.XXX    

The XXX describes the name of the state file you just saved. Later on it's easier to use Emacs file name completion capability to load the file you want. If you don't exactly remember what files you saved, or which sessions you have in dir, you just type

      state.[TAB]    

when tinydesk-recover-state ask for filename. Prefix arg to `tinydesk-save-state saves' says to load directories too.

Automatic state file saving

Emacs 19.29+ has feature that makes it possible to recover a session. See bunch of auto-save-list-* variables.

Has it ever happened to you that Emacs crashed mystically when you were in the middle of your daily routines. You had several C++ files open, perl code, text files, RMAIL, ... This package installs tinydesk-auto-save function to write-file-hooks and in regular intervals all your Emacs session files are stored into the state file. After a crash you can easily recover your session by reading the saved state file information with tinydesk-recover-state <FILE>. The name of the file of the latest saved state is in file "periodic"

Development note

There is no plan to duplicate desktop.el functionality to save points and modes and so on. This is for simple state restoring only.


Tinydiff.el --- Diff and patch minor mode. Browsing, patching.

Preface, jan 1996

Long ago there was set of simple functions lying around to generate instant diffs for the file that was being edited, before it was checked in with RCS. At the time vc.el was not in the Emacs distribution. Looking at diffs and using "goto-line" command in other buffer gave an idea to make a separate diff mode. The project turned out to be a bit bigger than just taking simple diff. You may wonder, why would you use this utility over ediff.el? If you like working with "command line" diff interface, then you may want to use this utility over ediff.el. There is a command prompt when various diff options can be manipulated with key bindings. Lik: Change rcsdiff to diff command, copy previous argument etc.

Overview of features

Taking diff

Browsing diff

Sending or saving diff

Patch

Genrating diff – parsing diff

Be in buffer where you have diff file and just turn on the

      M-x tinydiff-mode    

Then take a look at the bindings you have available:

      C-x b    

If you want to generate [rcs]diff for current buffer, call function

      M-x tinydiff-diff-show   (I have bound this to C-z C-d)    

And it generates diff and puts you on tinydiff-mode. X window users and those that have the highlighting capabitities can enjoy more about this mode, because it marks line numbers in buffer with mouse-face. You just click the point to jump to diff position

Taking diffs

The main purpose of this module is to help you taking "diff shots", inside emacs. This means that the file must be loaded into emacs and your cursor must be in the buffers, before you execute

      M-x tinydiff-diff-show    

Command prompt

The help key is on ?, press it to get summary of command while you're in minibuffer prompt. The command prompt in minibuffer looks like this for rcs controlled file.

      > cd /users/foo/dir1/dir2; rcsdiff -c -r1.21 test.txt    

You can edit this command as much as you like, but please leave cd XXX alone because the minibuffer commands expect it it be present. The hotkey command won't work without it.

Command prompt: rcsdiff and diff toggle

To conveniently construct diff command against another file, say test2.txt, you can hit key C-z to chage the prompt immediately to

      > cd /users/foo/dir1/dir2; diff -c test.txt    

And add the test2.txt to the end of line. If you want to restore the previous rcsdiff form, just hit C-z again. This C-z facility works only if the initial command was rcsdiff. There is no point of converting initial diff command to rcsdiff command though.

Command prompt: tab completes file name

While your're editing the command you can also use the TAB key to complete filename in the 'cd' command directory. If you specify any directories for the file, the directory's files are completed. That feature should allow you to get filenames into the prompt easily.

Command prompt: diffing between two Rcs revisions

There is also more commands, like C-r which changes

      > cd /users/foo/dir1/dir2; rcsdiff -c -r1.21 test.txt    

prompt so that it has now two -r commands. You can take diffs between two versions easily with it. The C-r key is a toggle.

      > cd /users/foo/dir1/dir2; rcsdiff -c -r1.21 -r1.21 test.txt    

Case study:

You see nice package on the net. You download it ;; and notice that it needs some fixes. You put the original version ;; to your private rcstree with the same version number as what ;; the package had; say 2.2. Then you CheckOut the original, make ;; changes, and put it back to tree with version 2.2.1.1. You dont't ;; put it back with 2.3, because that's not your file. You made the ;; correction to 2.2, so you must make a branch.

Okay. You have the original 2.2 and you have the fixed version 2.2.1.1 and you want to send the diff to the author. Here is how you do it

And hit enter. Then you get clean diff that you can send to author. And when he responds back or sends you new version, say 2.5, you repeat the whole process again if you intend to make more changes 8put original 2.5 on ice and make branch 2.5.1.1 for your changes)

Command prompt: autosave and backup file diff

Other helpfull commands insert he #autosaved# and backup~ filenames into the current point. Remember to put the # or ~ file to the left and not to the right. you do want to diff current file against the saved one; right? The first one is original prompt. That second is after C-r and latter after C-v

      > cd /users/foo/dir1/dir2; diff -c test.txt
                                        * point here

      > cd /users/foo/dir1/dir2; diff -c #test.txt# test.txt
      > cd /users/foo/dir1/dir2; diff -c ~/backup/test.txt~ test.txt    

Notice that your backup file may not reside int he same directory. The backupfilename is returned by function make-backup-file.

Generated diff: the Prereq tag

It is important that when you send diff, it is diff between two rcs versions if possible (if you're author of program). In those cases where revision information can be found, the diff data is preceeded with this line:

      Prereq: N.NN        e.g. Prereq: 1.76    

If the receiving end has GNU patch, the patch program first checks if the version that person has is exactly N.NN and aborts if he had some other version. This prevent applying diffs that are meant to other versions. Regular Unix patch program does not notice the Prereq: tag, so consider getting more safer GNU version as soon as possible.

Patching

There is also included little patching function.

      M-x tinydiff-patch          non verbose
      C-u M-x tinydiff-patch      verbose    

For elisp (.el) files the load-path is automatically searched for possible destination of the patch. You can set variable

      tinydiff-:patch-list    

To match files and their associated patch directories if you receive patches for other files regularly. This function is most useful for RCS diffs, because they can be easily detected and the file information is also included in the diff.

Patch: general notes

Note: normally when patch program is called it always makes backup with the suffix .orig. So if you have applied a patch, then there is two file in the directory.

      FILE.txt        -- patched file
      FILE.txt.orig   -- original file, before the patch    

It also creates rejections file if all dind't go as planned.

      FILE.txt.rej    

Patch: success or failure

When the patch has been applied, This package checks if all went well. If rejection file was created; then the patch process's output is shown and the rejection file is loaded so that you can see what possibly went wrong and if you should be concerned.

If you get this rejection file, then there propably is potential trouble. Please contact the sender of patch immediately and tell about your troubles. There are few common reasons why patch failure happened.

Patch: what happens after success

When the patch succeeds, there is a bit special handling for Emacs elisp packages. Say we recieve correction to the following module and you have it loaded in emacs: (feature 'foo) returns true.

      foo.el    

After patch is applied, you're asked if you want to reload the new release of foo module (just patched). You should answer Yes to get the newest one running in your Emacs immediately.

Patch: after success, returning to original version

If the patched version, which is usually new version of the progrmam doesn't work as it is supposed to, you can go back to the original version by appluing the same patch again. You should report what problems you had to the maintainer and inform that you wnet back to previous version.

IMPORTANT If you did get the rejection file, you can't use that patch to go back to original!! See next chapter how to go to original version in that case

Patch: rejection file created – what to do?

If you want to go back to original version, apply the same diff again; this reverses just applied patch. Just call M-x tinydiff-patch in the buffer where you have the diff.

When you do that, the function detects that there is already a orig file and prompts you to choose an appropriate action.
Here is the explanation what they do and what should you choose

Command o

Go back to (o)riginal. This copies the FILE.txt.orig over the FILE.txt and deletes FILE.txt.orig and doesn't do anything else (stops the patching process). You're back to starting point as if you never patched anything.

Command r

®etry means that the FILE.txt.orig is copied over FILE.txt and the pach is tried again for FILE.txt. You may have asked the author to send more context with using the -C10 switch and after you received this new patch you want to try if it now goes ok. The FILE.txt.orig still remains as a backup

Command g

(G)o says that we should apply the diff again to FILE.txt. Do this only if you did not get rejections last time. The intention is that you apply the patch again, and this reverses the situation. I mean 1) you patch; you get new version 2) you patch again: you degrade to the version before patch (original file before patch)

Development note

There is ediff.el, which is much more complete package than this is. The aim was to develop a simple but handy package for everyday diff'ing and easy package patching.

Bugs

The "f" key, which shows the function identifier in diff browse mode tinydiff-mode, can handle buffers which are narrowed, but if the buffer is using folding.el or similar package where goto-line does not work properly, the returned message shown to user is not correct.

Please unfold the buffer and you get the correct result.

Example

This hook setup turns on the view mode for easy scrolling of buffer.

      (add-hook 'tinydiff-:diff-hook  'my-tinydiff-diff-hook)

      (defun my-tinydiff-diff-hook ()
        "Turn on view-mode in diff buffer."
        ;; See tinydiff-:diff-buffer.
        (view-mode 1))    

Sending good bug reports

If you find anything funny happening in the command line prompt while you use the tdi minibuffer commands. Immediately do following.


Tinydired.el --- Dired enchancements. Backgroud Ange ftp support

Preface, Jan 1996

This package started evolving, when there was need for something more from ange-ftp, like background file loading. Ange-ftp also had nasty habbit of putting user to just downloaded .zip or .tar.gz buffer. That not what was usually wanted, but to download the files somewhere other than inside emacs. There was need for ability to mark files for download and get them all at once to a download directory. With standard ange-ftp you would have to load them one by one. Sometimes you may want to go associated ange-ftp buffer and give commands directly there, so a command to switch between ange-ftp and dired buffers would be handy.

Now you can do this with standard ange-ftp and Emacs dired.

Note: This paskage is just extension to ange-ftp, consider getting next generation ange-ftp, the EFS, if you want overall better and more complete interface. Use this package if you only need features like batch put/get at backround. (Further note: EFS was later installed to XEmacs and it does not work any more with Emacs.)

Overview of features

Vax dired listing note

When you connect to a VAX host; you may get some error message and you don't see the dired listing; don't panic. Just repeat the C-xC-f command with

      C-x ESC ESC    

And it should succeed second time. There are quirks in the VAX handling and if you run into it; the usual cure is:

      Kill the VAX ange-ftp process buffer    

XEmacs note

The dired and ange-ftp implementation (nowadays efs) is completely differen than in Emacs

** THIS PACKAGE IS FOR Emacs ONLY **

General dired additions

In simplest form. This module installs some functions in your dired hooks. Their purpose is

It also changes one dired function with defadvice, so that you can control if you want to have only one dired buffer when ascending to another directory. See variable:

      tinydired-:use-only-one-buffer-flag    

Dired and ange-ftp additions

When you want to start ftp session in emacs you just do

      C-x C-f /login@site:/dir/dir/file    

Let's take an example: To see what new things has arrived to GNU site, you'd do this:

      C-x C-f /ftp@prep.ai.mit.edu:/pub/gnu/    

After that you are put into the dired listing, where you can mark files with dired-mark command

      m           Mark file    

Now you have files ready. Next put files into batch STORAGE. There is "a" prefix for ange-ftp related commands.

      a S         Big S put selected files into storage
      a q         To check what files you have batched
      a c         To clear the batch storage    

Now start ftp'ding the files in background. You're prompted for the download directory.

      a g         Get marked file(s)    

If you want to operate on the associated ftp buffer directly, there is command

      a b         For "buffer change"    

that puts you into ftp, where the dired buffer refers. When you're in the ftp buffer you have some keybinding available.

      C-c f       insert stored files on the line
      C-c d       insert directory name
      C-c b       back to dired window    

It's sometimes handy that you can give direct ftp commands.

Setting up ange ftp

Here is my settings, which you can use as a reference so that you get the ange running. For more details, see the ange-ftp.el's source code. These settings include firewall "ftpgw.poboxes.com" ;; (setq ange-ftp-generate-anonymous-password t) (setq ange-ftp-dumb-unix-host-regexp "tntpc") ;PC hosts (setq ange-ftp-gateway-host "ftpgw.poboxes.com") (setq ange-ftp-smart-gateway t) (setq ange-ftp-local-host-regexp "\\.myhost\\.\\(com|fi\\)|^[^.]*$") ;; Always use binary (setq ange-ftp-binary-file-name-regexp ".") (autoload 'ange-ftp-set-passwd "ange-ftp" t t) (setq ange-ftp-generate-anonymous-password "jdoe@example.com")

How to use this module 3 – special vc

There are some extra commands that you may take a look at. See source code of bind function

      tinydired-default-other-bindings    

What additional commands you get when loading this module.

The VC special commands were programmed, because I felt that the C-x v v in dired mode didn't quite do what I wanted. I wanted simple ci/co/revert commands for files that were in VC control. And I wanted to handle them individually, expecially when ci'ing. (written for Emacs 19.28).

This VC part of the package is highly experimental. I'm not sure if I support it in further releases.

Important ange-ftp interface note

The ange ftp batch interface used here may cause unpredictable problems. Sometimes the get or put process doesn't start at all although you see message saying it started the job. I have had several occurrances where lcd cmd succeeded, but then nothing happened. Repeating the put or get command cleared the problem whatever it was.

So, never trust the message completed, unless you saw that the download percentage count started running. If you're downloading important file, double check the real ftp buffer for correct response. Try again if ftp wasn't started. Another way to clear the problem: kill the ange ftp buffer and try the command from dired again. It automatically opens session to the site.

Advertise – other useful packages

There are exellent dired extensions around, please consider getting these packages:

Note: Slow autoload

When you have added the autoloads into your .emacs, the first time you bring up dired buffer may be quite slow. This is normal, Emacs just need to load some additional files that this package uses.

Note: Refreshing the view takes long time / point isn't exatly the same

This is normal, dired is just slow and program has to do lot of work to maintain the "view". Eg. save view, save marks, delete marks, revert, sort, restore marks... Only the current line position is preserved where user was, not point.

Note: Code

Emacs ships with package dired-x.el, which seems to offer some more goodies to dired. Currently, if the dired-x is detected the appropriate functions in this package are diabled, to prevent overlapping behavior. However, if the function behaves differently than the one in some dired extension package, then the function isn't disabled. Eg. see tinydired-load-all-marked-files, which can turn off marks.

Note: limited vax directory support

You can connect to VAX host with find-file and this package provides modified functions to allow you to use f in dired and load file into Emacs. Any other TinyDired commands are disabled in dired vax buffer. Don't try anything fancy there, you know that it isn't unix ls buffer.

See function tinydired-remove-bindings. You must add your own keyboard disable function if you have added tdd functions to other bindings than the default to disable this package in VAX buffers. Add your disable funcion to

      tinydired-:readin-hook    

Note: limited dos directory support

You can connect PC hosts that print 'dir' into the dired buffer. Your only command available is `f, just like in vax dired, so please don't even try any other choices.

The PC support is experimental and is based on unix --> LAN connected PC which is running pctcp software: Win 3.11 (workgroup) ctlapp.exe ftp server. Do not mail me about PC support, since I won't fix it if it doesn't work. Get efs distribution if you need PC ftp support.


Tinyeat.el --- Eat blocks of text at point, forward and backward

Preface, overview of features

Non-windowed and Windowed Emacs

This package works best in windowed Emacs, because in windowed environment you can use the modifiers Control, Alt and Meta freely with other keys. The idea of this package is to overload your single key, backspace, as much as possible with various delete functionalities.

In non-windowed Emacs there is no key named backspace, so standard Emacs bindings are bound instead. Many of this package's features are also unused because there are no suitable keys to bind the commands to. In non-windowed Emacs the extra bindings have been marked with (*):

                      was                 now
      -------------------------------------------------------------
      Meta s          <none>              tinyeat-backward-preserve (*)
      Meta d          kill-word           tinyeat-forward-preserve  (*)
      Meta SPC        just-one-space      tinyeat-delete-whole-word (*)
      Meta k          kill-sentence       tinyeat-delete-paragraph  (*)
      Meta C-d        down-list           tinyeat-kill-line-back    (*)
      Meta ESC        mark-defun          tinyeat-erase-buffer
      Meta C-y        <none>              tinyeat-yank-overwrite    

Story behind this package

One day the developer got frustrated of moving cursor around the point and using keys del or backspace to write C++ and LISP symbols. The start situation was:

      (defun lisp-symbol-name-myname          ()
                              *    

He decided to change 'myname' to something else. Normally he would reach out for ESC-d for kill-word to delete myname and type the new name:

      (defun lisp-symbol-name-mynew           ()
                                   *    

Next, he noticed that there were extra spaces involved. A call to fixup-whitespace would make it go away ... Hmm that was not bound to any key by default (in this particular Emacs he was using at the time), so he had to type it the long way round: M-x fixup-whitespace. His thoughts were: "Oh, why I hadn't I bound it to some easily reacheable key". The story continues. He looked at the function once more and decided that name symbol-name-mynew wasn't a good one after all. He decided to delete 3 words backward. Now, how do you do that?

      (defun lisp-symbol-name-mynew ()
                                   *    

He murmurs, "where is the command to delete backward ...". After spending valuable minutes to find the delete-backward-word command with the emacs M-x apropos and hitting the page up and down keys to find anything that would look like what he wanted, he sits back with despair, "Rats again, there is no such command". Silently he ends up tapping the backspace until he reaches correct point:

      (defun lisp- ()
                  *    

and starts typing a new name...

      (defun lisp-my-func ()    

All is perfect for a moment. Then, he notices that there are too many newlines above the newly created function and says to himself: "I really should delete those 5 extra empty lines above the function. Now, how do I kill backward 5 empty lines backward? The kill-line in C-k kills only forward" ...". The story teller rests here to leave your imagination to continue.

Lesson learned

As you can notice, people often spend most of the time to position the cursor to the right spot and deleting text over there.. over here .. typing more .. changing our mind ... and so on.

It was time to do something creative, so that user wouldn't have to worry about the deletion of text so much. This package provides atempts to provide smart deleting capabilities: whether you want to delete forward of backward. Naturally it isn't capable of miracles, it just does few guesses, and a guess may be wrong. If it so happens that a lot of text have suddenly retired (vanished, vaporized) from you buffer, remember, there is no need to panic. Just send a bug report to that poor maintainer, and hit undo.

The maintainer would be surprised if you ever wanted to discard this package after you have tried it. Can he expect a happy smile at this point? Now, load this and be happy, spread the word and help others to get "the job done", whatever you were doing.

Default keybindings

chunk delete: words, spaces, symbols ...

      <<              >>                  <<>> [Delete whole word]
      Alt-Backspace   Control-backspace   Shift-Backspace    

Line delete

      <<              >>                  <<>> [zap whole line]
      Alt-Backspace   Control-k (Alt-k)   Control-k
      + Shift                             + Alt    

Buffer delete

      \/              /\                  \//\             ZAP
      untill pmax     untill pmin         Paragraph delete Whole buffer
      C-A-backspace   C-A-Backspace       C-S-backspace    Esc-Backspace
                      + Shift    

Joining next line to the end of current line: Esc Control-backspace

[Some minibuffer hotkeys]

      f1  = Kill whole line.
      f2  = Delete line backward (to the left)    

[Mouse binding]

      (Alt|meta)-Mouse-2 overwries text when pasting.    

Known Bugs

This package heavily relies on various modifiers that can be attached to the BACKSPACE key and that is a difficult subject in Unix. For example the Alt keys usually does not exist and to make it work, yu have to introduce yourself to xmodmap(1) or keycaps(1) and possibly xev(1) in order to find the key symbols correctly.

Worse, In the same Unix the Emacs and XEmacs diagree what a simple key sequence

      BACKSPACE    

Means. Or with various modifiers. To get some taste, here is what XEmacs 20.4 and Emacs 20.3 in Redhat Linux 6.2 return:

                          XEmacs          Emacs

      <esc backspace>     M-backspace     ESC DEL
      <shift backspace>   delete          S-delete
      <alt backspace>     <nothing>       <nothing>    

There is nothing this package can do to cope with these changes in key symbols or the environemtn you use. If you can, try to get the ALT key working and shift-modifier for backspace and everything is well. If that is not possible, the power of the predefined keybindings are mostly left unused and you have to look at the install function and determine how woulf you use your keyboard best with these functions.


Tinyef.el --- (E)lectric (f)ile minor mode. Easy C-x C-f filename composing

Preface, Apr 1995

There was a post in gnu.emacs.sources where Anders Lindgren andersl@csd.uu.se presented the basic code that allowed electric ~ and electric / characters to wipe out full (mini)buffer in certain cases. What you see here, is complete rewrite and enchancement of that code. This is a real must for any minibuffer file handling.

Overview of features

Description

This ins only slightly electric, in a sense that it only defines some keys to be electric and it needs some other keys solely to its own use (you can't insert these chars to buffer without C-q CHAR) If you're another non-english speaking, as I am, the electric means that the character you press behaves differently if the pressing happens around certain other charcters (some condition is met which triggers this other behavior). Other than that, the character behaves normally. Below there is a sample graph to give you an overview of what the so called "electricity" is is practice. In these presented cases cursor it at the end of line. Jusr load this file, press C-x C-f and experiment with keys "[]\/~".

      b> http:/www.site.com/~userFoo/dir1/dir2/dir3/ "/" [e-slash]
      a> http:/
      The e-slash action wiped out the line, because writing
      two slashes normally indicates, that you want to give
      another path

      b> ~/dir1/dir2/dir3/                       "~" [e-tilde]
      a> ~
      The action wiped the line away, because it assumed
      you want to give "~userFoo" or another "~" relative path

      b> ~/dir1/dir2/dir3/                       "[" [step-delete-back]
      a> ~/dir1/dir2/
      The action wiped previous directory name or until
      special mark, See code, defaults are  ":/@" (ange-ftp things)

      b> ~/dir1/dir2/                            "=" [undo]
      a> ~/dir1/dir2/dir3/
      The action works like normal undo.

      b> ~/dir1/dir2/                            "`" [chunk-delete]
      a>
      The action deleted whole line. It deletes until special marks
      like "@:". If repeated, it deletes constantly backward    

Automatic Isntallation

This file includes function tinyef-install which hooks the mode to the appropriate places. Eg. to your minibuffer. If you're in trouble, you can always turn this mode off with the supplied hotkey, which is by default C-c /. You can't "see" whether mode is on or off in minibuffer, since it doesn't have its own mode line. But calling the hotkey will tell you the state change. You can also remove this mode completely from your emacs if you need to do that in emergencies. just call following function with some prefix argument like C-u to tinyef-install

Mouse bindings in minibuffer

When this package loads, it calls function tinyef-install-mouse which defined following bindings to your minibuffer

      <-- BIG erase backward from point Mouse-3 (because it's free)
      <-- Small delete backward C-mouse-1. Use C-mouse-3 to undo( -->)    

This should give your free hands to cut,paste and Delete, without lifting your hand off the mouse.


Tinygnus.el --- Gnus Plug-in. Additional functions. UBE fight etc.

Preface, Sep 1997

I haven't have a chance to try the new Gnus for a long time because the envinronment didn't have Emacs 19.34. And when the sysadm installed it, I started slowly moving from my dear RMAIL (which I had configured to work very well) to the bold and beatiful Gnus. I had also started using procmail and subscribed to many mailing lists, so the only choice to manage all my mail was Gnus. Here you find some functions that I found useful.

Overview of features

Url pointers

Fighting against UBE messages

Please visit http://spam.abuse.net/ for up to date information. Other good sites: http://spamcop.net/ and http://www.spamcop.com/

[2000-11] Automatically generated Gnus blacklist by Brian Edmonds is at http://www.gweep.bc.ca/~edmonds/usenet/index.html

Many of us receive UBE (Unsolicited Bulk Email) and if we don't do anything to stop them, then the practice comes approved de facto internet convention. It is important that you complaint about every piece of UBE you may receive, your vote counts and it will also give you satisfaction to know that most of the postmasters kick off the idiot in the other end of the wire. There are two functions in this module:

      tinygnus-article-ube-send-to-postmasters    U      UBE
      tinygnus-summary-ube-send-to-postmasters    C-c'u  send UBE    

The first function is fully interactive and it reads the current active article and composes forward message to all postmasters mentioned in the received header chain. Before sending you have a chance to reformat the article anyway you like.

The latter function is useful to batch send complaints: you process mark(#) articles in summary buffer, Hit C-c'u, and each article is processes and complaint is sent to postmasters. Before sending message, the function asks confirmation. You can suppress the confirmation with C-u prefix argument. Note: It may take some time to compose all complaints if you have marked many articles, because parsing Received: headers and checking them with nslookup may be slow. If you use procmail or Gnus split methods to flter your UBE mail to one single newsgroup, say junk.ube, Then you can mark all messages in the newsgroup and handle all the UBE you have received in a whip.

Why is the complaint message sent to postmaster address, while recent sites have set up an abuse addresses as well? That's simply because RFC822 requires that each site must have postmaster account and you should be able to count on delivery to that address.

[RFC822] (...) standard specifies a single, reserved mailbox address (local-part) which is to be valid at each site. Mail sent to that address is to be routed to a person responsible for the site's mail system or to a person with responsibility for general site operation. The name of the reserved local-part address is: Postmaster

From the standard, "postmaster@domain" is required to be valid. Some domains have opened specific addresses where you can send these complains, e.g. abuse@aol.com, fraud@uu.net. If you know a specific address where to send the complaint, update tinygnus-:ube-abuse-account-table

Gathering information from articles (e.g. URLs)

If you read group that has very high traffic, and don't have to time to read all articles, but you're are still interested in seeing if there are any good urls mentioned, you can use function below. It will not record duplicate urls, only unique ones.

      C-c ' g u       tinygnus-summary-gather-urls    

Function steps through all marked articles (Mark command in summary buffer is in M P submap), examines each message and puts the urls in tinygnus-:output-buffer. You can clear and display with commands:

      C-c ' g d       tinygnus-summary-gather-display
      C-c ' g c       tinygnus-summary-gather-clear    

Configuring the user format functions

Before you load this file, it might be good to configure variable tinygnus-:uff-table so that it won't clash the definitions of your own gnus-user-format-function-X. If you load this file without modifying the table, it will replace all existing functions according to that table. In case you don't know what this is all about, go to Emacs info pages C-h i, go to Gnus node, press 's' to search for 'Summary Buffer Lines' RET. Look at the specifier %uX, where X is anything.

Miscellaneous commands

tinygnus-make-group-from-dir-nndoc can be used to generate all nndoc groups fast from bunch of mailboxes that you dropped to some directory. You might have downloaded archives of mailing lists sorted by month and year and you want to genrate Gnus groups for them. This is it.

Nnml handling commands

TinyGnus is mainly designed for nnml backend. Gnus can be easily used for mailing lists; Gnus customisations; moving groups from one place to another. In TinyGnus there are some exotic functions that may prove handy when you have the same need. See below.

tinygnus-make-group-nnml-from-dir. If you have nnml groups in ~/Mail; this function can create the equivalent nnml groups to your gnus easily. Give a REGEXP to match directories to include for group creation (E.g. "list\." for all mailing list list.* directories)

tinygnus-make-group-from-dir-nnml-procmail-spool. A procmail (never mind if you don't know what that is); is a tool to deliver each incoming mail to correct mailbox as it arrives and it is very efective for filtering mailing lists. Procmail users have to reserve separate directory for these mailboxes; usually ~/Mail/spool/ and all files end to *.spool ( list.ding.spool, work.lab.spool ... ). Keeping Gnus aware of the mailboxes in the ~/Mail/spool would normally be manual work, but this function can create the nnml groups for you for each found spool file from the directory.

tinygnus-group-parameter-mailing-list. Use this to read the last nnml mail from the directory and suggest an email address from From, To, Cc, Reply-To to be inserted into the group parameter to-list. When you start a fresh Gnus and create nnml groups, which are mailing lists (e.g. from old mail); the tedious part is to recover the "list status" of the group and insert correct to-list field into each group. With This function; just mark the groups where you want to add the parameter and you're set in few minutes.

Enhanced Gnus functions

Enter group in Topic mode with SPC

Function gnus-topic-read-group is enhanced to maximize speed of reading new articles. Normally when you enter Group, gnus shows unread and ticked articles, but if you have any previously ticked articles in group, making the summary buffer is slow. If we ignore the ticked articles and display only the newly arrived, unread, articles, the time to generate Summary buffer is far less. If you have many private mail,work, mailing list groups, this saves you from lot of time to be able to track new messages.

Show dormants immediately in non-nntp groups

Function gnus-summary-limit-children is enhanced so that it will include dormant articles in Summary creation in non-nntp groups. Some people found out that the dormant mark ? is handy in mail groups to mean todo or `see this later' or urgent. Normally gnus treats all groups the same: nntp or private mail makes no difference. However the dormant mark can be used to mean different meaning in nntp group and non-nntp groups and this enchancement does just that. You get fast Summary with dormants now and you don't need to separately limit the buffer to show the dormants. To turn off this feature, set tinygnus-:show-dormants to nil.

Compressed Gnus newsrc files

Having a unix account that has unlimited disk space is very rare and for that reason being able to keep files in compressed format s preferrable to avoid going over Quota with message "Quota limit exceed, remove nnnK withing N days...".

Gnus has compression support for Group files, but not for the bloating .newsrc or .eld files. Gawk. They consume your disk real fast because they become big in no time.

For that reason there is included adviced Gnus code that automatically starts using compressed startup files if your gnus-init-file has extension .gz. Changing from normal init file to compressed one is easy:

  1. gzip your .newsrc and .eld files
  2. (setq tinygnus-:z ".gz")
  3. M-x load-library RET tinygnus RET

If you later want to restore this settings: Unzip, do (setq tinygnus-:z nil), and reload the package. But if you're low of quota, you propably do the reverse operation.

Gnus version note

This file installs only features to Gnus 5.8.2 (Emacs 20.5) and if you're using newer gnus version the advice code is not activated. Using this package should be safe with any existing Gnus version later than 5.8.2

Line format example for *Group* buffer

The personal Group buffer line can be configured as follows. If you try this with very old Gnus, drop away that fancy ~(cut 6) and use plain %d.

      (setq gnus-topic-line-format "%i%(%{%n%}%) %A -- %g %v\n")

      (add-hook 'gnus-select-group-hook   'gnus-group-set-timestamp)

      (setq gnus-group-line-format
          "%M%S%p%3uZ[%L]%-4uE%uT %5y: %-40,40g %7,7~(cut 6)d %uC\n")    

Which looks like the following in the buffer, notice that the topic mode is on.

      Procmail 34 -- 9
        [2]3.g       0: nnml:list.ding        30T1810
        [2]3.        0: nnml:list.ntemacs     30T1819
      * [2]3.  !     0: nnml:list.procmail    30T1850
        [2]2.t      33: nnml:list.flamenco    30T1849
         | |   |                              %d
         | |   %uT
         | The whole "2.t" comes from %uE
         %L    

There you can see the benefit of the user functions. The [2] tells the group level, "2.t" says "2" day total Expiry, "." means that the period is explicitely defined as a group parameter and "t" means that total expiry in the group parameter list is on. Do you see the extra g at the top line? It tells that the gcc-self group parameter is activated in group parameter list. If group has ticked articles, the %uT will show it. The %ud says "Day 30 in the month, Time 18:10" when you read the group.

All these additional functions that display these status informations can be found from this package.

Displaying the group parameter info

As you saw above, the %uE function, or more precisely, tinygnus-uff-group-expiry controls what information is returned by looking at tinygnus-:uff-table. Please configure it to display whatever you want from group parameters.

Article wash functions

If you are interested, you can add following function(s) to the gnus-article-display-hook

Debuging Gnus: can't select group

If something is wrong with the Gnus and you can't enter the group for a reason or another, something has happened to your setup. There is experimental funtions in this package that may shed some help. The first thing to try is calling tinygnus-gnus-debug-investigate-problem Which asks for a group name, give fully qualifies name like "nnml:list.ding". This function is geared towards debugging nnml groups, so you may not benefit a lot for other backends.

Thre is no detailled instructions how to fix the situation after the function has run, but the printed results in tinygnus-:debug-buffer should at least give better clues. LOOK CLOSELY THE RESULTS. And supply them to gnus newsgroup or mailing list. Maybe someone can by looking at the values what's the problem.

Gnus summary minor mode

tinygnus-summary-mode is turned on when summary buffer gets created. There are some keybindings that you may wish to relocate for faster access, e.g. the search functions that repeat the last search. In Gnus, pressing Esc-s to search again would require a confirmation of the search string each time, while using `tinygnus-gnus-summary-search-article-forward uses the supplied string immediatedly. To relocate keys, use this code:

      (defun my-tinygnus-summary-mode-hook ()
        "Define new keybindings."
        (let* ((map tinygnus-:summary-mode-map))
          (define-key map [(alt ?<)]
            'tinygnus-gnus-summary-search-article-forward)
          (define-key map [(control ?<)]
            'tinygnus-gnus-summary-search-article-backward)))

      (add-hook 'tinygnus-summary-mode-hook
                'my-tinygnus-summary-mode-hook)    


Tinyhotlist.el --- Hot-list of important buffers, files(ange-ftp), dired

Preface, may 1995

There is excellent utility 'msb.el', but when it comes to having most important files at hand, It needs some companion with it. An emacs session can easily have 20 C++ files, user may start news while the compile it going on and try some lisp code found from the gnu.emacs.help articles, load couple of emacs configuration files for editing and then realize that there is mail coming, because some biff utility tells so. User switches to mail reader and starts reading the latest messages... within short period of time emacs is full of buffers and to use MSB to navigate through them all may be get one frustrated: "Where was that buffer again, do I need to step 3 panes before I can see that file...?"

The navigation is especially problem if user is working only with handful of source files actively, while he may still have 40+ files loaded.

What would help the situation? A simple hot list for my most used files, where one can put and remove items very easily. No more searching like in msb.el.

This package does not intend to replace msb, it's superb in class of its own, but there may be also need for a hot list, because the most used files page in msb changes dynamically whenever buffers are changed. Hot list in the other hand stays the same from session to session.

Overview of features

How to use the hotlist

When you load this package, it defines hot list cache to store the items. The list will be empty at first, but after you have added an entry to it, you can display the hot list. To add or remove entries from hot list, is explained in function:

      C-h f tinyhotlist-control    

If you use add and remove commands often, it might be useful to to define some custom key bindings. The alternative way is to use prefix arguments to functions tinyhotlist-control

      (global-set-key [(shift f3)]   'tinyhotlist-add)
      (global-set-key [(control f3)] 'tinyhotlist-remove)    

In non-windowed environment hot list is is managed through completion menu. Admittedly, this is not as nice as the pop-up menu., To use keyboard, use function:

      tinyhotlist-control-kbd    

Here is an example of the displayed hot list in pop-up. The second string to the right is abbreviation name of the directory, e.g. ~ftp1 is a short name for /user@site.com:~user/project/this/. The txt is short name for $HOME/doc/txt/

      +-------------------+
      |hotlist            |
      |===================|
      |*Backtrace*        |
      |*VC-log*           |
      |.emacs             |
      |.procmailrc        |
      |ChangeLog          |
      |RMAIL              |
      |file.txt     txt   |
      |other.txt    txt   |
      |remote.cc    ~ftp1 |
      |remote.cc    ~ftp2 |
      +-------------------+    

Note about the pop-up display: The font used in pop-up may not be proportionally spaced, like Courier, so the entries may therefore show as ragged. That is, the directory names are not nicely lined up.

Shortening long filenames

The typical menu item is quite long, because there is buffer name and filename part. The default rule shortens the home directory names to "" but if your file is elsewhere, you have to modify the tinyhotlist-:abbreviate-file-name-table. There is examples how to use it at the end of source file. Like:

      /user@site.com:~user/project/this/  --> ~ftp1    

If you make changes to this variable after the hot list has been made, the new abbreviations will take effect on at creation of new items. To rebuild everything from defaults (this destroys you previous content), call function tinyhotlist-build-default-hotlist.

Hooks: saving hot list after each cache update

The buffers are stored into variable tinyhotlist-:cache and there is two hooks that run after the entry is deleted or added to the cache. The hooks are tinyhotlist-:add-hook and tinyhotlist-:remove-hook. They contain default value tinyhotlist-save-hotlist which updates the cache on disk after each change. You can set these hooks to nil if you want to manually control when to save cache. (Maybe you load BASE cache every time and modify it during Emacs session, but you don't want to save this "session" hot list).

      (add-hook 'tinyhotlist-:load-hook 'my-tinyhotlist-load-hook)

      (defun my-tinyhotlist-load-hook ()
        "My hotlist settings"
        (setq tinyhotlist-save-hotlist nil)
        (setq tinyhotlist-:remove-hook nil))    

Saving and restoring the hot list

When you're satisfied with the hot list, save it to file with command:

        M-x tinyhotlist-save-hotlist    

To automatically restore the hot list when package loads:

      (add-hook 'tinyhotlist-:load-hook 'tinyhotlist-load-hotlist)    

To save the current hot list automatically when Emacs exists:

      (add-hook 'kill-emacs-hook 'tinyhotlist-save-hotlist)    

Example

Here is complete example setup how you could configure this package.

      (autoload  'tinyhotlist-control "tinyhotlist" "" t)
      (ti::add-hooks 'tinyhotlist-:load-hook
           '(tinyhotlist-load-hotlist my-tinyhotlist-init))

      (defun my-tinyhotlist-init ()
        "Sets defaults for hotlist"
        (setq tinyhotlist-:default-function       'my-tinyhotlist-defaults)
        (global-set-key [(control shift mouse-3)] 'tinyhotlist-control))



        (defconst tinyhotlist-:abbreviate-file-name-table
          (list
           ;;   Remember: the substitution order must be _BIGGEST_
           ;;   substitution first.
           ;;
           ;;  Shorten ange ftp references
           (list
           "/foo@example.com:/home/foo"
           "~foo")

           (list txt    "~t")
           (list wtxt   "~wt")
           (list elisp  "")   ;; and wont show this either
           (list h        ""))))   ;; don't display the home

      (defconst tinyhotlist-:default-regexp
        (concat
         "^RMAIL$\\|scratc\\|diff\\|buffer menu\\|diff\\|Messages"

         ;; Procmail
         "\\|procmailrc\\|pm-.*\\(hdr\\|log\\|rc\\|txt\\)"

         ;; text
         "\\|elisp.txt\\|ssjaaa.txt"

         ;; perl
         "\\|\\.pls"

         "\\|.mak"

         ;; emacs project files
         "\\|emacrs\\|funcs.ja.el\\|tinylibm.el\\|tinylib.el"

         ;;  C++ project files
         "\\|wmpmea.*cc"

         ;; Gnus
         "\\|article\\|newsgroup\\|Summary\\|MIME-out"))

        ;; ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ window-system ^ ^
        )    


Tinyigrep.el --- Top level interface to igrep.el

Preface, Dec 1996

Somewhere at Summer 1996 Kevin Rodgers kevinr@ihs.com decided to put together all grep calls to one package named igrep.el: agrep, egrep, fgrep and zgrep. It also could search trees recursively.

The package draw attention and many people picked up the package from the gnu.emacs.sources newsgroup. The default M-x grep command that came with emacs was a pale shadow compared to igrep.el package's possibilities and advanced features. The birth of tinyigrep.el was the need to integrate searches to some common directories or grouped files, like news articles, info pages, project directories, lisp sources, Emacs startup files. A package that would allow so called "databases" (directories to search). igrep.el interface seemed to offer great deal of flebility if you did not have locate(1) or glimpse(1) and their indexes up to date all the time.

Description

Do you need this package?

If you use Emacs "grep" then I suggest you to move to igrep.el and evaluate tinyigrep.el as well. It simplifies your grep tasks much more. Additionally, if you have several directories where you keep some persistent data where you want to do lookup from time to time, then you propably appreciate this package. Package defines all the parameters for you and all you need to to is supply the SEARCH-STRING.

Suggestion

You may find it useful to keep the igrep buffer in a special frame when working in windowed environment. See if you like this:

      (if window-system   ;; Use variable `console-type' in XEmacs
         (setq special-display-buffer-names
           '("*compilation*" "*grep*" "*igrep*")))    

A simple example how to use search database

Suppose you want to search 1) emacs cl*el files 2) all your ~/Mail (recurse into dirs) 3) your ~/News files. The sample database definitions would look like this:

      (require 'tinyigrep)  ;; gives macro `tinyigrep-db-lisp-elt'

      (tinyigrep-db-push-elt
        (tinyigrep-db-lisp-elt
           "cl.el"        ;; Find root based on this file
           "lisp-cl"      ;; the name of search "database"
           "egrep"        ;; Program to do the work (remember zgrep)
           ;;  Grep only cl libraries
           '(list (concat dir "cl*el"))))
      ;;
      ;; Notice '(nil) which turns on recursive search.
      ;;
      (tinyigrep-db-push-elt '("Mail" ("egrep" ("~/Mail/*") (nil))))

      ;; This greps only ~/News/*
      (tinyigrep-db-push-elt '("News" ("egrep" ("~/News/*"))))    

Special database for current file directory

Normally you add databases to variable tinyigrep-:database. There is also a special database whose name is ., which refers to files that are under current buffer's filedirectory. Eg. say you are editing:

      /user/foo/txt/file.txt    

Selecting a special database . will give you a prompt to limit search for files under that directory. You can modify the file pattern as you like:

      Search: /user/foo/txt/*.txt    

You can use this search criteria for successive searches by selection last database.

Selecting igrep command from command menu

When you call TinyIgrep, you get prompted for a database selection, which could be "lisp-cl", "Mail", "News" anything you defined. The igrep interface menu looks like this:

      igrep: i)grep g)uess l)ast time d)ired [c)ase r)ecur u)ser]    

Pess key ? to see more help on the command line interface. You can change igrep.el options listed in [], e.g. key c toggles case sensitivity of the search by adding or removing the -i option for grep, r can be used to toggle recursive mode on or off, and u toggles user switches on and off. The user options are stored to history list tinyigrep-:history-igrep-user-options from where they can be recalled.

List of predefined databases

For your convenience, function tinyigrep-install-default-databases is run from tinyigrep-:load-hook, which defines several databases Here is summary of available default database selections:

Home:

Operating system:

Perl pages:

Emacs and Emacs lisp:

Seach Emacs packages: (there are many more, these are only examples)

In addition to the above, if you have any of these files in the directories along the load-path, you can search those directories recursively. Please create these empty files "to mark" these directories for automatic scanning. In Unix, simple touch(1) command create a file.

A Typical Emacs lisp package installation structure (site wide) might look like this. Create the appropriate dummy files as needed, like creating site-lisp-flag.el to directory /usr/share/site-lisp/

      /usr/share/site-lisp/
                          common/             for Both XEmacs and Emacs
                          emacs               Emacs only packages
                          net/                Net packages
                              cvs-packages/   CVS method
                              packages/       Big packages
                              users/          ftp or http directories
                          xemacs/             XEmacs only packages    

If you want to define a short name for any of these defaults, add additional entry e.g. for "vm". The last parameter could be '(nil) which instead if Žnil' to enable recursive search.

      (tinyigrep-db-push-elt-lisp-package "vm" "vm.el" "grep" nil)    

Here is small piece of lisp code which adds multiple short names (defaults are lisp-*} to the search database:

      (require 'cl)

      (dolist (package '("vm" "gnus" "irchat" "semi-def" "mc" "tinylib"))
          (tinyigrep-db-push-elt-lisp-package
             package (concat package ".el") "egrep"))
      ;; end of code    


Tinyindent.el --- Like indented-text-mode, but minor-mode.

Preface, sep 1994

The original auto-indent-mode from autoindent.el was very short and limited, so I thought I extend it a little...here is the result. Thank you Alan for giving me a push to extend your code into new directions. When I spoke with Alan and he gave me free hands, because he hadn't used the .el for quite a long time.

I wasn't satisfied with the indent-relative function, so I coded a preprocessor for it. Now the cursor won't jump all over the line if the previous one was empty. Just try original M-x indent-relative when there is empty line above and you'll see what I mean.

And where this module really shines: Has it ever been easier to line up variables according to '=' or in within lisp 'let*', or writing mail messages while this mode is turned on...

Overview of features


Tinylib-ad.el --- Library of adviced functions. Backward compatibility

Preface, 1999

This is lisp function library, package itself does nothing. It modifies existing Emacs functions with advice.el in order to provide backward compatibility for functions that have changed. Eg. Emacs 20.4 introduced new parameter NOERR to require command and if you wanted to use a package in lower Emacs that uses this new feature, you would have had to upgrade to 20.4.

There is another way, load this library first and continue using your current Emacs version. This package will redefine functions only when needed, so it should be quite safe.

Code policy

If I have found some useful macro from someone's .el or from news, the proper source and name of author + time is preserved. All the credit goes to those marvellous programmers!

Usage

You must not autoload this package; but always include

      (require 'tinylibm)    

You don't need any other require commands: all my other library functions get defined as well by using autoload. Repeat: you don't have to put these in your packages:

      (require 'tinylib)     ;; leave this out
      (require 'tinyliby)    ;; not needed either.
      (require 'tinylib-ad)  ;; not needed either.    


Tinylib.el --- Library of general functions

Preface, 1995

At some point I started using several functions in program modules I developed over the time, so it was time to move all common parts into general library.

Briefly:

Quick function help

Please use function

      tinyliby.el / ti::y-get-file-documentation    

which will build up a buffer containing all functions/macros and variables used in any lisp package file. You can print the results to get an overview of all functions in this file.

If you feel that some function description is not clear, please drop me a mail. There is no plans for separate info files; that's why I try to keep the function descriptions as good as possible.

Also look at the function

      tinyliby.el / ti::y-describe-symbols    

which will help you to find particular lisp information from the emacs. E.g. to search for function that has "file" in their name.

If you're pacakge write, here is more resources

Here is standard tool set I use for writing/studying/lining up variables for lisp...

      tinybm.el           drawing sections (book marks)
      tinytab.el          tab minor mode
      tinyindent.el       another "line up my vars" minor mode
      lisp-mnt.el         std emacs package use lm-verify
      eldoc.el            show func doc immediately (under cursor)
      tinylisp.el         E.g. find lisp error.    

What is this 'tiny' thing?

The term tiny does not refer to file size, it just happened some that the first released my package was named "tinyappend.el" and the prefix has stayed since.

Code policy

All functions are written by [jari], unless otherwise stated. If there has been interesting function from some other package a reference to the file is preserved. All the credit and and cheers for the original author who wrote so respectable code, that it could be used right from the box! If someone contributes good, general purpose function, all the credit belongs to him automatically. Persons name and date and so on is included.

TinyXXX Libraries' intention

These libraries are by no means private. My wish is that all Lisp developers would contribute their general purpose functions and they would be merged into FSF or other libraries so that the functions would be commonly available.

The biggest problem in the lisp world seems to be compatibility: after every new Emacs release you have to be on your toes if that broke backward compatibility. This is understandable from the Emacs developers point of view: they don't want to carry any old burden with the latest high tech product. But it places other lisp package writes in an awkward situation: if they do have the chance to follow the Emacs development, sooner or later their fine package breaks.

Then comes the issue of Emacs and XEmacs differences and different platforms, now when NT has gained firm grounding.

In order to reuse the code in all my modules and to keep up with the Emacs/XEmacs interface and different releases, the general function has been moved to libraries.

When a new original Emacs function (perhaps after new Emacs release) is found, the old code is moved to (b)backward library. This way a compatibility to the old versions is preserved. Feel free to drop maintainer a note if you know a function that should be used instead of some of these library functions.

Code reliability

Almost all of these functions are in actual use all the time and they have been found to be quite good behaving. This doesn't mean that they don't contain bugs. And if you feel that function should have more parameters or they should behave "more generally", please mail the maintainer. Any suggestions are considered in detail.

The functions are not tested systematically, one by one. Instead, I couple of quick tests were carried out to verify that the function worked expectedly. It may still have bugs, when fed with some other data or used in some other task. Please be patient and send backtrace and the values used and the bug gets fixed as fast as possible. Report bugs immediately, since someone may be using that function without knowing the error.

Turn on you debug

If some function reports an error, immediately turn on debug and repeat your task

      (setq debug-on-error t)
      (setq debug-ignored-errors nil)  ;; Emacs 20.x    

Now when error happened, you get Backtrace buffer displayed. Send the content of the buffer and all variable values that are relevant to call. See 'e' command in backtrace to display values.

Local variable naming in the functions.

following names are common inside functions' 'let' body. However, the coding started long time ago and there was no discipline in variable naming, so there are still functions which do not use the standard local variable naming.

If you think about submitting general code, It would be welcomed if the functions used these variables. Of course it's up to you if you feel naming conventions are waste of time. Still, spend a moment thinking who might be reading your code.

      beg end     begin area, end area [points]
      bf, bfn     buffer file name
      bn          buffer name
      bp          buffer pointer  , sometimes "beginning point"
      buffer      buffer [pointer or name]
      cmd         usually a shell or process command string
      ep          end point -- see bp
      func        variable to store a function symbol
      fid         "function id", name which is used in debug trace
      list        a list
      len         length of object [string, list, array]
      line        current line contents as string
      level       matching subexpression level
      mb me       match end/beginning point or Marker beg/end
      nbr         holding integer
      ob          original buffer [pointer or name]
      p           general point
      pb pe       point: beg, end
      ptr         a list pointer that will be moved.
      [-]re[-]    referring to regexp
      reg         register [integer ie. char]
      ret         return value of a function
      str         string
      verb        flag representing 'vebosity' usually (interactive-p)
      win         a window pointer    

Defining minor mode

If you're eager to define minor mode in 1 minute, then here is one macro that does everything for you. After this you have all the minor mode variables ready and the mode works in both the Emacs and XEmacs including the menus.

      (eval-and-compile   ;; So that defvars and defuns are seen
      (ti::macrof-minor-mode-wizard
       ;;
       ;; 1. prefix for variables and functions
       ;; 2. Modeline name
       ;; 3. prefix key for mode.
       ;; 4. Menu bar name
       ;; 5. <forget this>
       ;;
       "xxx-" " xxxModeline" "\C-cx" "xxxMenubar" nil

       "XXX minor mode. Does fancy things."  ;; mode description
        Defined keys:
        \\{xxx-mode-map}
        "

        "XXX help"    ;; message displayed when user calls mode
        nil           ;; Forms When minor mode is called

       ;; This is used by easy-menu.el and defines menu items.
       (list
        xxx-mode-easymenu-name
        ["Eval whole buffer" xxx-eval-current-buffer    t]
        ..)

       ;;  this block defines keys to the mode. The mode minor map is
       ;;  locally bound to 'map' symbol.
       (progn
         (define-key map "-" 'xxx-eval-current-buffer)
         (define-key map "=" 'xxx-calculate))))    

Defining minor mode step by step

If you want to take more personal control over the minor mode creation, here I explain step by step what macros you need to include in your package to get minor mode created, This takes only half an hour and you have basic minor mode ready. Put all following calls near top of your file. We suppose we're creating XXX-mode.

[1] First, define standard variables for minor mode.

      (ti::macrov-minor-mode "xxxModeline" "\C-cx" "xxxMenubar")    

After that user has following varibles for customization. (for complete list of created variables, see the macro's description)

      ;; Don't like default key combo C-c x
      (setq xxx-mode-prefix-key "\C-cm")

      ;; The default mode string was too long, use shorter.
      (setq xxx-mode-name "xxx")

      ;;  When mode runs, I want to do this.
      (add-hook 'xxx-mode-hook 'my-xxx-settings)

      ;;  I want to add additional keys
      (add-hook 'xxx-mode-define-keys-hook 'my-xxx-keys)    

[2] Next we need installation function, which installs our minor mode so that emacs is aware of it. The minor mode functions, xxx-mode, will call xxx-mode-define-keys-hook which takes care of defining keys to key maps and creating menus with easy-menu.el. The separate installation function is used, because it takes care of emacs specific things and if called with additional argument, it also knows how to remove the mode gracefully.

      (ti::macrof-minor-mode-install
       xxx-install-mode
       xxx-mode
       xxx-mode-map
       xxx-mode-name
       xxx-mode-define-keys-hook)    

[3] Do we have additional files attached to the end of package? If yes, then we need pgp-tar unpack function too.

      (ti::macrof-install-pgp-tar "xxx-install-files"  "xxx.el")    

[4] Finally the user callable minor mode function is created.

      (ti::macrof-minor-mode
       xxx-mode
       "XXX minor mode. Does fancy things."
       Defined keys:
       \\{xxx-:mode-map}
       "
       xxx-install-mode
       xxx-mode
       xxx-mode-name
       xxx-mode-prefix-key
       xxx-mode-easymenu
       nil                        ;Yes, print turn on/off message
       "XXX help"
       xxx-mode-hook)    

That's it. when you execute all these statements you have basic core for emacs minor mode. The only things missing is the actual functions that the minor mode commands uses and the function that defines keys and menus for the minor mode. You probably want to start from the function that defines keys and menus. Here is ready macro for that too.

      (add-hook' xxx-mode-define-keys-hook 'xxx-mode-define-keys)

      (ti::macrof-define-keys
       "xxx-mode-define-keys"
       'xxx-:mode-prefix-map
       'xxx-:mode-prefix-key

       'xxx-:easymenu
       'xxx-:easymenu-name
       "Programming help menu."
       (list
        xxx-:easymenu-name
        ["Eval whole buffer" xxx-eval-current-buffer    t]
        ..)
       '(progn
          (define-key map "-" 'xxx-eval-current-buffer)
          (define-key map "=" 'xxx-calculate)
          ..))    


Tinyliba.el --- Library for (a)utoload definitions

Preface, 1998

This is lisp function library, package itself does nothing. This library defines autoload functions and few emacs version detection functions.

The autoloads are automatically generated and you should not fix them by hand. To add or update autoloads from a package, do it like this:


Tinylibb.el --- Library of (b)ackward compatible functions.

Preface, 1998

This is lisp function library, package itself does nothing. This library defines new [X]Emacs release functions for older [X]Emacs releases.

Code policy

If there has been found a useful macro from someone's .el or from news, the proper source and name of author + time is preserved. All the credit goes to those profilic programmers.

Usage

You must not autoload this package; but always include

      (require 'tinylibm)    

Yes, there is no typo, you load "m" lib. It will handle arranging everything for you. This library is included by "m" library automatically. Repeat: you DO NOT PUT any of these in your packages:

      (require 'tinylib)
      (require 'tinyliba)
      (require 'tinylibb)
      (require 'tinylibo)
      (require 'tinyliby)    

A single statement will arrange everything:

      (require 'tinylibm)    

Notes

2000-09-12 ttn@revel.glug.org in gnu.emacs.sources http://www.glug.org/people/ttn/software/ttn-pers-elisp/ reported that: New file core/veneration.el allows GNU Emacs 19 support. We define some functions used by this library that are available in GNU Emacs 20, but not in GNU Emacs 19: compose-mail and minimal supporting functions (see mail-n-news/compose-mail.el), shell-command-to-string, and char-before. We also redefine match-data to handle arguments.

1998-10 SEMI's poe*el libraries also emulate various Emacs versions. There should be only one emulation library for all package writers. It would be best if all backward compatibility functions were moved either to SEMI or to another common place.


Tinylibck.el --- Library to (c)onvert (k)eybindings for XEmacs or Emacs

Preface

This file tries to overcome differencies between Emacs and XEmacs keybinding. I developed this at the time when I used 19.28 and I wanted to use my other packages with any emacs version in spite of key definition differencies. This file is in fact "library" and propably interests only lisp programmers that want to make some old package, that has Emacs specific bindings, to work in XEmacs (or vice versa).

Emacs 19.30+ note

Newer Emacs release now supports XEmacs styled bindings. You can write

      (local-set-key [(control meta up)] 'ignore)    

and it should work both in XEmacs and Emacs. If all your keybindins are like that and you don't use Emacs lower than 19.30, then you don't need this package. I recommend that you use primarily this style.

Putting your key definitions to separate file

You should separate all you keybindings to one file, do not stuff all your emacs definitions in one huge ~/.emacs, but instead use some basic structure like this:

      ~/.emacs            -- the main; points to ~/rc/emacs-rc.el
      ~/rc/emacs-rc.el    -- The main loader
      ~/rc/emacs-kbd.el   -- All the keybindinds
      ~/rc/emacs-x.el     -- X settings and X-packages loads
      ~/rc/emacs-vc.el    -- vc settings and modifications
      ~/rc/emacs-bup.el   -- Backup settings and redefinitions
      ~/rc/emacs-gnus.el  -- gnus customization
      ..    

You can load your other initialize files from .emacs with load command. Suppose you have Emacs keybinding startup file; which you want to make compatible with XEmacs too. The reason why you should use ti::ck-maybe-activate is that, it can determine your emacs version and decide when the converter is needed and when not.

      ;; at the beginning of keybindings, you add these

      (require 'tinylibm)
      (autoload 'ti::ck-advice-control "tinylibck")

      (ti::ck-maybe-activate 'xemacs-mouse)
      (load "~/rc/emacs-rc-keys")     ;; All XEmacs styled bindings
      (ti::ck-maybe-activate 'xemacs-mouse 'disable)

      ;;  load rest of the startup files
      (load "~/rc/emacs-rc)
      ...
      ;; End of startup file    

Some lowlevel explanation

If you're in Emacs, you use X-event bindings like this

      (global-set-key [C-up] 'ignore)    

Unfortunately, this does not work in XEmacs, but using the conversion function before the definition, it does.

      (global-set-key (ti::ck-do [C-up]) 'ignore)    

Now the current Emacs version gets the right keybinding,

      for Emacs  it returns       --> [C-up]
      for XEmacs it returns       --> '(control up)    

You can also use the XEmacs keybinding, since the conversion goes both ways. Having the following setting:

      (global-set-key (ti::ck-do '(control up)) 'ignore)    

it converts this to suitable form depending on the current Emacs in use.

About advices

So that you don't have to go and add that 'ti::ck-do' call for every keybinding, I have provided advices that hook themself to appropriate keybinding functions. The conversion is then done transparently and you don't have to change a thing in you keybinding settings.

About debugging

If you suspect any weird behavior in your emacs while this package is loaded, you should check that the ti::ck-:debug is turned on. (M-x ti::ck-debug-toggle)

The buffer ti::ck-:debug-buffer constantly records any conversion actions and you can find the problems quickly. Please send the supicious/false conversion lines to the maintainer of this package and if possible, tell how the conversion should go in your opinion.

I'd recommend that you keep the debugging permanently on, because if problems arise afterwards and if the debug were off, there is no way to tell what went wrong in what command.

Important; when you have problems, increase

      ti::ck-:debug-buffer-size    

immediately to some arbitrary big value so that you get all the conversions recorded.

Known limitations

This package tries to do its best to make the conversion, but sometimes it is just impossible. For example the following case is beyond of this package. In Emacs you can define

      (define-key xxx-mode-map [?\C-`] 'some-function)
                               ^^^^^^^    

But when your're in XEmacs and you try to do the same, it gives error although tinylibck is currently active. The reason is that lisp intepreter never actually passes key "?\C-`" to define-key but it actually evaluates the vector in place to an integer value and sends that to define-key function . The call actually is seen in Emacs like this:

      (define-key xxx-mode-map [4194400] 'some-function)
                               ^^^^^^^^^in my HP-UX 9.05    

And in XEmacs it is evaluates to this:

      (define-key xxx-mode-map [0] 'xxx-tab-backward)    

The code "0" appears, because XEmacs doesn't know Emacs "?\C-`". You should write [(control ?\`)] for XEmacs and it would work ok. Be aware of this limitation if you plan to use Emacs styled bindings. Alternatively, you can tell that you that some particular piece of code has been written by using XEmacs style. (Wouldn't you want to you use it all the time in Emacs...)

      ;;   This is Emacs file.
      (require 'tinylibck)                   ;Keybind converter.
      (ti::ck-advice-control)             ;turn it on
      ;;
      ;;   But here I want to use xemacs style for a while
      (define-key tinytab-mode-map [(control ?\`)]  'tinytab-tab-backward)
      ;; And other similar keybindings ...
      (ti::ck-advice-control 'disable)    ;don't leave it on    

Thank you

Vladimir Alexiev vladimir@cs.ualberta.ca Presented initial idea of the conversion process. Commented how the conversion should go in XEmacs.

Stephen Eglen stephene@cogs.susx.ac.uk Stephen had the patience to send bug reports from XEmacs 19.12 and test new versions of tinylibck.el


Tinylibid.el --- Library for (Id)entifying buffer, regardless of mode

Preface, Feb 1995

Seems quite uninteresting package to you? I bet it does, unless you're a lisp programmer who has infite time to twiddle his c++-mode-hook + 20 others hooks and have all the time develop nice little funcs to make living in emacs easier.

While someone may think that all users stick to one mode e.g. when they are programming C++, that's not obvious. For example programmer may move between all kind of modes during programming and the trouble is, that while the buffer's logical content remains the same, the hooks know nothing about it. Hooks are just dummies that get called whenever you turn some mode on, try C++ mode over nroff code and you'll be surprised.

Now let's see one session example:

  1. write list ;lisp-mode + folding-mode
  2. hmm, write some comments ;tinyindent minor mode, no folding
  3. hmm, need center-command ;move to text-mode
  4. code again ;lisp-mode
  5. adjust defconst var pos. ;turn on tiny tab minor mode
  6. code again ;lisp-mode

Programmer may have bound all common modes into keys so that he can ;; can access various modes very fast; changing modes is no problem. What is the problem, is that when you turn off the CODE-mode, all information about comment-start etc. vanish.

Overview of features

Imenu example

If you're using imenu.el to generate buffer jump points, it is very likely that the imenu command won't generate right jump points if you're in wrong mode. Let's use imenu example. Here is first try: The code sniffs around to see if we're on some mode and then configures imenu according to it.

      (defun my-imenu-mouse (event)
        (interactive "e")
        (my-imenu))

      (defun my-imenu (&optional arg)
        "Sets parameters to imenu."
        (let* (raise)
          (setq imenu-max-items 20
             imenu-sort-function nil)
          (cond
          ((memq major-mode
            '(lisp-mode emacs-lisp-mode lisp-interaction-mode))
            (setq imenu-create-index-function
                  'imenu-example--create-lisp-index
                  imenu-sort-function
                  'imenu--sort-by-name
                  raise t))
           ((memq major-mode '(c++-mode))
            (setq imenu-create-index-function
                  'imenu-example--create-c++-index
                  imenu-sort-function
                  'imenu--sort-by-name
                  raise t))
           ((memq major-mode '(c-mode))
            (setq imenu-create-index-function
                  'imenu-example--create-c-index
                  imenu-sort-function
                  'imenu--sort-by-name
                  raise t)))
          (if raise
              (imenu))))    

Here is better and more robust way. It'll let you be in any mode while retaining right imenu.

      (require 'imenu)

      ;;  Separate functions for keyboard and mouse.
      (defun my-imenu-mouse (event &optional arg)
        (interactive "e\nP")
        (my-imenu arg))

      (defun my-imenu (&optional arg)
        "Sets parameters to imenu. If called with arg, the output is
       unsorted."
        (interactive "P")
        (let* ((sort-func (if arg nil 'imenu--sort-by-name))
               (table
                '((lisp-mode
                   imenu-example--create-lisp-index)
                  (emacs-lisp-mode
                   imenu-example--create-lisp-index)
                  (c++-mode
                   imenu-example--create-c++-index)
                  (c-mode
                   imenu-example--create-c-index)))
               ;;  So, in what mode were really?
               (mode (or (ti::id-info t) major-mode))
               (el (assoc mode table)))
          (if (null el)
              (message "Sorry, no imenu for this buffer.")
            (setq imenu-max-items         20
                  imenu-sort-function             sort-func
                  imenu-create-index-function     (nth 1 el))
            (imenu))))    


Tinylibm.el --- Library of s(m)all macros or functions

Preface, 1995

This is lisp function library, package itself does nothing. It contains small functions or macros.

Code policy

If I have found some useful macro from someone's .el or from news, the proper source and name of author + time is preserved. All the credit goes to those programmers.

Usage

You must not autoload this package; but always include

      (require 'tinylibm)    

You don't need any other require commands: all my other library functions get defined as well by using autoload. Repeat: you don't have to put these in your packages:

      (require 'tinylib)   ;; leave this out
      (require 'tinyliby)  ;; not needed either.    


Tinylibo.el --- Library for handling (o)verlays

Preface 1995

The functions were developed to ease the usage of highlighting, which really seemed "inside" stuff when I first wanted to use colored text in emacs.

Code policy

All functions are written by [jaalto], unless otherwise notified. If I have found interesting function from some other .el I have written a reference to that .el. If the code is directly taken 'almost as is' all the credit belongs to the Author of the original code. Cheers for him, to write so recpectable code, that it can be used right from the box!

If someone contributes good, general purpose function, all the credit belongs to him automatically. Persons name and date and so on is included.


Tinylibxe.el --- Library for Emacs and XEmacs emulation.

Preface 1996

There are incompatibilities for XEmacs and Emacs, which prevented writing portable code. The bigger problematic things have been collected here, some of them have been implemented in lower level libraries like in tinylibb.el.

Overlay.el in XEmacs 19.15+

Good news; XEmacs 19.15+ has new package that emulates Emacs overlay functions.

What you should know – keep this in mind

This library's intention is to make it possible to use some package that is written only in Emacs or only in XEmacs in mind. Normally You couldn't use that package in another emacs, because there may be functions that are not implemented.

When you load this library, it emulates those unknown functions as much as it can, so that that you can use the package for both emacs. However, it may not be possible to reproduce exactly the same behavior in the Emacs that was not the primary target for the package. The emulation may in worst case be only so, that you are able to load the package without errors, but the functionality of the package doesn't correspond to the original version.

When you write your own packages, do not try to make use of the latest glory details of the Emacs. If you do, you can be sure that your package won't work anywhere else.


Tinylisp.el --- Emacs lisp programming help grab-bag

Preface, Feb 1997

Private lisp help functions were scattered around files and in other private libraries. One day the author decided to write a minor mode to access all those tools that were written one by one and he I didn't want to continue stacking up lisp-mode-hook for all the growing features. So, if you're programming in Emacs Lisp, this minor mode may slightly increase your productivity.

Overview of features

Lisp coding help

Edebug support

Elp support – Lisp code profiling

Elint support – Lint your elisp code

Checkdoc support – Check doc strings for style requirements

Find-func.el support

Remarks

Tutorial, how do you check your package

          xxx-buffer-handling
          xxx-buffer-clear

      Check also that your macros are defined first before functions.
      If possible, maintain this definition order in your file

          defvar, defconst, defcustom  (on top of file)
          defsubst
          defmacro
          defun    

Defcustom.el and evaluating an `defcustom' variable

If you don't know what defcustom is, or if you don't use it, you can ignore this section. The defcustom variables are evaluated pretending like they were defconst, but because this evaluation is a bit special, pay attention to following paragraph.

If you got thrown to error during evaluation, pay attention now, CALL COMMAND $ Z or M-x tinylisp-emergency IMMEDIATELY. For full details, see function documentation strings in the source file for these:

      (defadvice defconst
      (defun     tinylisp-eval-at-point    

Find lisp code error position

The most useful functions in this package are the two error finding functions which try their best to put you on a line that generates the lisp error. You can use this feature to e.g. check your ~/.emacs startup files and find the spot where eval-current-buffer fails.

The best function, tinylisp-error-find-1, was programmed by Mikael Djurfeldt mdj@sanscalc.nada.kth.se and is included here with his permission. Thanks Mikael, the funstion has saved from me a lot of debugging!

Following lisp code call chain

The traditional way to follow lisp code is to use TAGS file (See 'etags' or 'ctags' shell binary and C-h a "tags") which reads bunch of *el files and builds up internal representation of all defined symbols and their locations.

But using tags is not very flexible if you write the code yourself, because when you add new function or new variable, the TAGS file is immediately out of date. Hm. The TAGS is general tool for many programming languages, but in Emacs lisp, we can take advantage of the fact that Emacs already knows where the symbols are defined. The information is stored to load-history whenever you run load require load-file or load-library.

In this package, there are two functions that make use of load-history and if the symbol is not in the history, they try to find definition from the current buffer. You see, if you do eval-current-buffer the definition information is not stored to load-history. With these commands you can browse some packages without any extra TAGS file.

[The only assumption is that you have loaded the file !!]

      $ '     tinylisp-jump-to-definition (do not record call chain)
      $ +     tinylisp-jump-to-definition-chain (record call chain)
      $ \177  tinylisp-back-to-definition (probably your backspace key)
              This returns to previously saved call-chain point    

The jump command also know following prefix arguments

      M-0 $ ' tinylisp-jump-to-definition (empty call chain)
      C-u $ ' tinylisp-jump-to-definition (record call-chain)    

Examining text properties and overlays in buffer

If you have ever played with text properties or overlays (called extents in XEmacs), you know how hard it is to examine buffer's characters and debug where the properties are.

In this package there is "constant char browsing mode" where every time you move your cursor, the face info and/or overlay info is displayed in the echo-area. If you supply 3 C-u arguments, the information is also recored to the separate buffer. This is the most easiest way to examine some character properties in arbitrary buffer positions. See C-h f on following function:

      $ p     tinylisp-property-show-mode    

Examining charcter syntax

Major modes define syntax tables for characters and sometimes you want to see the syntax class of a character under cursor. This mode behaves in the same manner as text property display, just turn it on and it will constantly show char info.

      $ y     tli-syntax-show-mode    

Snooping interesting variables

Has is happened to you that you're debugging package and it installs many hooks and and sets many different variables and then you suddenly realize that it went all wrong? You may even have noticed that some ill behaving package keeps preventing file writing!

No problem, you can define interesting variable sets to peek their contents, e.g. checking all file related hooks for problems. And if you supply C-u prefix arg, your editing is updated to the variables. With any other non-nil arg, the contents of the variables are recorded (kinda before install – after install snooping) See function:

      $ s     tinylisp-snoop-variables    

And additional prefix arguments: You can save variables states, modify them as you like, and go back to restores values.

Elp: notes

[excerpt from Barry's elp.el] ...Elp can instrument byte-compiled functions just as easily as interpreted functions, but it cannot instrument macros. However, when you redefine a function (e.g. with eval-defun), you'll need to re-instrument it with M-x elp-instrument-function. This will also reset profiling information for that function. Elp can handle interactive functions (i.e. commands), but of course any time spent idling for user prompts will show up in the timing results.

To elp functions right, follow these steps. important "(defun" must be left flushed in order the function to be found. If there is any leading spaces before the '(' or 'defun', then function won't be found and will not be (un)instrumented.

Elp: Summary mode's sort capabilities

When you call $ ŽE' s to show the elp result(s), the results buffer is put into tinylisp-elp-summary-mode where you can sort the columns with simple keystrokes. The sort keys correspond to the column names.

      f)unction Name  c)all Count  e)lapsed Time  a)verage Time
      =============   ==========   ============   ============    

Elp: customizations

You should be aware of this variable in elp; which resets the list every time you display it. You can toggle it's value from the echo menu.

      elp-reset-after-results    

Edebug support

To instrument function for edebug, you'd normally have cursor inside current function and call C-u M-x edebug-eval-defun. But suppose you only see function call like this:

      (my-function arg arg arg)    

then you'd have to a) find out where the function is defined b) load that file c) position cursor over the fuction definition d) call edebug to instrument it. That's too much of a work. Instead there are commands that do this for you. See edebug submap C-e for edebug commands

      $ C-e RET   Instrument function _named_ at point
      $ C-e DEL   Uninstrument function _named_ at point
      $ C-e SPC   Instrument all functions in buffer
      $ C-e x     Uninstrument all functions in buffer
      $ C-e X     Uninstrument all functions instrumented by $ C-e RET    

Todo section

In standard Emacs there seems to be underused package trace.el. Add direct support for it.

The regress.el provides support for writing and executing regression tests for Emacs Lisp code. Could that be supported too?

Add support to xray.el


Tinyload.el --- Load set of packages when Emacs is idle (lazy load)

Preface, Jul 1997

While it is possible to arrange Emacs rc (start-up) files to use all possible and imaginable autoloads, there are still packages that can't be autoloaded due to their setup nature or other behavior: require commands are necessary in .emacs in order to use those modules. This means that for every require command, the Emacs startup slows remarkably. Experienced Emacs users have very complex boot configurations, so waiting minutes for Emacs startup screen to appear is quite frustrating.

The described situation gave birth to this package. Now the emacs is ready to use within few seconds.

What this package does, is, that it caches the load requests and executes them when it thinks there is free time. Instead of setting up all at once on startup, the emacs configuration is built piece by piece, until the whole 100% configuration is there.

The benefit is that Emacs starts instantly, and when it is idle, the remaining packages, that you wanted to be available in your daily Emacs session, are loaded.

Overview of features

If you're a first time Emacs user or if you consider lisp difficult, have a look at simpler setup than what is described below from C-h v tinyload-:load-file. The idea is that you tell the configuration file which lists packages that you want to load in format:

      PACKAGE CONFIG-WORD    

The CONFIG-WORD should be self explanatory: it instructs in which OS and in which Emacs flavor the package is loaded. Here isa sample: reportmail is only loaded under win32 and XEmacs.

      paren
      autorevert win32
      gnus.el
      reportmail  win32-xemacs    

Another easy interface is to use functions:

      `tinyload-load-list-add-function'
      `tinyload-load-list-add-package'
      `tinyload-load-list-delete-function'
      `tinyload-load-list-delete-package'    

First user notice

When you use this package for the first time, you may feel uncomfortable with the amount of messages you see displayed on the echo area. And if you're in echo-area prompt (e.g. after C-x C-f) those messages may disturb the echo area prompt.

Just don't panic. Move your cursor key to the left (C-a) or start typing and the load will be interrupted. As long as there is activity in your Emacs the load will not happen.

The messages that are displayed in the echo area are important, because they get stored in Messages buffers and you can take a look if anything strange happened. Like if some package couldn't be loaded at all. Pay attention to fatal messages.

Messages in *Message* buffer

There are different types of messages

      TinyLoad: fdb ok      (10% 1/10)                         [1]
      TinyLoad: elp 'noerr! (20% 2/10)                         [2]
      TinyLoad: [ERROR] loading  ~/elisp/rc/emacs-rc-init.el   [3]    

In addition to these basic messages, there are some internal messages that do not concern regular user, only the maintainer. When he TinyLoad wakes up; you might see following message

      Tinyload: timer expired; invoking load process..[busy;stop;N]
                                                       |    |    |
                                    user activity status    |    |
                                              Continue status    |
                                Busy count; and deadlock indicator    

Which simply means that Emacs called the loader function and because Continue status was nil, user did nothing at the time of invocation. If the message [busy;stop;N] then user was doing something that weren't allowed to be interrupted. Usually this happens when cursor is in echo area e.g. after C-x C-f. If the cursor never leaves the echo area or if the busy situation continues for a certain period of time, the program automatically clears the busy signal and continues loading. You should not see infinite [busy;stop.N] messages. If you really see 100 such messages; then contact the author: there must be an unresolved deadlock and a bug in the program.

When the tinyload-:load-list has been handled, the loader process terminates itself. The following message tells that the process has ceased to exist. If you want to start reading the list again, call M-x tinyload-install.

      TinyLoad: Loader process terminated.    

Tutorial

Let's supposes your emacs startup consists of following rc files The name rc comes from Unix resource files, like $HOME/.bashrc, $HOME/.cshrc ...

      emacs-rc-main.el     -- the main load controller
      emacs-rc-path.el     -- settings `auto-mode-alist' etc.
      emacs-rc-bup.el      -- Backup settings
      emacs-rc-set.el      -- Emacs variable settings

      emacs-rc-keys.el     -- Keyboard customizations
      emacs-rc-font.el     -- Fonts and Font lock; face settings
      emacs-rc-hooks.el    -- All add-hook commands and mode settings.
      emacs-rc-ding.el     -- Gnus customizations (symlink to ~/.gnus)
      emacs-rc-pkg-std.el  -- Loading std Emacs packages and their setup
      emacs-rc-pkg-misc.el -- Non-std distrib, additional packages
      emacs-rc-tips.el     -- Tips (code samples) from the Usenet
      emacs-rc-mail.el     -- mail agent, Rmail, VM, message.el etc. setup    

Now suppose your .emacs loads all these files like this

      ;; $HOME/.emacs -- Emacs startup controller

      (require 'cl)   ;; Tell location of startup files
      (pushnew "~/elisp/rc" load-path :test 'string=)

      (require 'emacs-rc-path)
      (require 'emacs-rc-bup)
      (require 'emacs-rc-set)
      (load "emacs-rc-keys.el")
      (require 'emacs-rc-font)
      (load "emacs-rc-hooks")
      (load "emacs-rc-ding")
      (load "emacs-rc-pkg-std")
      (load "emacs-rc-pkg-misc")
      (load "emacs-rc-tips")
      (add-hook 'mail-mode-hook '(lambda () (require 'emacs-rc-mail)))

      ;; End of file $HOME/.emacs    

The reason why there may be both load and require commands may be that you frequently make updates and changes to some of your start-up files. Like if you frequently update Setting for Gnus, and you want to reload your settings, the (load "emacs-rc-ding") is executed again. If you used require the new settings would not have been loaded. (See explanation of load and require from the Emacs info manual). So, to re-cap, if you would call:

      M-x load-file ~/.emacs    

Only the load commands' files would be loaded again. All the require files would have been skipped, because the rc resource features had already been defined.

Now, loading all these files, either with require or load, takes too much time when you start Emacs. After some rearrangements you can put the delayed loading into use:

      ;; $HOME/.emacs -- Emacs startup controller

      (require 'cl)   ;; Tell location of startup files
      (pushnew "~/elisp/rc" load-path :test 'string=)

      ;; Have these minimum features immediately available

      (require 'emacs-rc-path)
      (require 'emacs-rc-bup)
      (require 'emacs-rc-set)
      (load "emacs-rc-keys.el")

      ;;  Load this setup only when mail composing is started

      (add-hook 'mail-mode-hook '(lambda () (require 'emacs-rc-mail)))

      ;;  ........................................... lazy loading ....
      ;;  We can afford to load these later

      (setq tinyload-:load-list
        '(("emacs-rc-font")
          ("emacs-rc-hooks")
          ("emacs-rc-ding")
          ("emacs-rc-pkg-std")
          ("emacs-rc-pkg-misc")
          ("emacs-rc-tips")
          ("emacs-rc-mail")))

      (require 'tinyload)
      ;; End of file $HOME/.emacs    

When Emacs load this startup, only the most important files are loaded saving the start time considerably. After tinyload finds that your Emacs is idle it starts loading all the rest of the packages you defined in the tinyload-:load-list. For more complex setup, refer to end of tinyload.el source file, where you can find a complete example setup.

NOTE: Please pay attention to one detail above. The emacs-rc-mail will be loaded from load list and it will be loaded when you call M-x mail. Do you believe there is redundancy? The idea is that you may call M-x mail way before the TinyLoad reaches that file in its load list and the hook guarantees that you get the setup at mail invoke time.

But it may be the other way round: TinyLoad has already loaded the mail setup for you and thus invoking M-x mail is fast, because there is nothing to load any more.

Similar things you should do to GNUS, VM, RMAIL and others that you call and whose setup you want to have immediately available

Delayed loading, require and autoload

Above you saw how to load your Emacs rc files. But the delayed loading is not only suitable for those. It also helps you to load files, that can't be autoloaded.

If you can arrange loading a packages with autoload command, do that. Never put require or direct load command into your Emacs rc file, because load commands eat start time.

Packages usually explain in the installation section two ways how to load them: here is an example from tinytab.el

      (require 'tinytab)

      or use this; your .emacs is read quicker

      (autoload 'tinytab-mode              "tinytab" "" t)
      (autoload 'tinytab-return-key-toggle "tinytab" "" t)    

The first way forces loading the whole file (takes time); and the latter only tells that the package's functions tinytab-return-key-toggle and tinytab-mode exists. If you happen to call those functions, only then the package gets loaded. The big difference here is that when you put the latter in your Emacs rc file, Emacs reads autoload statements much faster than the require command.

It is not always possible arrange to load package with autoloads, because the package may behave so that in order to get the features installed, package must do the setup by itself: you can't do it yourself. Here are few packages that can't be autoloaded:

      crypt++     -- crypt(1) support.
      tinymy      -- collection of utilities
      fdb         -- Emacs Debug error filter
      fa-extras   -- Filling extras    

When you would normally include a require command for these into your Emacs rc file, you can now move the packages to load list and keep only autoloads in the rc files.

      ;; Old rc file

      (autoload ....
      (autoload ....
      (require 'fa-extras)
      (autoload ....

      ;; New rc file

      (autoload ....
      (autoload ....
      (autoload ....    

And the missing require entry has been moved to tinyload-:load-list.

Use separate rc file for load definitions

It may be good idea to make a separate rc file that only has the load list definition and a call to tinyload.el, like this:

      ;; emacs-rc-tinyload.el -- load definitions for tinyload.el
      ;;
      ;; If you compile this file, `defconst' shuts up Byte Compiler

      (defconst tinyload-:load-list
        '(...
          ...))
      (require 'tinyload)
      (provide 'emacs-rc-tinyload)
      ;; End of file    

And then you add following call to your $HOME/.emacs, to the end of the file, although the place really doesn't matter.

      (require 'emacs-rc-tinyload)    

Used timer process

A normal timer process is used to load the packages from the load list. The timer awakens at regular intervals and loads one package at a time: more packages are not loaded if there was input pending at the time of previous load. The load messages are recorded to Messages buffer. In old Emacs releases this buffer does not exist; but it will be created for you.

About implementation

When tinyload-:load-list is set, the value of the variable is saved under property original. When the idle timer runs, the list is read from the beginning and each package at a time is loaded. The last unloaded package position is saved under property 'pos.

The situation looks like this:

      tinyload-:load-list 'original   --> (list) original contents
      tinyload-:load-list 'pos        --> (nth nbr) next package to load.    

If your do something in your emacs while the list is being looped, or when the loader function is about to be called, that interrupts the work. Next time the timer functions run runs, happens:

Force loading

There is also property fatal-list which contains entries that couldn't be loaded. The list is updated while the loading takes place. If you examine the failed files and make corrections; you can try to reload the whole load list again if you call

      C-u M-x tinyload-loader-process    

Special features

In case you want to load all packages and leave nothing in autoload state, add this code to your Emacs startup file. When the loader process exits, it will check all Emacs functions for autoload definitions and load those packages as well.

      (add-hook 'tinyload-:process-uninstall-hook
                'tinyload-autoload-function-load)    

Restart and cancel

If you want to restart the evaluation of load list, call M-x tinyload-install, which will install the package again by removing old processes and resetting counters. To stop the loaded process permanently, call tinyload-cancel.

Bugs

Every effort has been made to check that Emacs has no activity before the package is loaded at the background. A series of sit-for input-pending-p and more obscure mini-buffer checks have been run before the load kicks in. If the package is still loaded while you were doing something, please send suggestion how the event could be detected so that the load wouldn't interrupt you again. However, there is no single and sure solution to notice user activity reliably.

Despite of the efforts, an unlucky moment may load the package, when it was not appropriate. Please hang on and wait for the load to finish, you're will regain control after if if you had pressed any key.


Tinymacro.el --- Fast way to assign newly created macro to a key

Preface, 1995

This started as a very little project when mosh@ramanujan.cs.albany.edu (Mohsin-Ahmed) 1995-03-17 in gnu.emacs.help post asked for easy way to assign newly created macro to some key. In reponse the author sent a simple function to do it, but he informaed that one macro, which was recycled every time, was too little. Author started modifying code more, and that was the birth of this package.

Description


Tinymailbox.el --- Berkeley style aka std. mailbox browsing minor mode

Preface, sep 1997

It is possible to use Procmail http://www.procmail.org/ to manage growing incoming mail. But sometimes your recipes go wrong and mail ends up folders that you dind't intend to. People usually direct UBE, UCE and Spam mail to different folders, but sometimes procmail filter just guesses wrong and it sends perfetly valid mail into one of these reject folders. It is good to check the Spam mailboxes manually for valid mail and then extract it out of them. Not very nice job to do. At the the time Gnus was not available for managing multiple forlders so I decided to pull out some old code and make it a package.

Overview of features

Showing and hiding headers

When you browse a mail folder, it has lot of attached headers, which don't interest you at all when you want to look at the messages itself. for example, here is one typical header from a test message

      From nobody Sun Sep 28 20:57:48 1997
      To: nobody
      Subject: Re: bandwidth (was: [RePol] check this issue)
      References: <em>tbd8lwmfid.fsf@totally-fudged-out-message-id</em>
      From: Foo bar <em>judgeDredd@marylyn.com</em>
      Date: 28 Sep 1997 20:57:47 +0300
      In-Reply-To: Jeff's message of "Tue, 23 Sep 1997 01:35:26 -0400"
      Message-ID: <em>tbiuvlmick.fsf@marylyn.com</em>
      X-Mailer: Quassia Gnus v0.11/Emacs 19.34
      Lines: 3
      Xref: marylyn.com junk-test:4
      X-Gnus-Article-Number: 4   Sun Sep 28 20:57:48 1997    

When you go from this message with tinymailbox-forward, the headers that you're interested in are only shown according to tinymailbox-:header-show-regexp. The messages headers are collapsed as you move around the messages. This approach was chosen, so that parsing a big message file (Gnus nnfolder backend) wouldn't put you on hold while the headers were collapsed. Now the headers are handled while you browse forward and backward. The above headers lookes like this after processing it:

      To: nobody
      Subject: Re: bandwidth (was: [RePol] check this issue)
      From: Foo bar <em>judgeDredd@marylyn.com</em>
      Date: 28 Sep 1997 20:57:47 +0300
      X-Mailer: Quassia Gnus v0.11/Emacs 19.34
      X-Gnus-Article-Number: 4   Sun Sep 28 20:57:48 1997    

By default all the X- headers are shown, so you may want to make the tinymailbox-:header-show-regexp a bit more restrictive if your messages have too much X-headers. You can toggle this message hiding feature with

      C-q     or tinymailbox-header-hide-mode    

Copying or deleting messages

When you browse the mailbox, you can perform copy or delete on the current message with following commands.

      ' RET   tinymailbox-copy
      ' SPC   tinymailbox-copy-body
      ' d     tinymailbox-delete    

Moving between the messages

There are couple of movement commands that let you jump from one message to another. See also variable tinymailbox-:move-header-regexp

      C-p     tinymailbox-forward-body  or Ctrl-home
      C-n     tinymailbox-backward-body or Ctrl-end
      home    tinymailbox-forward (see tinymailbox-:move-header-regexp)
      end     tinymailbox-backward    


Tinymy.el --- Collection of simple solutions.

Preface, Nov 1995

Emacs startup files started to look quite interesting:

      emacs-rc-tips     emacrs-rc-el      emacrs-rc-el      emacrs-rc-el.sun
      emacs-rc-18       emacs-rc-19       emacs-rc-abb      emacs-rc-compile
      emacs-rc-debug    emacs-rc-default  emacs-rc-font     emacs-rc-ding
      emacs-rc-font.b   emacs-rc-gnus     emacs-rc-hooks
      emacs-rc-init     emacs-rc-init2    emacs-rc-mail
      emacs-rc-o        emacs-rc-o-19     emacs-rc-out
      emacs-rc-path     emacs-rc-pc       emacs-rc-prog     emacs-rc-set
      emacs-rc-test     emacs-rc-time     emacs-rc-tips     emacs-rc-vc
      emacs-rc-w3       emacs-rc-x-menu   emacs-rc-xe
      emacs-rc-dired
      ..    

Private functions seemed to grow all the time, most of which were turned into packages, but sometimes it was just function or two that made a life with Emacs easier. What you see here is a selection of so called general my functions. The term my does not refer to mine, but has a background in function naming. Remember? All user functions are recommended to be named so, that the first word is my-, like my-FUNC-NAME-HERE

Overview of features

Timer processes

Buffer

Compile

Files

Gnus, mail

Keys

Line formatting

Mouse

          TinyMy: -rw-r--r-- 108k /users/jaalto/elisp/tinymy.el    

Shell

vc

Window

Minor modes in this package

Sort minor mode

If you have data in columns, use C-cmS or M-x tinymy-sort-mode to toggle sort mode on and off. With it you can sort columns 1-9 easily. Mode line indicator is "S"

Display minor mode

Hot key C-cmD or M-x tinymy-display-mode. If you have DOS file and you load it into Emacs, you usually see the ^M characters. With the display mode active, it hides them from the screen, but they are still in the buffer. This display mode will hide other non-ascii characters too. See the source if you want to find out the full repertoire.

This display mode is automatically turned on when you load an dos-like file that has ^M character at the end of line. Mode line indicator is "D".

Another display made selection also let's you view MS Word binary files in some extent.

Features immediately activated when package loads

What commands are defined when you load this file?

It's better to look at the code of this file, than to explain all the key definitions here, because I may not remember update this text section every time I add new interactive commands to the file.

All the new interactive commands can be found from these two functions:

      tinymy-define-keys
      tinymy-mail-common-keys    

See their description, or alternatively hit

      C-h m                                ;; to view all bindings
      M-x delete-non-matching-lines tinymy ;; show bound keys    

Key bindings

When you load this package, you can also install global key-bindings that if you set the load hook:

      (setq tinymy-:load-hook
          '(tinymy-install
            tinymy-define-keys
            tinymy-define-key-extra
            tinymy-alias)    

If you want to use your own bindings, use it like this:

      (setq tinymy-:load-hook '(tinymy-install my-tinymy-keys tinymy-alias)
                                               ^^^^^^^^^^^^^^
      (defun my-tinymy-keys ()    

There is table of global bindings which you can modify if the bindings clash: the auto install will warn you about this automatically and your own bindings are not replaced by default. See variable: tinymy-:define-key-table


Tinynbr.el --- Number conversion minor mode oct/bin/hex

Preface, aug 1997

One day in a laboratory the developer once forgot his desk calculator in another building. He was examining binary (hex) files and other electronic documents that used hex and base10 numbers. He shroudly remembered that Unix included some basic calculator, but he dind't remember what was the name and how to use it. Whoops. Grin.

Instead of returning to get the missing calculator, he started pouring some lisp to make a simple minor mode to help to get along with the current task at hand. It didn't take long to make it, and the laboratory day was success. Ahem. Maybe should look at package calc.el someday.

Overview of features


Tinypad.el --- Emulate Windows notepad with extra menu

Preface, aug 1997

In gnu newsgroup there was a request that a class had been used to using Windows notepad and in order to make the transition to Emacs smooth, Emacs should have some notepad emulation mode so that pupils wouldnn't get lost completely in new envinronment. And here is it, a small notepad emulation. It installs one new menu to Emacs menu bar which is arranged exactly like the Windows notepad. I have included only the commands that are directly available from inside emacs and e.g. 'printer setup' is something that is not found there. But in order to be complete emulation, all the choices as in normal notepad are available.

Overview of features

      Undo   in   Control-z
      Cut    in   Control-x
      Copy   in   Control-c
      Paste  in   Control-v    

Code note

Why on earth I made this package to use "global" minor mode? I can't remember the reason. A simple menubar entry may have sufficed just fine.... Oh, it was that remaping the bindings. You see, when minor mode is turned on, it conquers the mappings underneath.

[1997-10-23] Hey, I just saw pointer to package Map-zxcv.el which takes care oc mapping the missing zxcv, so I don't have to bother with those here. Nice. You can ask it from Kim F. Storm storm@olicom.dk


Tinypage.el --- Handling ^L pages, select, cut, copy, head renumber.

Preface, jun 1996

I had found paged.el by Michelangelo Grigni mic@mathcs.emory.edu one year or so ago and had liked it very much. Unfortunately it used narrowing and didn't offer easy page select, copy, cut actions which belong to basic page editing.

Paged.el has one nice feature: It can renumber pages and make summary out of them. If I have time I will include those features to package too.

Overview of features

About making pages – basics

If you're totally unfamiliar to the concept of page: you make pages in emacs by adding the linefeed marker in the text, normally on its own line, just before your topics or headings.

      C-q C-l  --> ^L    

That inserts the ^L character in the buffer. That is where your page starts. The layout of your doc may look like this:

^L 1.0 Topic one txt txt txt txt txt txt txt txt txt txt txt txt txt txt txt txt

^L 1.1 txt txt txt txt txt txt ..

^L 1.1.1.1 txt txt txt txt txt txt txt txt txt txt txt txt txt txt txt ...

About renumbering

This package offers simple renumbering features, but it won't do everything for you! Let's first tell what it won't do. Renumbering these is piece of cake:

      1.1
      1.7.1.5             (1)
      1.5
      1.5.4.1             (2)
      1.5.4.5
      1.9    

The result is

      1.1
      1.7.1.5
      1.2
      1.5.4.1
      1.5.4.2
      1.3    

tsk-tsk, before you say anything... It went all right. Now you see what it won't do for you.

  1. It can't know that the 1.7.1.5 belongs under previous 1.1, because no back tracking is done. I won't even try! [write a separate package if you want that...I won't do it]
    1. Same goes here, it can't know that the 1.5.4.1 should actually start from 1.5.1.1
    2. The thumb rule is, that you go and make sure all the first level headings (those that end to X.X.1.1) are right before doing renumbering. In the above case, you should have done these before calling M-x tinypage-renumber-forward.

      1. --> 1.1.1.1
      2. --> 1.5.1.1 AND do replace M-% 1.5.4 with 1.5.1

      Then all the renumberin would have gone just fine. Little handy work and this package helps you to number your doc easily.

      Renumbering – be cautious

      If you have index section in you file, you have a little problem, because this package does not know nothing about such things. If the Index section is at the beginning, just go past it and use function:

            M-x tinypage-renumber-forward    

      Using

            M-x tinypage-renumber-buffer    

      Would be disaster. It can only be used for non-index buffers.

      Creating index

      After you have renumbered all, your old index section is useless, Just call function

            M-x tinypage-toc    

      And copy the showed buffer in place of the old index.

      Limitations

      Since the numbering is done according to regexp, there is no way to avoid the following false hit:

            1.1 Overview
            This is highly technical document concerning the latest
            NASA ultrawave reflective shield technique. You should
            refer to chapter:
      
                1.5
      
            Where the Daddy-Cool portable sondium emission detector is
            described in full...    

      The Number 1.5 is unfortunately renumbered to 1.2, and possibly causing headache in the NASA and in the spying countries... If you know elegant way to prevent these false hits, please drop me a mail. At this time I haven't much payed attention to this.

      Code Note

      The renumbering used here uses brute force, so the execution time is O(n2). If you have more that 30-40 sections, the renumbering might take 15-40 minutes. If you care to send me more pleasant numbering I'd be very gratefull and you're name would be carved to this module. For now, I'm just too lazy to change anything.


      Tinypair.el --- Self insert character (pa)irs () "" '' <>

      Preface, 1995

      I saw paired-insert.el posted to gnu.emacs.help group, and the code was so badly documented that I got frusrated. And when I finally got it going, I wasn't quite pleased with it. The code showed lot of promises, but it couldn't do smart pairing. Instead I started developing this module.

      Overview of features

      Pairing control

      Remember Always ask youself "Does this character the cursor is on, belong to word class?", when you wonder why the pairing does not take in effect around the current character block.

      The pair control is turned off for lisp mode, because it makes things worse if the pairing is on. The pairing in US style includes

            `'    

      But European people almost never use backquote, intead they use:

            ''    

      General pairing rules, just some of them

      The pairing is done according to assoc lists in the following way:

            ()
             *  <-- cursor here, pressing another ( does not pair.    

      but this behavior can be controlled through variable

      o if the cursor is at the beginning of the word (see syntax-table): -- if there is no pairs around the word, the whole word is paired. -- if there is pair, no pairing takes effect. The char acts as self-insert-command.

      Cursor positioning

      By default the cursor is positioned in the "middle" of the inserted pair chars. But for words, this is impossible, because there is no middle position. Please see the variables

            tinypair-:word-positioning
            tinypair-:word-positioning-function    

      which allow you to customize cursor positioning after word pairing.

      Word about syntax tables

      Syntax table play a major part in pairing, especially pairing words correctly. Suppose you're writing in text mode:

            ...txt txt... (help is the key)
                           *                    <-- cursor    

      If you now press " to have the word HELP paired, you don't get it, because normally text mode's syntax table says that "(" belongs to group "w" (word) too. So the actual word is seen as "(help" and the program determines that you're inside a word, thus not allowing the pairing.

      In the other hand, if you were in any other mode, say in C++, the "(" is defined as open parenthesis syntax and it that case the seen word seen would have been "help" and the " character would have been added around the HELP string. Like this:

            ...txt txt... ("help" is the key)
                            *                   <-- cursor    

      You may propably want quickly to see the syntax definition of characters; use function from my lisp libraries

            (defalias 'syntax-info 'ti::string-syntax-info)    

      To return to this syntax problem in text mode, you could do the following, to make certain characters out of "w" class.

            (defun my-syntax-default (table )
              "My syntax table settings."
              (modify-syntax-entry ?[ "_" table)
              (modify-syntax-entry ?] "_" table)
              (modify-syntax-entry ?{ "_" table)
              (modify-syntax-entry ?} "_" table)
              (modify-syntax-entry ?( "_" table)
              (modify-syntax-entry ?) "_" table)
              (modify-syntax-entry ?/ "." table)
              (modify-syntax-entry ?\' "\"" table)
              (modify-syntax-entry ?\" "\"" table)
              (modify-syntax-entry ?_ "w" table))    

      Then you just change the definitions of syntax table in hook:

            (setq text-mode-hook 'my-text-mode-hook)
            (defun my-text-mode-hook ()
              (my-syntax-default  text-mode-syntax-table))    

      Do you wonder why I put {}()[] into "_" class and not in corresponding "(" or ")" classes? Well, my stig-paren just went beserk and started beeping the bell whenever I was nearby ")" class... The "_" shut it down, so I just chose it. You can of course put the chars into any class you like.


      Tinypath.el --- Manage Emacs startup dynamically.

      Preface, Feb 1999

      How it all begun

      When you have set up your Emacs installation to your liking, a day comes when you decide that it's time to seriously reconsider the directory structure of your installed lisp packages. At start, it is customary to use simple file hierarchy where all private packages are installed under:

            ~/elisp   ;; some people also prefer ~/lisp    

      Complete kits are usually installed directly under the root:

            ~/elisp/packages/bbdb-2.00.06/
            ~/elisp/packages/psgml-1.0.3/
            ~/elisp/packages/pcl-cvs-2.9.2/    

      A more sophisticated way is to use symlinks to the latest versions, so that you don't have to change load-path every time you install a new version. It is only matter of updating the symlink:

            ~/elisp/packages/pcl-cvs/  --> ~/elisp/packages/pcl-cvs-2.9.2/
            |
            This path is in the `load-path'    

      In windows world you may have your H: disk mounted to Unix $HOME:

            H:  --> Unix $HOME  \\SERVER\DIRECTORY\YOUR-LOGIN-DIR    

      Now, there is a catch when you use Unix symlinks in $HOME/elisp and try to access the directories from Windows. Having set PC's HOME environment variable to point to H:, Emacs can start reading Unix $HOME/.emacs startup file, but you soon encounter simple error messages like "Can't load library xxx", which soon follow by bigger concerns: "autoloading xxx failed". The problem is the mounted H: disk. You see, PC's network mount can't distinguish symlinked directories from real directories, so all symlinked Unix directories in load-path are dead. And that's why most of the files cannot be found any more.

      The conclusions

      For cross platform solution it is best not to rely on symlinks, because they don't work over a Windows mount. Secondly, updating load-path should not be needed by hand after a new package installation, after a directory name change, after directory structure change, etc. A dream package would solve this all and do the hard work: "There, that is the root(s) of all Emacs lisp, go and sniff all the directories and update load-path" That was what this package originally was all about. Nowadays it does a little more than that. Your load-path is updated automatically without any manual work. You only have to give the start ROOT path(s) of your installed lisp hierarchies in the file system. This package is highly effective: scanning thousands of files in a matter of seconds and once the cache has been created, it takes only a snap to load it in next sessions. All require and load commands execute also faster than previously, because the information about existing files is immediately available. The speedup is helped through advised functions.

      Overview of features

      Automatic load-path configuration

      Automatic Info-default-directory-list configuration

      If you have added new info files by hand, just call function tinypath-info-handler to update your Emacs and update the dir entry.

      Automatic manpath configuration

      Win32 Cygwin environment support

      Compressed lisp file support

      How to set up your load path

      The tinypath-:load-hook contains function tinypath-setup which starts examining all directories under load-path and tinypath-:load-path-root which is set to reasonable defaults of site wide and personal installations. If you keep all your lisp files under $HOME/elisp, then you do not need to configure anything for this package to work. Your load-path has been updated after this statement at the beginning of your $HOME/.emacs

            (load "~/elisp/tiny/tinypath")   ;; Or where you have it installed    

      If you have many separate Emacs lisp root directories, like one for site-lisp and one for site-packages and one for your personal lisp files, then you have add those to variable tinypath-:load-path-root. Below there is an example for PC users, where the E: partition replicates identical Unix tree structure. The following actually works for Unix too, because non-existing directories will be ignored:

            (setq tinypath-:load-path-root
              '("~/elisp"  "E:/usr/share/emacs/site-lisp/common"))
            (load "~/elisp/tiny/tinypath")    

      XEmacs and Emacs specific directories

      In spite of great effort from developers to make packages compatible for both Emacs platforms, there is always some packages that only works with Emacs or XEmacs. It is assumed that the site admin has created directories like these to keep the site-lisp installation clean:

            ;;   This might be also under /opt/share/site-lisp
            ;;   Refer to file hierarchy standard at
            ;;   http://www.pathname.com/fhs/
      
            /usr/share/site-lisp/common/   .. For XEmacs and Emacs
            /usr/share/site-lisp/emacs/    .. Packages only for Emacs
            /usr/share/site-lisp/xemacs/   .. Packages only for XEmacs    

      To take care of the Emacs specific load-path setting, use code similar to this snippet. If you load the setup multiple times, the pushnew ensures that the directories are not added multiple times.

            (require 'cl)
            (dolist (path ("~/elisp"
                           "/usr/share/emacs/site-lisp/common"
                           ;;  Select Emacs or XEmacs specific installations
                           (if (boundp 'xemacs-logo)
                               "/usr/share/site-lisp/xemacs"
                             "/usr/share/site-lisp/emacs")))
              (when (stringp path)
                (pushnew path tinypath-:load-path-root :test 'string=)))
      
            ;; PLEASE COPY VERBATIM. THERE ARE OPTIMIZATIONS
            ;; THAT ACTIVATE If YOU ADD THE PATH
            (pushnew "~/elisp/tiny/lisp" load-path :test 'stringp=)
            (load "tinypath.el")    

      In fact this package will check current emacs version and make sure that only correct directories are included to the load-path. If you simply instructed to search the whole site-lisp root /usr/share/site-lisp, and current emacs binary is "emacs", then all directories that contain path portion /xemacs are automatically , ignored.

      Building part of site-lisp using Net

      If we continue talking a bit more about site-lisp, there is utility mywebget.pl at <http://perl-webget.sourceforge.net/> The packaging file includes a mywebget-emacs.conf which contains knowledge where the various lisp developers' home pages are and how to download all known lisp tools that does not come with Emacs. If you have lot of disk space and you're interested in getting more lisp tools to go with your Emacs, follow the instruction laid out in mywebget.pl's project page.

      If you are further interested in Emacs packages, see CVS version available for Unix at <http://www.cvshome.com/> and for Win32 cvs will ship with the <http://cygwin.com> installation. With CVS you can track development os Tiny Tools, Gnus, BBDB and others very effectively (by minimizing network traffic) and in timely fashion. Here is suggestion there you could put all your CVS lisp downloads:

             /usr/share/emacs/site-lisp/net/cvs-packages    

      Now, the overall structure of whole site-lisp looks something like this:

                     ROOT/  ( /usr/share/emacs or equivalent )
                     |
                     +--site-lisp/
                        |
                        +--emacs/
                           |  ...Eamcs only files
                        |  +--packages/
                        |  |  +--pcl-cvs-2.9.9/
                        |  |  +-... and so on
                        |  +--win32/
                        |     +--gnuserv/
                        |     +-... and so on
                        +--net/
                        |  +--users/
                        |     +-LispDeveloperA
                        |     +-LispDeveloperB
                        |     +-... and so on
                        |  +--cvs-packages/
                        |     +--liece/
                        |     +--lookup/
                        |     +--ILISP/
                        |     +--jess-mode/
                        |     +--devel/
                        |     +--emacro/
                        |     +--tnt/
                        |     +--cc-mode/
                        |     +--mailcrypt/
                        |     +--bbdb/
                        |     +--gnus/
                        |     +-... and so on
                        +--common/
                        |     ...COMMON for both Emacs and XEmacs
                        |     =======================================
                        |     ...Packages that you find posted to the
                        |     ...gnu.emacs.sources and whose author's
                        |     ...do not have a homepage
                        +--xemacs/
                           |  ...XEamcs only files
                           +--cvs-packages/
                              +--xemacs-packages/    

      XEmacs 21.2+ core packages

      The recent XEmacs versions ship with only the very basic installation. Lisp packages are distributed in separate archive xemacs-packages (nick named SUMO due to its huge size). There is also mule-packages and site-packages archives. A built-in heuristics tries to guess the location of these by looking under and near your XEmacs installation:

            .../XEmacs/XEmacs-NN.N/xemacs-packages
            .../XEmacs/xemacs-packages    

      If the archives have been installed elsewhere, you have to tell the location by defining following variable prior loading TinyPath. You can't put these to tinypath-:load-path-root because this is special information that needs to present during the very initial boot-up to find crucial packages like jka-compr.el.

            (setq tinypath-:core-emacs-load-path-list
                  '("/usr/share/site-lisp/xemacs/xemacs-packages"
                     "/usr/share/site-lisp/xemacs/mule-packages"
                     "/usr/share/site-lisp/xemacs/site-packages"))    

      Finding load-path directories

      If you only used default $HOME/elisp directory for your files, the tinypath-:load-path-function starts recursively searching all the directories under the root(s) tinypath-:load-path-root. Not all directories are counted in when the search descends below the root(s). Variable tinypath-:load-path-ignore-regexp decides if the directory should be ignored. By default:

      Gnus and other 3rd party packages

            _NOTE:_ in the latest version *Gnus* is treated specially. All
            Gnus versions are detected along load-path and the very latest
            Gnus version is installed to your `load-path'. This is based on
            the knowledge in the `gnus-version' variable and the heuristics
            will pick the newest for you. You actually do not have to do
            anything else, but to drop latest Gnus somewhere, to be able to
            use it immediately.    

      It is important to understand how this package works: It caches every possible lisp directory it can find. Now, if you have installed private copy of Gnus, say in ~/elisp/cvs-packages/gnus, there is a problem, because Emacs distribution also includes Gnus. There is NO WAY TO TELL OR CHANGE path order when the cache is in use. This is a design decision and cannot be changed. The old trick, where a new directory was added in front of load-path, will not work because everything goes through cache. What you need to do instead, is to tell that the "other" Gnus should be ignored during cache creation, so that it is completely unknown.

      Solution: ignoring directories

      There is very simple way. Put your regular expression to tinypath-:ignore-file-regexp-extra and it will tell which directories to ignore. Naturally you must put the lisp code before you load package.

            (setq tinypath-:load-path-ignore-regexp-extra
                  "\\|[/\\]x?emacs[/\\0-9.]+[/\\]lisp[/\\]gnus")
            ;; PLEASE COPY VERBATIM. THERE ARE OPTIMIZATIONS
            ;; THAT ACTIVATE If YOU ADD THE PATH
            (require 'cl)
            (pushnew "~/elisp/tiny/lisp" load-path :test 'stringp=)
            (load "tinypath.el")    

      [For advanced Lisp programmers] You can add ignored gnus directory to tinypath-:load-path-ignore-regexp via tinypath-:load-path-ignore-regexp-hook. When the hook is run, the default value for tinypath-:load-path-ignore-regexp is already available. In hook, append regular expression that excludes the Gnus directory. Here is an example; make sure that you don't add the regexp multiple times. The multiple invocations is protected by setting a plist property and checking it. The ugly [\\/] makes the regexp compatible with both Unix and win32 paths. System directories in Unix are typically /emacs/NN.NN/ and in win32 /emacs-NN.NN/, that's why added "-".

            (add-hook 'tinypath-:load-path-ignore-regexp-hook
                      'my-tinypath-:load-path-ignore-regexp-hook)
      
            (defun my-tinypath-:load-path-ignore-regexp-hook ()
              ;;  Do this only once
              (unless (get 'my-tinypath-:load-path-ignore-regexp-hook 'set)
                ;; mark as done.
                (put 'my-tinypath-:load-path-ignore-regexp-hook 'set t)
                (setq tinypath-:load-path-ignore-regexp
                      (concat
                       tinypath-:load-path-ignore-regexp
                       "[/\\]x?emacs[/\\0-9.]+[/\\]lisp[/\\]gnus"))))    

      #todo: What about XEmacs public/private Gnus installations ?

      Updating new lisp packages

      Suppose you have installed a new version of a package:

            ~/elisp/gnus/pgnus-0.74/
            ~/elisp/gnus/pgnus-0.95/    ;; NEW    

      Both these directories end up being added to the load-path, but that is not preferable. It is the latest version that should be in the load-path. The solution is to move the old versions under some directory name that will be ignored by default. It is recommended that a backup of previous packages are renamed to start with a word "tmp-". All directories that start with prefix tmp are ignored, the problem has been solved. However if you update package in a site-lisp directory, there may be a distant problem that somebody needs older version of the package. If you made the backup like above, that user cannot load the old package any more, because it doesn't show up in load-path

            % mv ~/elisp/gnus/pgnus-0.74/ ~/elisp/gnus/tmp-pgnus-0.74/    

      There is no easy answer to keep old packages. Admin could announce that: "new version has been installed in DIR, the old one is in TMP-OLD-DIR" and have users manually arrange their load-path if needed. Following simple lisp command would solve their setup. The statement below adds the old directory to the beginning of load-path and thus load commands would find the old version of the package first.

            (load "~/elisp/tiny/tinypath")
            (pushnew TMP-OLD-OLD-DIR load-path :test 'string=)
            (tinypath-cache-regenerate)    

      Remember to mention to users that they need to update cache with tinypath-cache-regenerate (called with prefix argument) to see the changes.

      Duplicate files in path

      If you have accustomed to putting your path to specific order, you have to rethink your strategy if you are going to use this package. The philosophy behind creating this utility was: YOU SHOULD NOT NEED TO DO MANUAL WORK TO UPDATE PATHS. This means that the order of the paths must not be significant. Now, You may face a situation where you install a library or package that contains a file, which has already been installed to your hierarchy. Take for example, smtpmail.el:

            /usr/local/bin/emacs-20.4/lisp/mail/smtpmail.el
            /usr/share/site-lisp/common/packages/semi/flim-1.12.1/smtpmail.el    

      We have a problem here if FLIM's smtpmail.el is not compatible with the one in Emacs. If it is, then there is no problem. Either one can be loaded, and the load-path order does not matter. But you don't know that before you get error "function smtpmail-xxxx not defined" and you start investigating with (locate-library "smtpmail") which package is actually active.

      After installing tinypath.el package, please investigate your path with [C-u] M-x tinypath-cache-problem-report and see if you find many duplicate entries. Investigate each one and possibly move the file to another name or remove older ones. E.g. in the above situation, the cure might be moving FLIM's smtpmail.el under name flim-smtpmail.el so that it doesn't get loaded with (require 'smtpmail). The best is to contact the maintainer(s) and tell them about conflicts. Here is a sample of one generated problem report:

            imenu.el
              323 34073 1998-05-07 16:28:08 e:/usr/share/site-lisp/common/other/
              910 37169 1999-12-04 02:47:58 e:/usr/share/site-lisp/common/programming/java/jde/jde-2.1.6beta13/lisp/
              1350 38663 1999-11-28 01:14:38 e:/usr/local/bin/emacs/gnu-emacs/emacs-20.4.1/lisp/
            base64.el
              515  9943 1999-12-11 19:15:20 e:/usr/share/site-lisp/common/packages/gnus-5.8.2/lisp/
              807  9892 1999-11-15 00:00:12 e:/usr/share/site-lisp/common/packages/w3-4.0pre.46/lisp/    

      Explanation: User had used imenu as a separate package since early Emacs versions in "other" directory. The latest Emacs already ships with one, so it is best to delete the offending other/imenu.el. Keep on eye on the numbers here: The lower, the more close it is to the beginning of cache when the directories were searched. The Package with lowest score will get loaded. For base64.el there seems to be no problem. Gnus path has lowest score, it is the current latest development version, so it will get loaded before w3's base64.el . A simple major mode tinypath-report-mode is turned on for report buffer. Unnecessary files can be deleted with Control-shift-mouse-1 or C-c C-d.

      Symlinked directories are ignored

      It is traditional to use symlinks a lot in Unix to arrange easy access to versioned packages. Here is the traditional way how you can always refer to ~/elisp/gnus/ no matter what version is currently installed.

            ln -s ~/elisp/packages/gnus-N.NN  ~/elisp/packages/gnus    

      This package however skips those symlinks and records the absolute path name to the load-path. There are couple of points: a) it is more instructive to peek the load-path to actually see what versions have been installed to the Emacs b) The symlinks are error prone since there may be several symlinks that lead to same directory. In general, it is not a problem that the symlink directory is not included in the load-path. There may be one situation where symlink causes trouble for this package:

      If you draw a symlink to the the current directory from SEPARATE directory, then that directory will never be seen:

            ln -s ~/some-disk/elisp/artist-1.1/ ~/elisp/packages/artist-1.1    

      You shouldn't do this, instead either a) move the package physically under the ~/elisp/ from the ~/some-disk/elisp/ so that the recursive search will record it or b) add the separate directory ~/some-disk/elisp to the tinypath-:load-path-root.

      Using cache

      Now when you're freed from update burden of the directories in your disk, you can concentrate organizing the files under sensible directories. Here is an example how the organizing could go:

            ~/elisp/users/kevinr/       Kevin Rodger's files
            ~/elisp/users/ilya/         Ilya Zakharevich's files
            ..
            ~/elisp/packages/bbdb-2.00.06/  Version-ed packages
            ~/elisp/packages/psgml-1.0.3/
            ~/elisp/packages/pcl-cvs-2.9.2/
            ~/elisp/packages/tiny-19990215/
            ...
            ~/elisp/mime/               All MIME relates packages under this
            ~/elisp/mime/semi/          SEMI packages
            ~/elisp/mime/tm/            TM packages
            ...
            ~/elisp/lcd/                LCD (lisp code) hierarchy
            ~/elisp/lcd/misc/           http://www.cs.indiana.edu/LCD/
            ~/elisp/lcd/functions/
            ...
            ~/elisp/other/              All single add-on packages    

      All these paths in load-path and you can imagine how slow a standard Emacs would become: it takes even more time to find some package xxx, when Emacs sees a call (require 'xxx), because Emacs must start looking into every single directory under load-path until it can determine if it can or cannot load the asked package. This utility will store all lisp files in cache, and it is activated by default. The variable tinypath-:cache-expiry-days controls the interval when it is concluded that a new tree recursion is needed. If you install new packages during those non-expiry days, it is best to call C-u M-x tinypath-cache-regenerate to build up to date image of your files and load-path directories.

      If you want one short advice: always call tinypath-cache-regenerate after any lisp file or directory update.

      Cache file and different Emacs versions

      It is important that each Emacs loads correct cache file. The cache file's name is derived from the emacs version. The emacs type is "xemacs" "win32-xemacs" "emacs" or "win32-emacs".

              tinypath-:cache-file-prefix
            + EMACS-TYPE
            + HOST
            + EMACS-VERSION
            + tinypath-:cache-file-postfix
      
            ~/elisp/config/emacs-config-tinypath-cache-win32-HOST-emacs-20.4.1.el.gz
            ==========================================                        ======
            prefix                                                           postfix    

      Unix hosts and NFS mounts

      In Unix environment, it is also common that several hosts are NFS mounted so that your home disk is available from every server. The available programs are not usually NFS mounted, but programs are stored locally on each server's own disk. Now, there would be a problem if you logged to host A and started tinypath.el which had made cache in on host B, because A does not have the same directories as B did (site-lisp). This has been taken care of by including hostname part in the cache file name. For each host, a separate cache file is created. Now, suppose all the Unix hosts are same brand, say Sun OS, Linux, or HP-UX and a good administrator has separated the programs and the data in their own directory structures. Furthermore, these structures are NFS mounted and thus visible to the remote machines. In this scenario, it would not really matter to which host you log into, because you would always see the same programs and site-lisp directories and there would not be need for host specific cache files. In that case, disable the HOST word by writing a simple function which will return an empty string "":

            (setq tinypath-:cache-file-hostname-function '(lambda () ""))    

      Info file support

      In addition to updating the load-path, the recursive function has a chance to search for installed info files as well. When you keep all your site lisp under one directory, it is not uncommon that the bigger packages include documentation files in info format as well. Like:

            /usr/share/site-lisp/emacs/pcl-cvs-2.9.9/
            /usr/share/site-lisp/common/packages/psgml-1.2.1/    

      One possibility is that after you download and uncompressed package, you would copy the info file to some central directory where you keep all you info files. This is lot of manual work. (Never mind that in Unix you might use Makefile to install everything, in Win32 it's all manual work). This package do the same job by looking for directories that either have info files or a central info repository called dir. dir. If the repository has all the info files up to date, nothing is done. In other cases:

      The Info-default-directory-list is updated to include any new directory locations and they are saved to same cache file. When you call C-h i you will see the new info entries. Easy and maintenance friendly. No need to worry about supplied info files any more, they are automatically integrated to your Emacs. If you have installed any new packages to your system, Emacs packages or Unix packages that installed something with "install -c", it is best to update your info files with M-x tinypath-info-scan-Info-default-directory-list. This is also called if you call: C-u M-x tinypath-cache-regenerate

      Cygwin support (Win32 and woman.el)

      It is common that Emacs in Win32 environment is coupled with http://www.cygwin.com toolkit which contains all the manual pages for the unix commands and possibly new info pages. This package will locate cygwin1.dll file along PATH and recurse whole cygwin installation root to find new entries that can be used inside Emacs. In theory this all should happen automatically and the only thing you have to do is to ensure that you have proper PATH settings at your OS level before this package is started. If Cygwin /bin directory in in PATH, tinypath-:extra-path-root will get set to a correct value at boot time.

      If you have more places where you keep Unix tools which contain more manual or info pages, like Reed Kotler http://www.reedkotler.com/ you must manually set variable tinypath-:extra-path-root to the list of search root directories. If you set this yourself, you must also include the cygwin installation root directory

            (setq tinypath-:extra-path-root
                  '("e:/unix-root/cygwin"
                    "e:/unix-root/reed-kotler"
                    ...))    

      Package woman.el will be configured automatically if it is along load-path to handle manual page viewing with command M-x man. Please make sure that you do not destroy the pre-defined woman-manpath in your Emacs startup files with lisp commands or the efforts to find out new manual pages are thrown off the window. Search you startup files for anything that looks like setq, defvar, defconst: (setq woman-manpath ... and change the code to add to the variable instead:

            (require 'cl)
            (dolist (path '("one" "two" "three"))
              (pushnew (expand-file-name path) woman-manpath :test 'string))    

      Faster Emacs configuration (Perl emacs-util.pl)

      Indication of this feature at startup is following message, where EXT refers to externally launched process which must be waited until further processing is done.

            TinyPath: EXT Process running ... [may take a while]    

      As this package evolved and more support was added to various environments, like Cygwin, which requires traversing hundred of directories to find out if they contained info or manual pages, it came evident that Emacs Lisp method is too slow. An alternative method was developed using Perl language and script emacs-util.pl which can traverse directory hierarchies to find relevant directories for the setup. This interface is automatically used if two conditions are met in current environment:

      If all goes well, a call-process to the utility script will return the file hierarchies much faster than the Emacs Lisp ever could. The difference is that you don't see the traversing progress as you would if Emacs Lisp did the same thing. The command line arguments passed to the utility scripts can be found from the Message buffer and you can run the program yourself if you think that it returns incorrect listing. Print the script help with following command:

            % perl emacs-util.pl --help    

      Here are some performance statistics of the perl script in action. (Use --verbose argument to see the statistics)

      Let's consider one scenario that you may encounter if you intend to use Cygwin similarly as the big brother Linux. Let's suppose that you have dedicated a disk portion where you intend to duplicate whole Linux-like directory hierarchy. You have ROOT under which you keep all the files, including anything that is Cygwin-related.

            E:/usr/share/site-lisp      Emacs lisp as outlined earlier
            E:/usr/share/site-perl      Perl packages and scripts
            E:/usr/share/site-php       PHP code
            E:/usr/share/site-cvs       Various other external CVS C-packages    

      The default heuristics win32-cygwin-p should find cygwin1.dll installed and report that Cygwin root is E:/ This means that tinypath-:extra-path-root will get set for you when package loads. Suppose further that you have set variable tinypath-:load-path-root to point out suitable locations in E:/usr/share/site-lisp. It would seem that this combination means that the hierarchies would be traversed multiple times, since the Cygwin root already includes all the rest:

            E:/                             Cygwin root
            E:/usr/share/site-lisp/emacs    For this emacs...
            E:/usr/share/site-lisp/common   Emacs and XEmacs compatible tree    

      Don't worry. The Perl utility is smart enough to reduce this to search only E:/ and discard other roots as redundant. Hm, what if other lisp files are found outside of the E:/usr/share/site-lisp/, because it searches every dir starting from E:/ Say:

            E:/tmp/try/some-file.el    

      Will the directory E:/tmp/try/ reported as lisp load-path candidate and added to search list? Yes and no. Yes, it will be reported, but No, it will not be added to the load-path because it doesn't match the initial user's idea where to look for lisp files. If you pump up the tinypath-:verbose to level 5, you can see PATH-NOK messages labeled "candidate" to indicate those rejections. Only files that reside under tinypath-:load-path-root directories are counted in.

      Updating running Emacs

      Suppose you have downloaded the latest versions of packages X, Y and Z and you want your current emacs's paths updated. You can do this:

            M-x tinypath-cache-regenerate    

      A bit of skepticism: It is a fortunate event if it all worked that easily. You see, you already have several packages loaded in your Emacs and they are using the "old" code. Now you wiped the old directories away and told Emacs to look for only "new" directories. After a while you may run into bizarre dependency problems. I recommend that after any major package update, which contains lot of files (like Gnus), you:

      Compressed lisp file support

      IN ORDER TO USE THE FULL COMPRESSION SUPPORT FOR AUTOLOAD FUNCTIONS AS WELL, SET VARIABLE tinypath-:compression-support to symbol all. THE DEFAULT SUPPORT ONLY HANDLES require and load commands. You must set this variable before package loads.

      Jka-compr and this package

      jka-compr has native support to un/compress any file that have specific extensions. The handling is done via file-name-handler-alist and commands like these will load properly including any autoloads.

            (load "my-el.gz")    

      The obvious problem is that you have to manually go and change all you load commands so that they end in .gz so that jka-compr takes care of loading. What if you later uncompress the file? You have to go and update all the load commands in you Emacs startup files. This isn't very nice, since you should be able to un/compress elisp files whenever you wish and still have permanent statement like one below. Basically this is what the compression support here is all about; you don't have to worry if the file is compressed or not when these advised functions are in effect. The following statement will always work:

            (load "my-el")    

      How the compressed loading works

      Note: Why you should not prefer compressed .elc files

      The purpose of compression support is to make it possible to have more useful lisp files in an account that has a limited disk space (quota). Keeping lisp files in compressed format saves quite a much disk space.

      Note: advised emacs commands

      The adviced functions can be further adviced, but if the redefined function uses interactive-p test, it will not indicate user call (like M-x load-library). The reason why the advised functions detect it, is that advice.el's ad-do-it macro cannot pass the interactive flag information to the original functions.

      Trouble shooting

      There is no denying it, this package is dangerous. When something goes wrong, it really goes wrong and your Emacs is messed up completely. So, here are some trouble shooting tips, that you might want to try to rescue the situation or understand what is going on. The most usual blame is the cache content which does not contain the correct or up to date information.

      Package is not found or loaded?

      Please confirm that the file location is known and is in right directory by calling M-x locate-library. If the result is not correct, please check tinypath-:load-path-root and tinypath-:extra-path-root. Try to remedy the situation, regenerate cache with M-x tinypath-cache-regenerate.

      You don't know what particular package is causing troubles

      Go to the Message buffer and clear it (C-x h followed by C-w). Run the path generation engine with debug M-x tinypath-debug-external-helper and study the output. It may be ignoring some files that you think should be included. Please check content of tinypath-:load-path-ignore-regexp and tinypath-:load-path-ignore-regexp-extra.

      You need to see the internals

      Call function tinypath-cache-file-find-file to display the current Cache and use C-s and C-r to search entries in the file. Remember that you must not modify this file, because any changes you do, will get overwritten next time the cache is created. The problem is somewhere else if you can see incorrect settings in cache file.

      Code note: General

      Because this package is among the first that is loaded from Emacs startup file, It contains copies of some functions from TinyLib libraries, to make the package independent until the point where the load-path has been set up and other libraries are available. In the code you may find marks "#copy:" which indicate code that has been copied/simplified to be used here. Autoloads statements in this package defer loading functions until the end is reached and load-path is determined and the rest of the functions can be loaded from the libraries.

      Code note: Where is that emacs package

      If you ever need to know the location of a package that Emacs would load or has loaded, while this utility is in effect, use this call:

            (insert (tinypath-cache-p "gnus.el"))    

      In fact the regula call yields same result, because locate-library is adviced:

            (insert (locate-library ""gnus.el"))    

      More easily, if you have tinylisp.el, which takes advantage of tinypath.el cache, you can load any emacs package for editing with command:

            M-x load-library RET tinylisp RET
            M-x tinylisp-library-find-file
            (tinypath cache)Lisp Library: gnus.el RET    

      Alternatively there is mode hot-keys $ l f and $ l p :

            M-x load-library RET tinylisp RET
            M-x tinylisp-mode  (in *scratch* buffer, see "E" in modeline)
            $ l f
            (tinypath cache)Lisp Library: gnus.el RET    

      Code note: Internal optimizations

      In the installation section it is instructed that the location of the package is pushed into the load-path before the package is loaded:

            (require 'cl)
            (pushnew "~/elisp/tiny/lisp" load-path :test 'stringp=)
            (load "tinypath.el")    

      Please follow this instruction. The reason is that program tries to use most efficient code to boot everything up and the first thing it can do is to check the location where it has been saved. This package will use this information assume that the Perl program emacs-util.pl is available in ~/some/path/bin/emacs-util.pl. If that fails, the Perl program is searched along exec-path. This is usually desirable, situation because every new installation include newer version of emacs-util.pl and the one at exec-path may not be up to date. The perl code will speed up booting compared to pure Emacs Lisp implementation. In addition the Perl code section in this file (often referred as "external") has extra features included.

      Code note: *Messages*

      This package will print loads of messages to Emacs "*Message*" or XEmacs " Message-Log" buffer. This is a design decisions so that execution can be easily traced during Emacs load time. It also help reporting errors. The default tinypath-:verbose 3 will log the most important messages. Even if you set the level to 0 or nil, still some messages are displayed. Have a look at Message buffer if you have not much used it before. You may find interesting information to debug some of your own mis-configurations, like stale directories in exec-path.

      Code note: Custom

      If you have Emacs that does not contain custom.elc (Yes, it must be in compiled format, be sure to check), you can download Noah Friedman's excellent custom emulation package cust-stub.el at http://www.splode.com/~friedman/software/emacs-lisp/ You have to load it from absolute location before loading this packages like this:

            (load "~/elisp/noah/cust-stub")
            (load "~/elisp/tiny/lisp/tinypath")    

      Code note: Insinuating packages

      Some packages can be auto-configured when the perl script reads the contents of the directories. Like package woman.el which needs to know the location of man path directories. For other packages there are different "installations". Gnus is one interesting example: Every Emacs and XEmacs release comes with Gnus version, which is usually outdated and many install Gnus privately. The problem is multiple Gnus versions in the load paths and the wished situation is that there would be only the latest. there is experimental code to find out which of the Gnus packages along load-path is the latest and after making hopefully right decision (according to gnus-version-* variable) the other Gnus locations are hidden by modifying load-path and tinypath-:load-path-ignore-regexp. This is a complimentary method to that suggested in the manual section "3rd party packages".

      Code note: Elp profiling results 2001-03-01

      The profiling results were run using method below. It must be note, that the tinypath-external-* is the time when the external perl program examines all the directories, so EXT time is not significant because it varies from system to system. The tinypath-external-setup-parse-data is the actual time spent in parsing the returned data. The functions that are called most of the time are the ones that must be kept on eye on and they seem to perform very well. Immediate below are the most important functions that perform the Parsing after the perl has returned results (these are not from the total listing, but after tweaking)

            tinypath-external-output-parse                   1    4.89  4.89
              tinypath-external-output-parse-1               5    1.09  0.21
              tinypath-external-output-parse-1-cache         1    3.79  3.79
      
      
            tinypath-external-setup-parse-data               1    5.77  5.77
              tinypath-external-setup-1-load-path            249  0.70  0.002
              tinypath-external-setup-1-man-path             44   0.0   0.0
              tinypath-exec-path-append                      73   0.92  0.012
              tinypath-info-handler                          31   8.46  0.27
              tinypath-external-setup-cache                  1    0.0   0.0    

      The timing information was tested and generated with:

            Function Name                                    Count  Elap Ave
            ===============================================  ====  ===== =====
            tinypath-cache-regenerate                        1     78.11 78.11
            tinypath-cache-setup                             1     71.63 71.63
            tinypath-cache-setup-scan                        1     66.35 66.35
            tinypath-external-setup                          1     65.52 65.52
            tinypath-external-helper                         1     56.08 56.08
            tinypath-external-helper-call                    1     52.29 52.29
            tinypath-info-handler                            31    12.47 0.402
            tinypath-info-files-in-directory                 62    10.81 0.174
            tinypath-external-setup-parse-data               1     8.23  8.23
            tinypath-info-scan-Info-default-directory-list   1     6.48  6.48
            tinypath-info-directory-contents-update          31    4.07  0.131
            tinypath-external-output-parse                   1     3.79  3.79
            tinypath-external-output-parse-1-cache           1     3.63  3.63
            tinypath-load-path-clean                         3     3.25  1.083
            tinypath-directory-list-clean                    12    2.85  0.237
            tinypath-expand-file-name                        1493  2.59  0.001
            tinypath-file-extension-compressed               2584  2.47  0.000
            tinypath-ti::write-file-variable-state             1     1.38  1.38
            tinypath-cache-file-write                        1     1.38  1.38
            tinypath-external-setup-1                        1     1.21  1.21
            tinypath-path-ok-p                               995   1.10  0.001
            tinypath-cache-setup-clear                       1     0.77  0.77
            tinypath-external-setup-1-load-path              249   0.70  0.002
            tinypath-path-ok-this-emacs-p                    1604  0.38  0.000
            tinypath-exec-path-check                         1     0.33  0.33
            tinypath-exec-path-check-verbose                 1     0.33  0.33
            tinypath-external-output-parse-1                 5     0.16  0.032
            tinypath-exec-path-clean                         1     0.16  0.16
            tinypath-external-bin-location                   1     0.06  0.06
            tinypath-exec-path-append                        73    0.06  0.000
            tinypath-executable-find                         1     0.06  0.06
            tinypath-Info-default-directory-list-clean       2     0.05  0.025
            tinypath-external-setup-1-man-path               44    0.05  0.001
            tinypath-emacs-versions                          1     0.0   0.0
            tinypath-info-file-DIR                           31    0.0   0.0
            tinypath-cache-status-string                     1     0.0   0.0
            tinypath-cache-file-name                         1     0.0   0.0
            tinypath-emacs-lisp-file-list-cache-clear        1     0.0   0.0
            tinypath-cache-status-message                    1     0.0   0.0
            tinypath-time-string                             1     0.0   0.0
            tinypath-use-compression-maybe                   1     0.0   0.0
            tinypath-directory-up                            1     0.0   0.0
            tinypath-self-location                           1     0.0   0.0
            tinypath-external-setup-cache                    1     0.0   0.0
            tinypath-info-handler-DIR                        31    0.0   0.0
            tinypath-exec-path-from-path                     1     0.0   0.0    

      Todo


      Tinyperl.el --- Grab-bag of Perl related utilities. Pod documentation

      Preface, march 1998

      Perl was quite new in 1994 and perl programs imported libraries using require command. Some time passed and the new Perl 5 was a complete rewrite. It introduced new Object and reference technologies to language but lot of perl coders couldn't grasp the new ideas immediately. Many made the decision to move to perl 5 only after it was mature enough. The perl 5 coding was so much cleaner and simpler compared to perl 4.

      As a result some additional Emacs functions were needed the Perl work going and this module more or less concentrates on helping to document perl programs with POD or getting perl man pages via perldoc interface. The other companion that you would already know is the cperl-mode which is the best mode for coding the perl language.

      Overview of features

      In Windows, both Activestate Perl and native Cygwin perl are supported. But you cannot use both. If you have accustomed to Activestate Perl, you may consider moving to Cygwin Perl, because it is more close to the Unix Perl where you can even use "perl -eCPAN -e shell" to install modules directly from CPAN.

      Sorry to tell you, but multiple perl installations are not supported. The one that is in your path first is used. Perl advances each time so much that you're much safer if you always have the latest version. This is true with Java and Python as well.

      tinyperl-mode minor mode:

      Other minor modes:

      Package startup

      At package startup the perl binary's tinyperl-:perl-bin @INC content is cached. If you have modules somewhere else than the standard @INC, then add additional -I switches to the tinyperl-:inc-path-switches so that these additional paths are cached too.

      In addition the Perl POD manual pages and paths are cached at startup. This is derived from Config.pm module $Config{privlib}.

      If you need to change any of the above settings in environment during the session, reload package or call tinyperl-install to update the changed values.

      Saving TinyPerl state (cache)

      When the package is used for the first time, the Perl @INC is read and all .pl and .pm files along the path are cached and written to file tinyperl-:cache-file. Next time this package is loaded, the cache file is read. This speeds up package initialization next time.

      If you upgrade Perl or add new packages along @INC, you must rebuild the cached information and have it updated to tinyperl-:cache-file. You do this by calling tinyperl-install with a prefix argument (e.g. C-u).

      The cache information is expired periodically, so it should keep up with the environment changes quite well. The default cache period is 7 days, but this can be set via tinyperl-:cache-file-days-old-max.

      Perl Minor Mode description

      Turning on tinyperl-mode in any buffer gives you commands to retrieve Perl's POD (Plain Old Documentation) pages. This is most useful with the programming mode perl-mode. Function turn-on-tinyperl-mode is also added to hooks perl-mode-hook and cperl-mode-hook by default. The list of key below may be not completely up to date, so consult C-h f tinyperl-mode.

            C-c ' f             tinyperl-pod-find-file
            C-c ' F             tinyperl-pod-find-file-this-buffer
            C-c ' P             tinyperl-pod-by-module
            C-c ' P             tinyperl-pod-by-manpage
            C-c ' k             tinyperl-pod-kill-buffers
      
            C-c ' m             tinyperl-module-find-file
            C-c ' d             tinyperl-perldoc
            C-c ' g             tinyperl-pod-grep    

      POD view mode description: navigating in pod page and following URLs

      When pod is loaded to buffer, another package, tinyurl.el, is turned on. It can track several different kind of URLs, including perl pod manpages for references like:

            See perlfunc manpage
                ^^^^^^^^^^^^^^^^
      
            See [perltoc]
                ^^^^^^^^^
      
            Devel::Dprof manpage
            ^^^^^^^^^^^^^^^^^^^^    

      You can use mouse-2 at the point to jump to the referenced POD page. Wait couple of seconds at the current line and any references or URLs found are marked. If you do not want to use TinyUrl package, add this setup:

            (add-hook tinyperl-:load-hook 'my-tinyperl-:load-hook)
      
            (defun my-tinyperl-:load-hook ()
              "My TinyPerl customisations."
              (remove-hook 'tinyperl-:pod2text-after-hook
                           'turn-on-tinyurl-mode-1))    

      In pod buffer where the pod documentation is displayed, an additional browsing mode, tinyperl-pod-view-mode, is turned on to help moving around topics. If you find the PgUp keys non-customary, see variable tinyperl-:key-pageup-control.

            ;;  moving down/up topics
      
            PgDown              tinyperl-pod-view-heading-forward
            PgDown              tinyperl-pod-view-heading-backward
      
            S-PgDown    tinyperl-pod-view-heading-forward2
            S-PgDown    tinyperl-pod-view-heading-backward2
      
            ;; Moving down/up one pod page at a time
            ;; The pod pages are all gathered to single buffer *pod*
      
            Meta-PgDown tinyperl-pod-view-forward
            Meta-PgUp   tinyperl-pod-view-backward
      
            ;;  The normal PgUp/Down command is available here
      
            Control-PgDown      scroll-up
            Control-PgUp        scroll-down    

      By default the POD documentation is kept in a single buffer where you can conveniently use C-s and C-r searches. If you would like to use separate POD buffers instead, a la M-x man, set variable tinyperl-:pod-buffer-control to 'many. The opposite is 'single.

      POD Write mode description

      There is additional minor mode to help you write POD in the current buffer The minor mode is in function tinyperl-pod-write-mode and you can switch to it any time you're adjusting the pod section. Don't keep on all the time, since it occupies some keys that are normally needed in programming.

            PgDown      tinyperl-pod-write-heading-forward
            PgUp        tinyperl-pod-write-heading-backward    

      With shift

            PgDown      tinyperl-pod-write-token-forward
            PgUp        tinyperl-pod-write-token-backward    

      Inserting default POD templates for program

            C-c . m     tinyperl-pod-write-skeleton-script-manpage
            C-c . f     tinyperl-pod-write-skeleton-script-function
            C-c . i     tinyperl-pod-write-skeleton-item    

      Inserting default POD skeletons for Modules or Classes.

            C-c . B     tinyperl-pod-write-skeleton-module-header
            C-c . E     tinyperl-pod-write-skeleton-module-footer
            C-c . F     tinyperl-pod-write-skeleton-module-function    

      POD skeleton for functions (C-c . F) is very different from the Module skeletons. This due to fact, that a Module offers documented function interface and the user callable functions should be described separately with POD in order to print the manual of the module.

      The POD skeletons for Modules are based on following Module layout. This is my only a suggested layout, see Lingue::EN:Squeeze.pm for complete first hand example. The places below where you see "P O D" are the places where you add pod. For each, a different pod skeleton is inserted and when the whole file is printed, it gives nice and maintainable interface description.

      There is another group of people that prefer writing the whole documentation after the _END_. It has drawback that then you separate the descriptions from the actual place where the code resides. The idea here has been that the documentation (function) is kept immediately above the code: if you change it (function), you can update the documentation at the same place.

      In the other hand, by putting documentation after _END_, the load time of module is decreased, because POD text is never read by perl interpreter. Another point to keep in mind is, that the computing power and disk speed will increase, so the _END_ solution's benefit is neglible. The maintenance is easier when the documentation is not separated from the place where it would be the most natural (nearest to the code).

            F I L E   B A N N E R
      
            P O D  H E A D E R
            NAME
            REVISION
            SYNOPSIS
            DESCRIPTION
            EXPORTABLE VARIABLES
            EXAMPLES
      
            #   module interface is written next
      
            use strict;
      
            BEGIN
            {
                  .. EXPORT          # The export interface
                  .. EXPORT_OK
            }
      
            Define exported globals
      
            Define private variables
      
            P O D   I N T E R F A C E   S T A R T
      
            P O D  P U B L I C for public functions or method
            sub ...
      
            NORMAL banner of private function
            sub ...
      
            P O D   F O O T E R
            KNOWN BUGS
            AVAILABILITY
            AUTHOR
      
            1;
            __END__    

      Perl SelfStubber

      If you're developing Perl modules, you can make it to use autoload interface. Module compiles much faster and it delays loading of functions until they are called. You can read about SelfStubber from the Module page Devel::SelfStubber.pm which links to SelfLoader.pm, which is (one file) to my opinion better autoload choice than Autoloader.pm (splits file to many files by function)

      To use SelfStubber with this package, you need to arrange your module to read like below. Notice the "BEGIN:" and "END:" comment-tokens are for function tinyperl-selfstubber-stubs, which will fill in the section with the right stubs.

      If you don't have "BEGIN: Devel::SelfStubber" and "END: Devel::SelfStubber" sections in your file, calling tinyperl-selfstubber-stubs prints the found stubs in separate shell buffer.

            package MyClass;
      
            use Exporter;
            use SelfLoader;
            use vars qw( $VERSION @ISA @EXPORT @EXPORT_OK );
      
            @ISA    = qw(Exporter);
      
            @EXPORT = qw( .. );
      
            $VERSION = ..
      
            # BEGIN: Devel::SelfStubber
      
            # END: Devel::SelfStubber
      
            1;
            __DATA__
      
            <implementation: functions and variables>
      
            __END__    

      Updating the VERSION variable

      If you plan to submit your perl module or program to the CPAN at http://cpan.perl.org/ the upload criteria is that your file must have a version number. The traditional method has long used some version control software's number (those of CVS or RCS etc.), but it really doesn't tell much to the user. It might tell something to the developer, but from user's point of view, he is much more interested in knowing when the file was last updated. The version number 2.77 may be two years old.

      Where is that variable used? The MakeMaker perl module (that you use when making packages ready to CPAN upload) reads the first variable named VERSION and names your release according to it.

      Consider to use two version numbers: one for the release and one for the kit name. In order to MakeMaker to pick up the version number for a kit (tar.gz release, that is, for the user), it must see a VERSION variable. You can store the (a) version control software's number at the beginning of file inside comments and the (b) release number to a perl variable.

            # @(#) $Id: index-body.html,v 1.2 2008/09/15 12:59:37 jaalto Exp $
      
            use vars qw ( $VERSION );
      
            #   This is for use of Makefile.PL and ExtUtils::MakeMaker
            #   So that it puts the tardist number in format YYYY.MMDD
            #   The REAL version number is defined later
            #
            #   The following variable is updated by Emacs setup whenever
            #   this file is saved
      
            $VERSION = '2007.0909';    

      If the VERSION variable uses number format NNNN.NNNN, then it is assumed to contain ISO 8601 date YYYY.MMDD and this package will update the $VERSION variable's date every time file is saved (see write-file-hooks and tinyperl-version-stamp).

      Submitting your perl script to CPAN

      In addition to archiving your Perl libraries to CPAN, you can also submit perl scripts there. In order to get your submission right refer to page:

            http://www.perl.com/CPAN-local//scripts/submitting.html    

      The most important point is that your script includes pod that describes your script. It must contain at minimum the headings README, SCRIPT CATEGORIES, COREQUISITES, OSNAMES which are already included in the default pod skeleton via command

            `tinyperl-pod-write-skeleton-script-manpage'    

      Here is code that that can be used in Perl programs to print out the pod documentation when --help option is requested (Use Getop::Long.pm). The code works for both Win32 and Unix Perl implementations. The variable $LIB identifies the "group" where the function belongs, in this case it is program, while it could have been a Perl library module too. You set global $LIB variable at the beginning of file with:

            use English
            use File::Basename;
      
            use vars qw( $LIB );
            $LIB = basename $PROGRAM_NAME;    

      Here is the help function written with POD (perl 5.004 or higher)

            <  Create this Help() function banner with mode key           >
            <  C-c . f   or `tinyperl-pod-write-skeleton-script-function' >
      
            # ***************************************************************
            #
            #   DESCRIPTION
            #
            #       Print help and exit.
            #
            #   INPUT PARAMETERS
            #
            #       $msg        [optional] Reason why function was called.-
            #
            #   RETURN VALUES
            #
            #       none
            #
            # ***************************************************************
      
            =pod
      
            < This part: appears after you have called                  >
            < C-c . m  or  `tinyperl-pod-write-skeleton-script-manpage' >
      
            =cut
      
            sub Help (;$)
            {
                my $id  = "$LIB.Help";
                my $msg = shift;  # optional arg, why are we here...
      
                pod2text $PROGRAM_NAME;
      
                print $msg if $msg;
      
                exit 1;
            }    


      Tinyprocmail.el --- Emacs procmail minor mode. Lint code checker.

      Preface, Sep 1997

      Procmail may revolutionize your daily email management. If receive 10-25 Spam messages per week, you may start to wonder if there automatic way to handle mail, so that Spam never lands on your inbox, $MAIL. Procmail is the answer. You can use it to pre-filter all mailing list messages without bloating the primary inbox. You may already use Gnus to read the mailing lists, but the mail splitting work is best handled by procmail. Why? Because procmail is always running, while your Emacs and Gnus isn't. Procmail processes incoming messages as soon as they are received and takes care of them, like forwarding those UBE messages to appropriate postmasters, if you had written such recipe to your $HOME/.procmailrc

      What is Procmail?

      [Excerpted from the procmail faq] Procmail is a mail processing utility, which can help you filter your mail; sort incoming mail according to sender, Subject line, length of message, keywords in the message, etc; implement an ftp-by-mail server, and much more. Procmail is also a complete drop-in replacement for your MDA. (If this doesn't mean anything to you, you don't want to know.) Learn more about procmail at http://www.procmail.org/

      Some terms

      [Excerpted from the Email Abuse FAQ]

      UBE = Unsolicited Bulk Email.
      UCE = (subset of UBE) Unsolicited Commercial Email.

      Spam = Spam describes a particular kind of Usenet posting (and canned spiced ham), but is now often used to describe many kinds of inappropriate activities, including some email-related events. It is technically incorrect to use "spam" to describe email abuse, although attempting to correct the practice would amount to tilting at windmills

      Overview of features

      Quick reference

      Required packages

      Writing the procmail code

      The coding functions are provided by other modules. The tab key advances 4 characters at a time, and minimalistic brace alignment is supported when you press tab before the ending brace.

            TAB     tinytab-tab-key                         tinytab.el    

      The RET autoindents, but this can be turned off by calling

            C-c ' RET   tinytab-return-key-mode    

      Whole regions can be adjusted with commands

            C-TAB   tinytab-indent-by-div-factor         -->
            A-S-TAB tinytab-indent-by-div-factor-back    <--
            C-c TAB tinytab-indent-region-dynamically    <-->    

      Jumping to matching brace or matching parentheses

            %               tinymy-vi-type-paren-match    

      Tabs and spaces

      When the procmail mode is active, the tab key does not produce a tab character, but sufficient amount of spaces. There is a reason for this, mostly due to Lint parser which has to move up and down columnwise when checking the code. The movements can't be done if the code includes tabs. If you need a literal tab in your regexps, you can get it with standard emacs way 'C-q` TAB.

      Aligning the lines that have backslashes.

      In procmail, you use backslashes a lot, like in the following example. The backslashes here are put after each line, but this construct is error prone, because if you later on add new echo commands or otherwise modify the content, you may forget to update the backslashes.

            :0 fh
            * condition
            | (formail -rt | \
               cat -; \
               echo "Error: you requested file"; \
               echo "that does not exist";\
               ) | $SENDMAIL -t    

      To fix this code block, you can use command C-c ' \ or tinyprocmail-fix-backslashes-region. It would have been enough to write the first backslash and then call C-c ' \ and the rest of the backslashes would have been added below the same cloumn.

            :0 fh
            * condition
            | (formail -rt |                                    \
               cat -;                                           \
               echo "Error: you requested file";                \
               echo "that does not exist";                      \
               ) | $SENDMAIL -t    

      Rules on how to write Procmail recipe

      In order to use the linting service, This package requires that you write your procmail code in following manner. These rules are needed, so that it would be possible to parse the procmail code efficiently and more easily.

      [recipe start]

            :   # (old way) although legal procmail, illegal here. Use :0    

      [flag order]

      In order to autocorrect read flags from the buffer, the flag order must be decided: and here is the de facto order. The one presented in the procmail man page "HBDAaEehbfcwWir" is errourneous, because flags "aAeE" must be first, otherwise it causes error in procmail (heresay). The idea here is that the most important flags are put to the left, like giving priority 1 for aAeE, which affect the receipe immedately. Priority 2 has been given to flag f, which tells if receipe filters somthing. Also (h)eader and (b)ody should immediately follow f, this is considered priority 3. In the middle there are other flags, and last flag is c, which ends the receipe, or allows it to continue."

            :0 aAeE HBD fhbwWirc: LOCKFILE
               |    |   |  |   |
               |    |   |  |   (c)ontinue or (c)opy flag last.
               |    |   |  (w)ait and Other flags
               |    |   (f)ilter flag and to filter what: (h)ead or (b)ody
               |    (H)eader and (B)ody match, possibly case sensitive (D)
               The `process' flags first. Signify (a)ad or (e)rror
               receipe.    

      Every recipe starts with :0 flags:, but if you prefer :0flags: more, you can use following statement. This 'flag-together (or not) format is automatically retained when everytime you call lint.

            (setq tinyprocmail-:flag-and-recipe-start-style 'flags-together)    

      [lockfile]

      The lockfile names must be longer than two characters. Shorter lockfile name trigger an error. Also lockfile must have extension $LOCKEXT or .lock or .lck; no other non-standard extensions are allowed. The lockfile name must be within charsert [-_$.a-zA-Z0-9/] and anything else is considered as an odd lock file name.

            :0 : c          # Error, should this read :0 c: instead?
            :0 : file       # Invalid, should read "file.$LOCKEXT"
            :0 : file.tmp   # Invalid, non-standard extension.
            :0 : file=0     # Invalid filename (odd characters in name)    

      [condition line]

            * H B ?? regexp # valid procmail, llegal here: write "HB"    

      [Variables]

      The literal value on the right-hand side must be quoted with double quotes if a simple string is being assigned. If there is no quotes or backticks, then Lint assumes that you forgot to add variable dollar($). Try to avoid extra spaces in the variable initialisation construct too :-.

            DUMMY  = yes        # Warning, did you mean DUMMY = $yes
            VAR    = ${VAR:-1}  # No spaces allowed: "$ {" is illegal.    

      [program names]

      Program sendmail must be named sendmail, but it can also be variable $SENDMAIL. Similarly, program formail must be named formail or it can be variable $FORMAIL. Use of $MY_SENDMAIL or $MY_FORMAIL are illegal and cause missing many lint checks.

      [commenting style]

      In recent procmail releases you're allowed to place comments inside condition lines. Lint will issue a warning about this practise if your procmail version does not support this. But while you may place comments inside conditions, they should be indented by some amount of spaces. The default indent is 4 spaces.

            * condition1    --> * condition
            # comment               # comment
            # comment               # comment
            * condition2        * condition    

      This is recommended for readability (separating conditions from comments) and Lint will fix these comment misplacements.

      [redirecting to a file]

      If you print something to file, then the shell redirection tokens > and >> must have surrounding spaces, otherwise they are not found in the procmail code. (because > can be used in regexps)

            :0 :
            | echo > test.tmp       # Do not use "echo>test.tmp"    

      Linting procmail code

      Writing procmail recipes is very demanding, because you have to watch your writing all the time. Forgetting a flag or two, or adding unnecessary flag may cause your procmail code to work improperly. The Lint interface in this module requires that

      To help Linting you procmail code, there are two functions

            C-c ' l         tinyprocmail-lint-forward
            C-c ' L         tinyprocmail-lint-buffer    

      These functions check every recipe and offer corrective actions if anything suspicious is found. If you don't want to correct the recipes, you can pass prefix argument, which gathers Lint run to separate buffer. In parentheses you see the buffer that was tested and to the right you see the program and version number. In this buffer you can press Mouse-2 or RET to jump to the line.

            *** 1997-10-19 19:37 (pm-test.rc) tinyprocmail.el 1.10
            cd /users/foo/pm/
            pm-test.rc:02: Error, Invalid or extra flags.
            pm-test.rc:10: Error, Invalid or extra flags.
            pm-test.rc:10: info, Redundant `Wc:' because `c:' implies W.
            pm-test.rc:11: String `>' found, recipe should have `w' flag.
            pm-test.rc:15: info, flag `H' is useless, because it is default.    

      The output buffer can be sorted and you can move between blocks with commands

            sl      tinyprocmail-output-sort-by-line
            se      tinyprocmail-output-sort-by-error
            b       tinyprocmail-output-start
            e       tinyprocmail-output-end    

      Lint: auto-correct

      In many cases the Lint functions are able to autocorrect the code: answer y to auto-correct current point. If you want to correct the place yourself, then abort the Linting with C-g and fix the indicated line.

      Lint: directives

      Most of the time the Lint knows what is best for you, but there may be cases where you have very complex procmail code and you know exactly what you want. Here are the Lint directives that you can place immediately before the recipe start to prevent Lint from whining. The word Lint: can have any number of surrounding spaces as long as it is the first word after comment.

            # Lint: <Lint flags here>
            :0 FLAGS    

      The comment must be in the previous line, the following is not recognized.

            # Lint: <Lint flags here>
            #   I'm doing some odd things here and ....
            :0 FLAGS    

      Here is list of recognized Lint directives. each directive must have leading space.

      Lint: error messages

      The error messages should be self-explanatory, but if you don't understand the message, please refer to pm-tips.txt file available from main procmail site.

      info, backticks in var init. Not a recommended practise
      See pm-tips.txt and section that talks about variable definitions.

      Lint: batch mode from command line

      You can also lint the procmail files from command line prompt like this. (You must have Emacs 19.30+ which has working -eval)

                % emacs -batch -q -eval                                     \
                   '(progn (load "cl") (push "~/elisp" load-path)           \
                    (load "tinyprocmail" )                                        \
                    (find-file "~/pm/pm-test.rc")                           \
                    (tinyprocmail-lint-buffer-batch)                                \
                    ) '    

      Change the filename "~/pm/pm-test.rc" to the file being linted. The Lint results will appear in file tinyprocmail-:lint-output-file which is ~/pm-lint.out by default. Below you see a shell script to run the above command more easily. Rip code with ti::package-rip-magic #!/bin/csh -f # @(#) pm-lint.sh – LINT A procmail batch lint with emacs tinyprocmail.el # # $Docid: 2002-01-30 Jari Aalto $ # set file = $1 # set EMACS = xemacs-19.14 set out = $HOME/pm-lint.lst # # notice all these 3 lines must be concatenaed together! There must be # no \ continuation characters. to the right. # $EMACS -batch -q -eval '(progn (load "cl") (push "~/elisp" load-path) (load "tinyprocmail") (find-file "'"$file"'") (tinyprocmail-lint-buffer-batch) ) ' 2>&1 $out # # end of pm-lint.sh

      Highlighting

      Just couple of words about the chosen regexps for procmail code. Notice, that if you make a mistake, the dollar($) in front of identifier is not highlighted. This should help with spotting errors by eye better.

            $VAR = ${VAR:-"no"}     # Error, extra $ to the left.
             ===    


      Tinyreplace.el --- Handy query-replace, area, case preserve, words

      Preface 1995

      I saw post in gnu.emacs.help where brianp@ssec.wisc.edu (Brian Paul) asked for help to replace his C variables: "Suppose I want to replace all occurances of the variable i in my C program with j." The normal emacs function query-replace wasn't suitable for this task because it offered too many false hits. (Guess how many i characters are used in non-variable context!).

      Well later I rembered that one could have used \bi\b to search words. But the nature of "word" is very different here as it would have been with \b, which relies on syntax table which you seldom want to change, whilst the "word definition " here can be changed on the fly. (Remember that \bi\b still matches entries like "i.here" where you would want to match only plain "i")

      Things are not that simple always, in fact, the first implementation of this package had to do with the latex math equation replace, so that program would automatically skip over normal text and perform replace within the blocks only. I think the engine offers lots of other usages too.

      I decided to pull out the v1.0 and make it a complete package, so here you are folks.

      Overview of features

      How to use

      If you know lisp, you can go and take straight advantage of the engine function:

            tinyreplace-replace-region-1    

      Normally functions work within area defined by you, but there is 'applications' section which offers several ready to run functions for various needs:

            tinyreplace-replace-region     ;like query replace but in selected area
            tinyreplace-replace-forward    ;start from current point.
      
            tinyreplace-latex-blk-replace  ;replacer text surrounded by latex BLOCKS
            tinyreplace-latex-math-replace ;replace text within latex
                                           ;math equations only.    

      What commands do I have while replacing interactively?

      There is some handy commands that normal emacs replace lacks

      See function tinyreplace-replace-region-1 for command explanation. To abort the search, you just press Ctrl-g or 'Q' and you'll be returned to the starting point of search.

      Command line prompt explanation

      The command line prompt will look like this

            Replace 'xx' with 'yy' (a,bvuBFNU? [+CSX] !ynqQ)    

      Where the flag settings active are displayed between brackets. + means that you have used (N)arrow command, C indicates case sensitivity, S tells that symmetry is activated and X means that line exclude is oboeyed. For full explanation of the commands, please press

      ?

      Which will print the command summary and explanation momentarily.

      Special commands in command line

      When you edit the Seach string or destination string, there is some keys that you can use.

            C-l     Yank the text under point to current prompt
            C-o     Yank previous SRING1    

      The Yank command is C-l not C-y, because if you edit and kill inside the promt line, you can use regular C-y to yank text back. The C-l command reads a space separated text from the buffer and pastes it into the prompt for editing.

      The C-o command yanks the SEARCH string to the prompt. It comes handy if you used C-l to yank the initial search string, edited yanked text and wanted to share it in the next prompt. This way you don't have to do the editing again, but only modify the previous string. To pick right word (Yank C-l) from the buffer, when you don't have have mouse, you can use following keys. Text to the left shows you briefly where the point currenly is.

            <           Moves buffer's point backward
            >           Moves buffer's point forward    

      This feature propably is at its best in a compile buffer where you have grep results and you draw region around the the files where you want the replace to happen. Move a little with [<>] and you will be soon in a line that has the grep word, then yank it to the replace prompt.

      Note about the arrow pointer

      Terminals that do not have highlight capability to see which portion of text will be replaced will appreciate the arrow at the beginning of line to show where the text is located.

      The option "a" that refreshes the arrow marker is forced to ask a minibuffer question in order to change the state of arrow (hide or show). I found no other way to do this and I think it's a bug in 19.28 emacs, because the state is not immediately shown in buffer.

      Drop me a mail if you know how to do the updating without using the extra read-from-minifuffer "Refresh arrow.." question.

      Note about commands

      The commands are hard wired in this module and you cannot add new ones as you can in replace.el which is minor-mode based. This package is meant to be companion to replace.el, and for that reason the interface has been designed to be as simple as possible without any additional modes.

      If you need some new command, please mail author directly. There is no plan to convert this module to minor mode.


      Tinyrmail.el --- RMAIL add-ons, pgp, mime labels, Spam complaint.

      Preface, overview of features

      1998-01: I no longer use RMAIL, but Gnus, and support for this module is questionable. If you're using RMAIL or considering using it, please strongly think if you could use Gnus instead. I've written another module tinygnus.el whehre I can provide better support than for this on.

      Description

      This little package offers some autmatic detection of PGP MIME mails: It attaches labels to your incoming mails. There is also new summary function, which enables you to make a query by ANDing the labels in your RMAIL.

      This means, that you can now classify your message, like this:

            BASE
            SUBSET-IDENTIFIER
                  MINOR-IDENTIFIER
                     NOTE-IDENTIFIER    

      Eg. For PGP mails I have

            {pgp}
            {pgp,v}         -- verified signature
            {pgp,u}         -- not verified
            {pgp,v,e}       -- verified and encrypted    

      The normail rmail's summary function gives you the OR summary, which would mean, that if you wanted symmary by {pgp,v}, it would give you all mail that has either {v} or {pgp} somewhere. Well, this summary is not suitable if you use one CHAR to denote attributes of your base-identifiers (multichar)

      Automatic deletion of incoming mail

      There is default function to mark messages as deleted according to regexp. Please configure this variable to suit your needs:

            tinyrmail-:delete-regexp    

      If you want more personal control whether the mail should be deleted or not, please remove the default delete function and add your own:

            (add-hook 'tinyrmail-:load-hook 'my-tinyrmail-:load-hook)
      
            (defun my-tinyrmail-:load-hook ()
              "Cancel some default settings and modify parameters."
              (remove-hook 'tinyrmail-:get-new-mail-hook
                           'tinyrmail-delete-function)
              (add-hook    'tinyrmail-:get-new-mail-hook
                           'my-rmail-delete-function))
      
      
            (defun my-rmail-delete-function ()
             ...)    

      Replying to UBE aka spam messages

      The spamming has become a very serious promlem in private email communication. Not only the spammers send mail to newsgroups, but they are harrashing private mailboxes as well.

      With this package you can send reply to a spammer and complaint to all postmasters that have allowed the spam mail to travel through their networks. The addresses are parsed from the Received headers of the message and verified by nslookup. ou can turn off the nslookup if you wasn't faster response, but this may result bounched messages back to you.

            (setq tinyrmail-:ube-use-nslooup t)    

      So that you don't sned complaint to your local admin and not to some other known middleman domain (like forwarding service), you shoul also set following variable to regular expression to reject some addresses:

            (setq tinyrmail-:ube-ignore-site-regexp
                  "YOUR-SITE\\|155\\.0\\.233")    

      The text to the beginning of message is read from file pointed by tinyrmail-:ube-message-file.

      New commands in RMAIL

      Refer to function tinyrmail-define-default-keys for exact setup. Currently the only new command added is

            "L" tinyrmail-rmail-summary-by-labels-and
            "U" tinyrmail-ube-send-to-postmasters
                UBE = Unsolicited Bulk Email    

      Fixing RMAIL format

      Sometimes you may get following error after you have hit "g" to get new mail: "Cannot convert to babyl". The reason for this behavior is still not quite clear to me, but the cause is in the incoming message that does not have

            From    

      Field at the beginning of message. I have seen even some garbage Prepended to field so that it looked like

            m?From    

      What have to start editing the RMAIL file directly to fix its format. Change the mode to text-mode, run M-x widen and search the last message that rmail was not able to read. You will easily find the point where "** EOOH" markers do not appear any more.

      Now starts the fixing part to make rmail happy again:

      After you have converted all headers to rmail format, you can start rmail again with command

            M-x rmail-mode    

      If you made any mistakes, rmail will let you know and you have to repeat the header fixing again. (possibly removing the prevous EOOOH markers and reconverting them). We aren't quite finished yet. You see, on error, rmail leaves the read mail into your home directory. Please check that

            ~/.newmail-USERNAME    

      file doesn't contain any new message that aren't already in your RMAIL buffer. If there is only old message, delete that file. Now we have finished and you can again use "g" to get new mail.

      Standard Rmail distribution changes

      This package changes the standard Rmail distribution sligtly and here summary. If you want to disable these features or only use some of them, you have to put separate configuration to your .emacs. To disable forms:

            (setq tinyrmail-:load-hook '(tinyrmail-install))    

      To disable advices, you do

            (setq tinyrmail-:load-hook '(tinyrmail-install my-tinyrmail-install))
      
            (defun my-tinyrmail-install ()
              (ti::advice-control
                '(rmail-show-message
                  rmail-summary-enable
                  rmail-summary-next-msg
                  )
                 "^tinyrmail"
                 'disable
                 ))    

      tinyrmail-:forms-rmail

      Advices:

      rmail-show-message active

      The message's headers are now always reformatted. If you change variable rmail-ignored-headers, the old messages are not affected until you "t"oggle headers. This advice does it for you automatically every time you select message. This advice slows message displaying a bit, but for me, it isn't very noticeable. You can very well turn this off if you dont' change content of rmail-ignored-headers.

      rmail-summary-enable active

      This replaces whole function. The original function did automatic message update whenever you moved around summary buffer. Now you can keep summary buffer search separated from the current message displayed.

      rmail-summary-next-msg active

      Same as above.


      Tinyscroll.el --- Enable or disable auto-scroll for any buffer.

      Preface, May 1996

      I was in the middle of testing one of my new packages which didn't quite work as I wanted, I was loading all the lisp files to see if it breaks. I watched the Message buffer to fill with statements

            Loading abbrev...
            Loading abbrev...done
            ...
            Loading rmail...
            loading rmail done...
            ...    

      But suddendly the emacs died. It kicked me off to the shell and I had no idea what package was the last one that got loaded.

      You see, the Message buffer keeps growing, but you have to tap the pgDown key to get to the end, all the time. Instead I decided to pull out some lisp to do general auto-scrolling for any buffer, so that I can just sit back and watch the buffer move. No more guessing in Message buffer what was the last message before Emacs sunk :-)

      Overview of features

      How to use this package

      The scroling here is based on timers, where the lowest interval can be one 1 second. This means that you don't get smooth and continuous scrolling, but regular update of the buffer, which may in rare cases seem jerky. However, using timers is the only possibility if we want to have general scroll utility for any buffer.

      To enable/disable auto-scroll for current buffer, use these:

            M-x tinyscroll-control              ;to activate scroll
            C-u M-x tinyscroll-control  ;to deactivate scroll    

      Lowest window of the same buffer always scrolls

      It is an interesting problem, when you have SAME buffer in multiple windows, to decide which window to scroll. I didn't want to scroll all windows, since otherwise I wouldn't have used two/or more windows for the same buffer.

      I decided that the lowest window for the buffer always scrolls. You can't change that. This was a design decision and I won't support scrolling middle/upper buffers. Just arrange your windows so that the scrolling one goes to the bottom.


      Tinysearch.el --- Grab and search word under cursor

      Preface, 1994

      In 7 Nov 1994 aep@world.std.com (Andrew E Page) posted interesting code by article name 'Script Example: Search for next word', which I took a look. The idea of code was excellent, but it didn't work as expected at all. Gradually the idea was crystallized into this package.

      "Why we need search word package, when in emacs I can do C-s to enter search mode: C-w C-w C-w to grap words immediately after point and finally C-s to start searching...?"

      Well, people tend to forget, that life was out there when 19.xx wan't in hands of developers. This package was originally made for 18. The advantage of this package is the variable

            tinysearch-:word-boundary-set    

      which you can easily change whenever you need (e.g. thru functions). To do the same in emacs, you have to go and modify the syntax entries involved...then come back again when you're done. I never do that, I seldom touch the syntax entries. Besides all mode-xxx go crazy if I would do so. Now you see the advantage?

      And of course I feel more comfortable to do just one keypress, like f2 to search forward instead of cubersome C-s C-w C-w C-w [n times] and finally C-s

      The prefix tisw in variables and functions names means "Tiny Search Word".

      Description

      Grab word under oint and searches fwd/back. The word is inserted into Emacs's search ring, so that you can later continue with C-s or with C-r call.

      Why doesn't it find my C++ function class::InitClass() ??

      User pressed the search function over the call:

            InitClass(;
            i =  i +1;    

      Now he can't find the function definition... Well, remember that this searches 'true' words, not part of them. A word is surrounded by at least one whitespace, since it's not a word if it is cat'd together with something else. Obviously the function definition didn't contain any spaces...

      The problem is, that if is you say ':' belongs to character set in C++, [because you propably want to grab variables easily. including the scope operator 'clss::variable' or '::global'] , the find funtion expects to find word in boundary

            nonWordWORDnonWord    

      And as you can see, the if ':' belongs to word, it can't simultaneously belong to NonWord !

      Summa summarum: Revert to emacs C-s for a moment, since the word is automatically added to the search buffer.

      Word accept function note:

      There is variable tinysearch-:accept-word-function, which has default function

            tinysearch-accept-word    

      The function's purpose is to check if the searched word is accepted and that search should be terminated. Currently there it contains some programming logic for C/C++ languages, so that certain hits are ignored. Consider following case:

            struct *foo;   - 1
            foo->x;        - 2
            x->foo         - 3
      
            int foo, x;    - 4
            foo = x;       - 5        * start of 'foo' and 'x' search backward    

      C/C++ mode, searching for 'foo' finds 4,2,1 – Not 3 C/C++ mode, searching for 'x' finds 5,4,3 – Not 2 But in text-mode, you would find all occurrances.

      The added logic to C++ ignores the struct's MEMBER matches so that you really can find the "main" variables. If you don't like this added feature, you can alwasy go to

            M-x text-mode    

      For a while, or if want to permanently switch this feature off, you set the variable tinysearch-:accept-word-function to nil, which causes all hits to be accepted.

      Needless to say, that you can use put your own checking function in that variable to control the accurrances better.


      Tinytab.el --- Programmers TAB minor mode. Very flexible.

      Preface, oct 1995

      There was a post in gnu.emacs.sources (what an source of inspiration), where someone asked:

            "Is there anyway to reset the number of spaces that TAB does?
             Like, I want to make it jump four spaces instead of the
             usual whatever.How can I set the tabs to 4?"    

      and the typical answer was:

            "In .emacs, set the variable tab-stop-list, like so:
             (setq tab-stop-list (list 4 8 12 ...))"    

      Well, A regular user does not want to touch the original tab-stop-list, because the 8 spaces per tab is the norm. But for programming the 4 tabs is norm, like for shell programming or for simple memos and text documents. The goal was to write a minor mode, which you can turn on and off, which handles only tab key. There also exists tinyindent.el, which is tab-alike mode too, but there is a subtle, but very important difference: it behaves according to previous lines, so its job is to "line up" with the previous text or code. Instead, this mode was supposed to be plain rigid. The tab goes where you want it, and you can control the amount of movement to either direction, back or forward.

      Overview of features

      Extras

      What this package does?

      Mimic tab-stop-list with minor mode if some analogy can be drawn. You only set one variable, that controls the amount of movement, whereas you would have to put many values inside tab-stop-list. The variable for tab widths is:

            tinytab-:width-table    

      The advantage is, than you don't have to alter the tab-stop-list at all. When the mode is off, the tabs are back again as they were (or as the other mode thinks how the tab should be) There is a little more than that: movement and deletion functions, that really make day shine when you program. They all operate according to the variable tinytab-:width. Try out the functions

            tinytab-indent-by-tab-width
            tinytab-indent-by-tab-width-back    

      to format region of code forward and backward easily. (This is different than using command indent-region) When you delete backward "one indentation level", you can do it when the division factor is 2/4/8. The nearest column that satisfies the division factor is used when "indenting back". See the example:

      Before: * << cursor here 123 567 9012 << columns, starting from 1

      After: * << cursor here, at div-factor compliant point 123 567 9012 << columns, starting from 1

      Don't forget to look at function

            tinytab-change-tab-width    

      Which allows you to switch between 2, 4, 8, you name it, tabs widths with one key press during the curren tminor mode.

      Major modes and this minor mode

      When you use some programming mode, say C++ mode, it usually provides function to indent the line right when you press tab key. If you then turn on this mode, you loose the mode specific indenting, because turning on minor mode overrides the underlying major mode bindings. There is included one simple function to deal with major modes: it preserves the original indenting style in some extent, so that you can use this minor mode and current major mode together. In variable tinytab-:tab-insert-hook there is function tinytab-tab-mode-control which looks at variable

            tinytab-:mode-table    

      If the mode is listed in the table and current point is at the beginning of line, then the line is handled by original major mode and not by this minor mode. This allows you to indent the line initially and then use normal tab indent within the current line according to this minor mode.

      However, this minor mode is normally meant to be used as turn on/off basis in such programming modes that indent lines when you pressing tab key. Current compatibility function tinytab-tab-mode-control only allows you to get some flexibility when this mode is temporarily on. Bind this mode to some fast key which you can use to toggle this mode on/off when you need tab for a moment in programming modes. If you don't want any support to major modes, put following into your $HOME/.emacs

            (setq tinytab-:mode-table nil)    

      Return key addition

      In this package there is also this little function which will make itself a must in no time:

            tinytab-return-key-mode   ;; I have bound this to C-c C-m    

      When the function is active, you can continue the ndentation from current position.

                                // Comment here. Call C-c C-m...and press RET
                                // And it automatically indents here.    

      See variable

            tinytab-:auto-indent-regexp    

      what line prefixes are "copied" along with the indented spaces.

      Development note

      This package solely concerns TAB key. Nothing outside of it is counted. I have no intention to make this a full fledged programming mode, since there is sh-mode, ksh-mode, perl-mode and many more for other languages. I almost added

            (make-variable-buffer-local 'tinytab-:width)
            (make-variable-buffer-local 'tinytab-:width-table)    

      But after thinking I decided not to add it to this package, since most of the time user is satisfied with the tab "4", at least that's what I use mostly. And changing the width usually means a little flick of a finger to reach out the function

            tinytab-change-tab-width    

      In very rare occasions one wants different tab widths in different buffers and in those cases you can add the lisp commands make-variable-buffer-local to mode hooks or after tinytab-:load-hook.


      Tinytag.el --- Grep tags: show C++/Java/etc. syntax call while coding

      Preface, overview of features

      Ready-to-use databases currently available:

      Story behind this package

      The word "tag" refers to famous tags package in emacs that allows you to browse your C/C++ code easily.

      Someone may be in the middle of c++ project at work and notice that he frequently consults the manual pages to find correct syntax for calling stdio.h functions. It's hard to remember them right every time. Time spent for reading manual pages may be considerable just to figure out what #include statements each function might require, and what type of parameters they need.

      No more. There must be a way out of this...

      If you have programmed in lisp, you propably know package called eldoc.el (get it fast if you haven't) by Noah Friedman friedman@prep.ai.mit.edu. It shows you the lisp function call arguments when your cursor is right over some function.

      What a cool tool! You never have to go to elisp info pages just to check what the function takes, and you don't have to pop up extra buffer with c-h f <func>. It's a real time saver. Similar keyword lookup feature culd be built for any programing. Since eldoc looked the lisp args from memory (emacs obarray, symbol storage), the other programming languages must use external reference files: databases.

      First, all C/C++ function syntaxes were extracted out of the man pages with small perl program. The final output after ripping all the 3C man pages loooked like this. The output is put under database 'c++-functions'

            <dirent.h> dir *opendir(const char *dirname);
            <dirent.h> int closedir(dir *dirp);
            <dirent.h> int readdir_r(dir *dirp, struct dirent *result);
            <dirent.h> long int telldir(dir *dirp);
            <dirent.h> struct dirent *readdir(dir *dirp);
            ...
            <string.h><strings.h> char *index(const char *s, int c);
            <string.h><strings.h> char *rindex(const char *s, int c);    

      Notice how perl stuck the '#define' statements at the beginning of each function. After this 'function' database was ready, the only thing needed was lisp code to handle database lookups for the keyword under the cursor. Similar approach can be user for any programming language. Just set up the database, entries to search; one per line. that's it.

      Word about installation – performance problems [19.29 or lower]

      Skip this part if you have 19.30+

      When you load this package, it immediately installs an example post-command function. It assumes that you're using the "Having a test drive" C++ database and stored it as explained. You propably want to remove that default post-command function and use your own definition. Here is how you remove it.

      Doing this is also recommended if you don't want post command actions, but want to use the tinytag-main-mouse functions directly. Call them only when you need them.

      If your databases are big, or if you're afraid of the overall emacs performance I STRONGLY ADVICE THAT YOU REMOVE THAT post-command with methods (2) or (1) You can always call the database with the supplied keyboard or mouse commands when you need the information.

      Having a test run

      There is sample C++ database from HP-UX 10 man 3C pages, which is unfortunately incomplete. You may consider using the BSD C-database instaed. The BSD is installed by default when you call M-x tinytag-install-sample-database-c. Rememeber that you really should replace those definitions with your own systems equivalents, because not all functions are found in all systems. Vendors are different.

      This is how you test this package.

      You should see the "strcat"'s function's definition displayed in the echo area. Next, you can start writing your own databases to languages you use.

      Installing support for your programming languages

      While you may have installed the default database for C/C++, you have to configure the variable tinytag-:database-setup-table to include all languages where you have databases available. It is recommended that you keep all emacs related configuration, including databases, in one place, e.g.

            ~/elisp/config/    

      First you need databases which you must write yourself. e.g. emacs-tinytag-python-function.el where you describe the function, packages and call syntax. The only thing after creating the database is to tell where it can be found. E.g for php you would add couple of you own variables:

            (defconst my-tinytag-:db-map-php
                 '((func       "emacs-config-tinytag-php.txt"))
                 "Java database.")
      
            (defconst my-tinytag-:db-re-php
                 '(("."        (func)))  ;; See name FUNC in prev. variable
                 "PHP database.")    

      And tell tinytag.el that the Java is now known:

            (defconst tinytag-:database-setup-table
              (list
               (list
                "code-php\\|php"
                '(my-tinytag-:db-map-php
                  my-tinytag-:db-re-php))
              (list
                "c-mode....."
                '(..
                   ))))    

      C/C++ database

      Run c-function-list.pl that comes with Tiny Tools Distribution to generate function database.

      Alternatively copy the database from the end of this file or use M-x tinytag-install-sample-databases

      Java database

      Run script java-function-list.pl that comes with Tiny Tools distribution to generate function database from the Sun JDK's javadoc html pages. See the manual page of the script how to run it (--help option)

      NOTE: In SUN documentation, there is no System.out.print() or System.out.println() functions that could be extracted. Please add Those functions by hand to the database.

      This script is also run with call tinytag-install-sample-databases, provided that you have perl and java and java-function-list.pl installed and located along PATH.

      Perl database

      <coming>

      Run perl-function-list.pl that comes with Tiny Tools Distribution to generate function database. See the manual page of the script how to run it (--help option)

      Database format and display

      There is nothing special in the database format, each entry must me in one line nad that's all. Try to find most suitable display format for your language, like the general method that is used for C/C++, Java and Perl

            <LIBRARY> return-value function-name(function-parameters) REST-INFO    

      Important: When function tinytag-search-db searches the whole database, it gathers the lines that likely match and FIRST one that is found is displayed in the echo-area. So that you're aware of other matches, the count of matches is displayed

            10: java.lang.System.out  void println()
            |
            Count of matches    

      If you have time, it would be sensible to move the most informational description of the function first in the list of lines, so that it get displayed. For example, you could move method this method first in the line and add [] inside function parameters to signal that the parameter is optional

            java.lang.System.out  void print([Object obj])    

      Alternatively, you can keep the buffer tinytag-:output-buffer visible e.g in separate frame, so that all the matched items are visible to you in case the one displayed in echo-are is not correct.

      Differencies between 19.30+ and lower

      The 19.30 Emacs has idle hook, which runs after you move cursor. It doesn't run if you move mouse. 19.28 on the other hand has post command hook, that runs every time you either move cursor OR move mouse.

      Now, to get display fast in 19.28, you propably want to wave your mouse fast couple of times. In 19.30 you can have immediate display with just one cursor move over the word.

      What to do if you don't see the definition displayed?

      hem most informative is the internal debug which you turn on with:

            M-x tinytag-debug    

      Then call this function directly over the word whose definition you want to display (e.g. strcat in C++)

            ESC ESC : (tinytag-post-command-1)
            ========
            Press this key combination and enter text to the right.    

      After that call there is buffer tinytag-debug that has some information about called functions and parameters. Please investigate the call chain for possible problem. Is the database selected right? if the regexp used for search right? If you don't know how to read the debug buffer's output, just send the buffer's content to me and describe what you did and what was your current major mode.

      Thank you

      Peter Simons simons@petium.rhein.de sent me NetBSD and Linux C databases and his perl script can help you to create your own database from the man pages.


      Tinytf.el --- Document layout tool for '(T)echnical text (F)ormat

      Preface, Jan 1997

      Late in the 1996 there was a need for a better text file handling than just plan text-mode. I was looking for a simple tool to generate HTML pages out of text-based documents. After some researching on the web, I still couldn't find anything that would have been strictly a text-based solution. There were many "languages" from which the HTML could be generated, but really, I didn't want to learn any new language just for that. I can understand people that write their documents still using LaTeX, but Win32 Word is much suitable and more known than any of those exotic formats. The project started by creating the tool that converted text into HTML (Perl t2html.pl script) and then writing a Emacs package to help writing the text files. It has been proven to be really nice combination where flexibility meets cross-platform demands.

      Overview of features

      You can use M-x add-change-log-entry-other-window (C-x 4 a) to create a standard ChangeLog record for your changes under the headings.

      The text layout you write

      This package

      What is Technical Format?

      In short: it is list of text placement and formatting rules. And you're looking at it right now in this document.

      This package offers minor mode for text files and helps you to maintain correct layout. You can even convert file into HTML very easily with the perl script which is usually distributed in the complete Tiny Tools Kit or available separately from the CPAN under developer account JARIAALTO. You do not need to know a shred about the HTML language itself. And it is much easier to update text files, than deal with HTML itself. When you have text ready, you just feed it to the t2html.pl perl script and it gives you nicely formatted HTML page. Writing HTML home pages is different story, because you usually want to include some graphics, JavaScript, PHP or JSP in the page. But putting some text document available in HTML format is easily made possible with this package.

      In the other hand, while you may not be interested in HTML, you could still consider writing your documents in 'Technical format' – with word technical I refer to the layout of the text, which is very rigid. In order to use facilities in this package, e.g. heading hiding/showing, the headings must be placed in columns 0 and 4 and the first word must be in uppercase. The actual text you write starts at column 8.

      If you decide write text like this, you become accustomed to the layout very quickly and it also helps keeping your documents in the same format.

      All in all, this package was primarily designed to help writing text documents for t2html.pl and viewing document in outline styled selective display. Please refer to mode description for full details of the text layout format.

      TF described briefly

      Please note, that this section may be slightly out of date. You should read up to date information from the conversion program using command t2html.pl --help available at http://perl-text2html.sourceforge.net/ and nearest Perl CPAN http://cpan.perl.org/modules/by-authors/id/J/JA/JARIAALTO/

      --//-- TF description start

      0123456789 123456789 123456789 123456789 123456789 column numbers

      Table of contents

                <Do not write any text inside this heading. It will>
                <be generated by tinytf.el automatically with M-x tinytf-toc>    

      Heading 1 starts from left

      emphatised text at column 1,2,3

            This is heading 2 at column 4, started with big letter
      
                Standard text starts at column 8, you can
                *emphatize* text or make it _strong_ and show
                variable name like =ThisVariableSample=. notice that
                `ThisIsAlsoVariable' and you can even _*nest*_ the mark up.
                more txt in this paragraph txt txt txt txt txt txt txt txt
                txt txt txt txt txt txt txt txt txt txt txt txt txt txt txt
                txt txt txt txt txt txt txt txt txt txt txt txt txt txt txt
      
             Plain but colored text at columns 5, 6
      
               EMPhatised text starts at column 7, Like heading level 3
      
               "Special STRONG EMP text in column 7 starts with double quote"
      
                txt txt txt txt txt txt txt txt txt txt txt txt
                txt txt txt txt txt txt txt txt txt txt txt txt
                txt txt txt txt txt txt txt txt txt txt txt txt
      
                 strong text at columns 9 and 11
      
                  Column 10 has quotation text
                  Column 10 has quotation text
                  Column 10 has quotation text
      
                    Column 12 is reserved for code examples
                    Column 12 is reserved for code examples
                    All text here are surrounded by SAMP codes
      
            Heading 2, at column 4 again
      
                txt txt txt txt txt txt txt txt txt txt txt txt
                txt txt txt txt txt txt txt txt txt txt txt txt
                txt txt txt txt txt txt txt txt txt txt txt txt
      
                o   Bullet 1 txt txt txt txt txt txt txt txt
                    txt txt txt txt txt txt txt txt
      
                    Notice that previous paragraph ends to P-comma code,
                    it tells this paragraph to continue in bullet
                    mode, otherwise this column at 12 would be
                    interpreted as SAMPLE code.
      
                o   Bullet 2, text starts at column 12
                o   Bullet 3. Bullets are advised to keep together
                o   Bullet 4. Bullets are advised to keep together
      
                .   This is ordered list nbr 1, text starts at column 12
                .   This is ordered list nbr 2
                .   This is ordered list nbr 3
      
                .This line uses BR code, notice the DOT-code at beginning
                .This line uses BR code
                .This line uses BR code
      
               "This is emphatized text starting at column 7"
                .And this text is put after the previous line with BR code
               "This starts as separate line just below previous one, EM"
                .And continues again as usual with BR code
      
                See the document /document.txt, where
                tag is substituted with -base switch contents.
      
                Make this email address clickable foo\@site.com
                Do not make this email address clickable bar\@site.com,
                because it is only an example and not a real address.
                Noticed the minus(-) prefix at the beginning of url?    

      Heading level 1 again at column 0

            Sub heading, column 4
      
                And regular text, column 8
                txt txt txt txt txt txt txt txt txt txt txt txt
                txt txt txt txt txt txt txt txt txt txt txt txt
                txt txt txt txt txt txt txt txt txt txt txt txt    

      --//-- TF description end

      How do you write text

      This package turns on two minor modes: tinytab-mode, that handles your TAB key movements and tinytf-mode, the Technical format minor mode. If you're uncertain about how the column will be treated in HTML output, call following function. If you have 19.30+ this is not necessary, see note about post command above.

      Do you wonder why 'z' prefix is default? Well, I wanted a fast key that was mostly unused. You can change that if you prefer some other key. See variable tinytf-:mode-prefix-key

            z RET   tinytf-column-info-display    

      Normal text you write as usual, but if you want to mark regions as "quotations" or "code examples" there is appropriate indent commands

            z /     tinytf-indent-region-text
            z '     tinytf-indent-region-quote
            z ;     tinytf-indent-region-sample
            z :     tinytf-indent-region-strong
      
            z t     tinytf-indent-paragraph-text
            z a     tinytf-indent-paragraph-text-as-is
            z l     tinytf-indent-paragraph-text-and-fill
            z q     tinytf-indent-paragraph-quote
            z Q     tinytf-indent-paragraph-quote-and-fill
            z s     tinytf-indent-paragraph-sample
            z 0     tinytf-indent-paragraph-zero    

      The tinytf-indent-paragraph-text-as-is is a bit special, because it won't fill the text while it moves the paragraph to the text position. Instead it adds symbolic <BR> codes to the front of every moved line. In HTML this ensures that the lines will be shown exactly as you see them. See also BR mark commands.

      There is no functions for bullet creation, because you can write them easily by hand. Use z b to fill bullet text nicely. Bullets look like this

            o   This is bullet..
                and cont'd line here
            o   Yet another bullet
                and cont'd line here    

      The tinytab-mode will advance your tab key by 4 every time, so the text in the bullets go to the right column (12). Remember also to keep the tinytab-return-key-mode on, because that continues lines as they were written above when you press return. See also bullet conversion command, which reformats previous text that used dashes(-) to separate bullets.

            z b     tinytf-bullet-format    

      BR marking commands

      In Html, the text would normally wrap according to the browser's page width. But sometimes you may wish to tell exactly that it shouldn't wrap the lines according to browser. For example if you want to include a quoted text "as is" from the Usenet posts to your page, you need o add symbolic BR code to the beginning of each line. Like including the following quotation

            >>Jim has a good point here...
            >>I would have expected that the system depends on..
            >Yeah; but you hadn't looked at the /usr/adm/today.log
            >    

      In order to add this to your page "as is"; you can do this: indent it as "Sample" and it will automatically show like that. But normally you want it to show as quoted text where you refer. Then you do:

            z Q         tinytf-indent-paragraph-quote
            z m b       tinytf-mark-br-paragraph    

      Which will prepend dot-code(.) to the front of every line. You can also add the dot-code by yourself or use following command

            z m B       tinytf-mark-br-line    

      Heading writing and handling

      You can only use 2 heading levels, which normally suffices. Sorry, there is no support for more deeper headings. You start headings with big letters or number at column 0 or 4. Here is some specialized commands for headings.

      This one converts first character of each heading to uppercase. This fixes mistakenly left lowercase letters.

            z f h     tinytf-heading-fix
      
            before command:
            heading
                heading
      
            after command:
            Heading
                Heading    

      You can (re)number heading easily with following command. If there is no number in the line, one is added to the beginning of heading. And if you have added new heading somewhere in the middle of text, just call this function and it renumbers all headings again. Running command with prefix argument removes numbering.

            z f 0     tinytf-heading-numbering
      
            before command:
            heading
                heading
            heading
                heading
      
            after command:
            1.0 heading
                1.1 heading
            2.0 heading
                2.1 heading    

      One note about renumbering. Some people write heading number so that they are closed with parenthesis. This style is not recommended with technical format style and when you do renumber, those parenthesis will be removed. The parenthesis style is not supported because the plain number style is more easily parsed and detected. In addition, the plain number style in headings is more widely used in the world.

            before command:
            1.0) heading
                1.1) heading
      
            after command:
            1.0 heading
                1.1 heading    

      Heading fixing

            z f a   `tinytf-fix-all'
                    Does lot's of things. Trim away trailing blanks
                    from buffer. Untabify buffer.
                    Renumber headings if needed. Delete extra whitespace
                    around headings.
      
            z f c   `tinytf-heading-fix-case'
                    convert current heading to lowercase
      
            z f C   `tinytf-heading-fix-case-all'
                    convert all heading to lowercase    

      About table of contents

      When you write text, you don't write the table of contents, but the headings. Be sure to add heading "Table of contents" somewhere in the document. To generate table of contents use commands:

            z T             tinytf-toc, Try with C-u argument too
            z mouse-1       tinytf-toc-mouse    

      Selective display

      The hiding and showing of the headings and their text is done by using the outline/folding style display. There is no magic in this; but there is two interesting commands that you can use in any selective display buffer.

            z C-p     Prints selective display (what you actually see)
            z C-c     Copy selective display    

      Word about key definitions when mode is turned on

      When the minor mode is active it overrides some commonly used key bindings and moves their original function under Control key. For example:

            original PgUp    --> Now Control-PgUp
            original PgDown  --> Now Control-PgDown
      
            PgUp             --> Moving heading backward
            DownUp           --> Moving heading forward    

      If you are using X environment or your emacs recognizes mouse, then there is one handy binding that opens or closes heading levels when you click over them.

            [mouse-3]       tinytf-mouse-context-sensitive    

      If you press this mouse button anywhere else than over the headings, it'll call original binding. This feature is similar as what is used in folding.el

      Technical note: about the outline layout

      Speed was my primary goal when I added the outline code. But that came with a price: I would have liked that the Heading-1 were separated by at least one empty space so that the buffer would look visually better.

            heading1-1
                heading1-1
                heading1-2
                                        << empty space here
            heading2-1
                heading2-1
                heading2-2    

      But that would have required adding some extra code to do bound checking every time the block is collapsed/opened. Currently I'm not going to add that checking because it would reduce speed and the check would cause unnecessary complexity to current code flow.

      Technical note: about the default prefix key z

      The prefix key definition is on tinytf-:mode-prefix-key That is currently "z" by default. If you type "zz", you get plain "z". I wanted to choose fast key and avoid wrist pain as much as possible. When you write TF text, you use this mode a lot and accessing commands should be easy too.

      Technical note: post command

      This note is valid only for old Emacs releases, prior 20.x.

      While you type text in the buffer, the post command activates at regular intervals to untabify the buffer. The untabify is done because it makes formatting text easier and when you print the text file, you can be sure that the output is the same regardless of the tabs.

      If you have Emacs 19.30+ there is additional help feature available to you. When you sit still in some column position for few seconds, the column description will be shown automatically. That should help keeping you informed of the text layout.

      Technical note: HTML utilities

      Two external utilities are searched for HTML generation: t2html.pl and htmlize.el. If these utilities are found, their locations are stored to plist of variable tinytf-menu. See source code of function tinytf-utility-programs-check for more.

      Known bugs

      In Emacs 20.6 the TinyTf pull down menu contains bold titles for certain sections. This gets almost always garbled with the first pull-down. Selecting the menu second time shows correct section names with bold letters.


      Tinyurl.el --- Mark and jump to any URL on current line.

      Preface, oct 1997

      Hm. one day a collegue of mine had a problem with his VM and he explained to me that he wanted the mouse-2 to run netscape browser instead of the default Emacs w3 browser. While he was waving his cursor over the http link, I suddendly realized: that I wanted that in my RMAIL buffers too. (I later moved straight to GNUS). It seemed that every package had it's own url handling: VM, TM, GNUS, MH?

      But really, how about the rest of the buffers and modes? There was no general ULR dispatcher minor mode that would work with any buffer and with any mode.

      Now there is; I can browse any buffer or document and jump to URLs on the line. Works for programing modes too. You just position the cursor somewhere on the line, wait 2 secs and the URLs are marked ready for launching.

      Overview of features

      Turning the URL recognizer on

      Load package with require or via autoload (see installation instruction at the top of file) and call M-x tinyurl-mode to toggle the global minor mode on and off. The modeline displays Ux when the mode is active. Character (x) is a one character shortname for browser that will activate, e.g. "n" for "netscape" browser set, (l) for lynx and (w) w3.

      If you want to turn the mode on or off for current buffer only, use M-x tinyurl-mode-1.

      The minor mode is turned on for all newly created (C-x C-f) or visited files, but if you make a new buffer with M-x switch-to-buffer, the URL mode is not turned on in those buffers.

      Cacheing URLs for later use (offline reading)

      General design: When you're not connected to the Net, it doesn't make sense to call browser directly, but cache the pushed urls to separate buffer. When you're online again, you can go to the cache buffer and relaunch pointers.

      THE CURRENT IMPLEMENTATION RELIES ON GNUS ( M-x gnus ) TO DETECT THE OFF-LINE, ON-LINE STATUS OF YOUR NETWORK CONNECTION. THE DEFAULT STATUS IS off, if no gnus is currenly loaded in Emacs. THIS MEANS THAT ALL "buttons" ARE CACHED TO SEPARATE BUFFER UNLESS YOU TELL THAT YOU'RE CONNECTED via M-x gnus-agent-toggle-plugged.

            Please send a mail to maintainer  if you can know more
            better alternatives to check network connections transparently
            in Win32 and other environemnts.    

      The offline reading is possible with Gnus, where you can toggle between "plugged" and "unplugged" Gnus. The default unpluggged condition detector is function tinyurl-plugged-p. It returns nil if you're running Gnus and it's in unplugged state.

      You can place your own unlpugged state detector to variable tinyurl-:plugged-function. Cache buffer used is tinyurl-:url-cache-buffer, which is URL-cache by default.

      You can force Tinyurl to go "plugged" by calling M-x tinyurl-plugged-mode-toggle. This internal flag overrides anything else in the system. The indicator "!" in the modeline tells if TinyUrl thinks it is in plugged state. You may need to call this function if you don't use Gnus as an primary MUA.

      Shortly:

            (setq tinyurl-:plugged-function 'tinyurl-plugged-always-p)    

      Editing the url and selecting access method manually

      You can pass a prefix argument like C-u before you press mouse-2 or M-RET and edit two parameters: a) The URL location itself and b) the access method. Say e.g. that your default command table is netscape and you see url

            file:/users/foo/file.txt    

      The `file:/' would be normally considered external and accessed via url method, which in this case is netscape. But you would like to use Emacs find-file instead. Send C-u and leave the url as is and change access method to:

            file    

      That's it. Remember however that you have full control and if you choose nonsense access method, which has nothing to do with the url, then you also carry the results, whatever they may be.

      Ignoring URL in the buffer

      You can use hook tinyurl-:dispatch-hook to check URL. If any of the functions return t, then the original binding in the mode is called and the TinyUrl is not used. E.g. In Dired buffer you want to ignore all URLs. There is default function tinyurl-dispatch-ignore-p that does just this.

      Centralised URL handling

      If you called M-x tinyurl-install-to-packages or had installation:

            (add-hook 'tinyurl-:load-hook  'tinyurl-install-to-packages)    

      then GNUS, VM, TM, and other packages redirect urls to TinyUrl. This way you don't have to setup each package to your taste. Plus you got the benefit that you can change url handler set on the fly with tinyurl-set-handler.

      Ignoring some buffers for mode turn on and offs

      If you want to exclude some buffers from the mode turn on or offs, say VM which does its own highlighting, then define your custom function like this

            (setq tinyurl-:exclude-function 'my-tinyurl-exclude)
      
            (defun my-tinyurl-exclude (buffer)
               "Exclude some buffers that use their own highlighting."
               (string-match "VM\\|Article" (buffer-name buffer)))    

      This only concern the golobal tinyurl-mode function. You can still use tinyurl-mode-1 anywhere to toggle the mode setting. You use this variable when you don't want tinyurl-mode to appear in buffer at all.

      Validating url

      The tinyurl-mark-line function doesn't check the validity of a matched regexp that was marked as pushable url. It's a dummy function that can only attach "buttons" and does nothing about their contents. But when you actually push the url, the url is run through functions in tinyurl-:validate-hook. When any of the function returns t, it is a go sign. The default handler tinyurl-validate-url rejects any url that match "foo|bar|quux".

      See also tinyurl-:reject-url-regexp for more simpler use.

      Choosing what agent handles which URL

      There is predefined tinyurl-:command-table which is consulted where URL request should be delegated. By default http:// or ftp:/ or file:/ requests are handed by browse-url-netscape and remote tar or gz fileas are loaded with ange-ftp.

      You can completely customize the URL delegation by writing your own url handler set and placing it to tinyurl-:url-handler-function. Copy the default setup and make your own modifications.

      Changing the url handler list

      When you click the url to run the viewer, the current url handler list determines what method is used. E.g. If you normally want netscape to handle your URL, then the current set is labelled "netscape". But in some situations, where you want to e.g. view text files or your resources in PC EXceed are low, or you want fast browser; then there is also "lynx" set. You change the browser set with command

            tinyurl-set-handler   Meta mouse-2    

      The modeline will show the first string from your active set; Un for Netscape, Ul for lynx set and Uw for w3 based set. You can add as many handler sets as you want by adding them to tinyurl-:command-table

      Exclamation character marks pushable URL

      NOTE: THE VISIBLE CHACTER APPLIES ONLY TO TERMINALS THAT DO NOT SUPPORT COLORS TO MARK PUSHABLE URLS. (Usually an Emacs started with -nw, or running inside a terminal.)

      When you see character "!" (netscape) or "?" (W3 browser) to appear in the front of the URLs, then you know that items are pushable. You can call the URL by clicking it with mouse-2 or tapping M-RET. In the following line, two url's have been detected. The first one sends normal http request and the second one would create mail buffer for the address.

            Some previous line here
            !http://foo.com/dir/file.txt  !foo@bar.com
            Another line below    

      Elswhere your mouse-2 and M-RET behave as usual. If you would like to paste(the mouse-2) somewhere in the "previous" or "another" line, that would work as you expected. But you can't paste inside the URL, because the URL is currently activated. If you need to do something like that, then you can use either of these strategies:

      Note: The character "!" that you see, is not a real editable character, but part of the overlay. While your text may appear to be modified. That is not what happened. See Emacs info pages for more about overlays.

      You can use variable tinyurl-:display-glyph to control if the glyph is shown or not.

      Accepted email URL

      The default accepted format is foo@site.com and if you see foo@site.com, that will not be recognized. Your can get this accepted by changing tinyurl-:email-regexp. You could use \\< and \\> (word border marker) regexps instead of default characters < >.

      Support for programming language URLs

      I'll gladly support any other languages. If you know the language you're using, drop me a mail and help me to undertand how I would add support to it. Especially I'd like to hear specs from Java programmers.

      C/C++

      The default agent to find C/C++ .h files is find-file.el's ff-find-other-file. This will handle your #include urls.

      Perl

      There is support for these perl statements:

            use package;
            require package;    

      Functions that recognize those are under tinyurl-find-url-perl*. The default find path for perl is @INC. Perl related urls are delegated to separate tinyperl.el package. In addition perl compile error lines are recognized:

            ERROR at FILE line NBR.    

      Perl pod page references are recognized in the format

            perlfunc manpage
            See [perltoc]    

      Emacs lisp

      The url handler function is tinyurl-find-url-lisp and Emacs load-path is searched. The usual urls "load-file", "load-library" "autoload" "load" are recognized. If you need to jump to function or variable definitions, you want to use a TinyLisp package, which offers minor mode solely for Emacs lisp programming purposes: Profiling, debugging, snooping hooks, you emacs packages, browsing code etc.

      Other languages

      Please let me know if you know package or you have code that can find other languages' URLs.

      Memory list

      Filename filter e.g. running catdoc for MS Word files

      There is table tinyurl-:file-filter-table which can be used to handle found url. Eg if you want to treat all files ending to extension .doc as MS word files and feed them through catdoc http://www.ice.ru/~vitus/works/ which spits 7bit out, you can associate shell action to handle url. Respectively if you want to use xv for viewing your images, you can associate that to the url. The default table handles these cases if you have xv and catdoc present. See variable description for more information. (You can also use your custom lisp url handler there)

      If you want to load the raw file into emacs, just supply prefix argument when you push url and you will be given choice to by-pass the set filters (if there is any) for the url.

      Code note: adding buttons to the current line

      The idle timer process is used to mark current line's urls with overlays. Please wait few seconds on a line and the ulrs that can be pushed are marked. If there is no idle timer available, then a post-command-hook is used.

      [Next applies only to Emacs with no run-with-idle-timer function]

      Using post-command-hook is not an ideal solution, but at least this package works with older Emacs versions. The threshold how quicly the line is scanned for url buttons is determined by variable tinyurl-:post-command-hook-threshold. The deafult value 7 should give you enough time to use mouse-2 (paste) before the line is buttonized. Remember that vawing you mouse creates events, so you can force buttonizing the line quite quickly.

      Code note: overlay properties

      The overlays have nice feature where you can add string to be displayed to the side of an overlay. See the overlay properties in the Emacs info pages for more. The overlay priority in this package is by default set to highest possible, so that the URL highighting is guarranteed to be dislayed. If you use some other package that also uses overlays, then decrease that package's overlay priorities. (If the package doesn't allow you to adjust the priorities, contact the package maintainer. To my opinion the priority value should be defined for all overlays).

      The only part that you should touch in the property list of the overlays, is the displayed string. You can choose anything you want, but prefer one character. By default the "!" is shown in both Windowed and non-windowed version.

      The overlays have property owner which tells to whom particular overlays belong. In this case the owner is this package, tinyurl. It is a good practise for all overlays to identify themselves via this 'owner property.

      Code Note: overlay management

      Let's consider what font-lock does for buffer for a moment: it marks whole buffer with faces (colors). While design this package, the goal was not to add buffer with full of clickable overlays, while that could have been done easily. The reason is efficiency and avoiding "highlight" bloat.

      Instead old overlays are removed and new ones are created only for current line, typically the count is between 1 .. 4. When you move to another place, these old overlays are destroyed and new ones created. The current line may now may have only 1 URL, so only one overlay was needed this time.

      For that reason you must wait for idle timer process to do its work on current line, before you can see those clickable URL buttons.

      Using only small number of overlays keeps the code clean and user friendly. It's also faster than buttonizing whole 500K faq document in one pass.

      Code Note: Adding support for new URL type

      If you see new url that you would like to have supported and you know lisp, then the changes needed are:

      To make changes do this:

      Then send diff to the maintainer. Use unified diff format (-u) if possible. Second chance is to use context diff (-c). Other diff formats are not accepted.

      Sending a bug report

      If you have a line where url is highlighted, but it doesn't cover right characters, then do this:

      Btw, in win32 the file url on C: disk is written like

            file://localhost/C|/foo/bar/baz.html#here    

      And according to RFC, if you leave out the <host>, the localhost is automatically assumed.

            file:///C|/foo/bar/baz.html#here    

      Known Bugs

      The URL is highlighted by setting mouse-face to property highligh. But I have seen that Emacs 19.34 in HP Unix with X window sometimes won't show the highlight when cursor is moved over the URL. Go figure why. I have heard similar reports from XEmacs 20.4.

      If you know what is causing this effect, let me know.

      Todo

      Add support for Java-Find.el


      Tinyvc.el --- CVS and RCS log minor mode. Checkout, Check-in...

      Preface, Dec 1996

      In work there may be very complex RCS revision numbers, multiple branches and I may have several branches CheckedOut for testing, correcting, and developing new features. It seemed natural to handle this "multiversioning" control from the log output.

      Overview of features

      Do you need this package

      If you don't use RCS/CVS don't load this package, it only works for log output and expects to parse buffers in that format. If you don't use many branches and thusly vc's log output much, this package may not be essential to you. This pacakge uses colors if window system is detected, but it partially copes with non-window system too, so that e.g. marks appear in the buffer as charaxter codes.

            revision 1.25       locked by: xx;
            date: 1997/11/10 17:20:45;  author: xx;  state: Exp;  lines: +3    

      In the above lines the first line, starting from "1.25" is highlighted (version number). In next line: 97/11/10 (the YY year is significant), "xx" and "Exp" are highlighted.


      Tinyxreg.el --- Restore points/win cfg stored in reg. via X-popup.

      Preface, oct 1995

      I saw post in comp.emacs by cpg@cs.utexas.edu Carlos Puchol

            I find that my life would be remarkably eased if only I
            could "jump" to the marks from a menu.
      
            Please, let me know if i can implement this myself
            through some sort of macro or something.    

      As a hobby I started quicly sketching what the person should do.. I dind't plan to write any code. It just happened that I got interested in the subject and started experimenting with couple of functions.

      As a result I had complete package in hand within an hour or so, which I also posted to the group. Later on I properly packaged all the functions here and rewote whole thing.

      Overview of features

      Register update note

      If you wonder why some of the registers disappear from the popup while you were sure you just stored some point to them, the reason is here.

      If you kill some buffer, or reload it again with find-alternate-file that means that the register reference "dies". That's why the main function tinyxreg-jump-to-register calls a house keeping function tinyxreg-update to make sure you can't select invalid registers. So, trust the poup: it tells what registes are available.


      This file has been automatically generated from plain text file with t2html
      Last updated: 2008-08-09 18:03