;;; tiny-setup.el --- Tiny Tools configure center. ;; This file is not part of Emacs ;;{{{ Id ;; Copyright (C) 2001-2007 Jari Aalto ;; Keywords: extensions ;; Author: Jari Aalto ;; Maintainer: Jari Aalto ;; Look at the code with folding.el ;; COPYRIGHT NOTICE ;; ;; This program is free software; you can redistribute it and/or modify it ;; under the terms of the GNU General Public License as published by the Free ;; Software Foundation; either version 2 of the License, or (at your option) ;; any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;; for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with program; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;; ;; Visit for more information ;;}}} ;;{{{ Install ;; Nothing to install. Load this file. ;;}}} ;;{{{ Documentation ;;; Commentary: ;; 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. Try 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. ;; ;; To activate individual features: ;; ;; (tiny-setup nil '(tinymy--defadvice)) ;; Add smart M-x compile ;; ;; After you have loaded this file, have a look at the *Messages* ;, (Emacs) or *Message-Log* (XEmcs) buffers, where you can find ;; messgaes from the setup procedure. ;; ;; Emacs 21.x news: Windowed Emacs modeline contains new feature, ;; where you can activate and deactivate minor modes. Shoot ;; modeline with your mouse and follow message: "Mouse-3: minor ;; mode menu". Minor modes available here are installed to that menu. ;; ;; 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, non-compiled ;; files: ;; ;; 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 ;;}}} ;;; Change Log: ;;; Code: (eval-when-compile (require 'cl)) (require 'tinyliba) (eval-and-compile (defvar font-lock-mode) (defvar mode-line-mode-menu) ;; Emacs only (autoload 'tinydebian-install "tinydebian" "" t) (autoload 'tinydesk-edit-state-file "tinydesk" "" t) (autoload 'tinydesk-unload "tinydesk" "" t) (autoload 'tinydesk-save-state "tinydesk" "" t) (autoload 'tinydesk-recover-state "tinydesk" "" t) (autoload 'byte-compile-file "bytecomp") (autoload 'tinylisp-install "tinylisp" "" t) (autoload 'turn-on-tinylisp-mode "tinylisp" "" t) (autoload 'ti::mail-mailbox-p "tinylibmail") (autoload 'turn-on-tinymailbox-mode "tinymailbox" "" t) (autoload 'turn-on-tinymailbox-mode-maybe "tinymailbox" "" t) (autoload 'folding-uninstall "folding" "" t) (autoload 'folding-install-hooks "folding") (autoload 'turn-on-folding-mode "folding" "" t) (autoload 'dired-sort-default-keys "dired-sort") (autoload 'tinymy-define-keys-extra "tinymy") (autoload 'tinymy-compile-run-command-advice "tinymy" "" t) (autoload 'tinymy-define-keys "tinymy") (autoload 'tinyef-minibuffer-define-key-extras "tinyef" "" t) (autoload 'turn-on-tinyef-mode "tinyef" "" t) (autoload 'turn-on-tinypair-mode "tinypair" "" t) (autoload 'turn-off-tinypair-mode "tinypair" "" t) (autoload 'turn-on-tinyperl-mode-all-buffers "tinyperl" "" t) (autoload 'tinyrmail-install "tinyrmail" "" t) (autoload 'turn-on-tinycompile-mode "tinycompile" "" t) (autoload 'tinytag-install-sample-databases "tinytag" "" t) (autoload 'turn-on-tinytf-mode "tinytf" "" t) (autoload 'turn-on-tinyurl-mode "tinyurl" "" t)) ;; Copy from tinylib.el (defmacro tiny-setup-ti::macrov-mode-line-mode-menu (mode-symbol text) "Add MODE-SYMBOL to minor mode list in Emacs mode line menu." (let ((sym (vector (intern (symbol-name (` (, mode-symbol))))))) (` (when (boundp 'mode-line-mode-menu) ;; Emacs 21.1 (define-key mode-line-mode-menu (, sym) '(menu-item (, text) (, mode-symbol) :button (:toggle . (, mode-symbol)))))))) (defvar tiny-setup-load-hook nil "*Hook run when package is loaded.") (defconst tiny-setup-:library-compile-order '("tinylibenv.el" "tinyliba.el" "tinylibm.el" "tinylibb.el") "Order of compilation of the libraries. This variable is list of REGEXPS.") (defconst tiny-setup-:library-compile-exclude '("tinylib-ad.el") ;; adviced functions "Libraries not to compile.") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; SETUP CHOICES ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; See list of file descriptions with this bash script: ;; ;; head -1 $(ls *el | sort) | grep ';;' (defconst tiny-setup-:option-table '(("dired-sort" ("Dired sort package. Defines `s' key prefix to dired.") ("autoload")) ("folding" ("Folding content management package. Detect {{{ and }}}.") ("autoload")) ("tinyadvice" "Collection of advised functions." ("load")) ("tinyappend" "A simple text gathering to buffer utility." ("bind" "bindforce")) ("tinybookmark" "Keep file in organized sections." ("bind")) ("tinybuffer" "Change buffers in current window." ("bind" "bindforce")) ("tinycache" "Maintain a cache of visited files [compile, dired]." ()) ("tinychist" "Command history save/restore utility." ()) ("tinycygwin" "Cygwin bug reporting interface and other Cygwin utilities." ()) ;;#todo: ("tinycomment" "Smart comment setting utility." ("autoload" "bind")) ("tinycompile" "Compile buffer additions. Minor mode." ("autoload")) ("tinydesk" "Save and restore files between Emacs sessions." ("activate" "bind" "bindforce")) ("tinydiff" "Diff and patch minor mode. Browsing, patching." ("autoload" "bind" "bindforce")) ("tinydebian" "Debian Linux utilities for system administrator. Bug reports etc." ("autoload" "load")) ("tinydired" "Dired enhancements. Background Ange ftp support." ("autoload")) ("tinyeat" "Eat blocks of text at point, forward and backward." ("bind" "bindforce")) ("tinyef" "(E)lectric (f)ile minor mode. Easy C-x C-f filename composing." ("autoload" "bindextra")) ("tinygnus" "Gnus Plug-in. Additional functions. Spam complain and more." ("autoload")) ("tinyhotlist" "Hot-list of important buffers and files. Entry can be ange-ftp or dired too." ("autoload" "bind" "bindforce" "bindmouse" "bindmouseforce")) ("tinyigrep" "Top level interface to igrep.el." ("autoload" "bind" "bindforce")) ;; there is nothing to setup in libraries. These are already ;; autoloaded in tinyliba.el ("tinylib-ad" "Library of advised functions. Backward compatibility." ()) ("tinylib" "Library of general functions." ()) ("tinyliba" "Library for (a)utoload definitions." ()) ("tinylibb" "Library of (b)ackward compatible functions." ()) ("tinylibck" "Library to (c)onvert (k)eybindings for XEmacs or Emacs." ()) ("tinylibenv" "Library for environment check functions." ()) ("tinylibid" "Library for (Id)entifying buffer, regardless of mode." ()) ("tinylibm" "Library of s(m)all macros or functions." ()) ("tinylibmenu" "Library for echo-area menu." ()) ("tinylibmail" "Library of (m)ail and news (t)ool functions." ()) ("tinylibo" "Library for handling (o)verlays." ()) ("tinylibt" "Library for handling text properties." ()) ("tinylibxe" "Library for Emacs and XEmacs emulation." ()) ("tinyliby" "Library of functions related to Emacs s(y)stem." ("defalias")) ("tinylisp" "Emacs lisp programming help grab-bag." ("autoload" "activate")) ("tinyload" "Load set of packages when Emacs is idle (lazy load)." ()) ;; This asks lock password at startup, can't define "load" option ;; for this for unattended load. ("tinylock" "Simple Emacs locking utility." ()) ;;#todo: ("tinylpr" "Easy Emacs lpr command handling, pop-up, completions." ("bind")) ("tinymacro" "Fast way to assign newly created macro to a key. Redefines C-x )" ("bind" "bindforce")) ("tinymail" "Mail add-ons. Report incoming mail, passwd, BBDB complete." ("autoload")) ("tinymailbox" "Berkeley style mailbox browsing minor mode." ("autoload")) ("tinymy" "Collection of user (`my') functions. Simple solutions." ("load" "bind" "bindforce" "defalias" "defadvice")) ("tinynbr" "Number conversion minor mode oct/bin/hex." ("autoload")) ;; Already autoloaded. M-x turn-on-tinynbr-mode ("tinypad" "Emulate Windows notepad with extra menu." ("autoload")) ("tinypage" "Handling ^L pages. Select, cut, copy, renumber headings etc." ("autoload" "bind")) ("tinypair" "Self insert character (pa)irs () \"\" '' <>." ("autoload" "activate")) ;; Please see the documentation in this file ;; LOAD tinypath.el AS VERY FIRST PACKAGE. Before even tiny-setup.pl ("tinypath" "Manage Emacs startup dynamically." ()) ("tinyperl" "Grab-bag of Perl language utilities. Pod documentation browser." ("autoload")) ("tinypgp" "PGP minor mode, remailing, keyring management." ()) ("tinyprocmail" "Procmail minor mode and coding checker. See http://www.procmail.org/" ("autoload")) ("tinyreplace" "Handy query-replace, area, case preserve, words." ("bind")) ("tinyrmail" "RMAIL add-ons, pgp, mime labels, Spam complaint." ("autoload")) ("tinyscroll" "Enable or Disable auto-scroll for any buffer." ("autoload")) ("tinysearch" "Grab and search word under cursor." ("bind" "bindforce" "bindmousealt" "bindmousemeta")) ("tinytab" "Programmed TAB minor mode." ("autoload" "bind" "bindforce" "bindextra" "bindextraforce")) ("tinytag" "Coding help. E.g. show Java/Perl/C++ function call syntax while coding." ("autoload")) ("tinytf" "Document layout tool for '(T)echnical text (F)ormat." ("autoload")) ("tinyurl" "Mark and jump to any URL on current line. Support also C, C++, Perl, Elisp." ("autoload" "bind")) ("tinyvc" "CVS and RCS log minor mode. Check-out, Check-in." ("autoload")) ("tinyxreg" "Restore points and window configurations stored in register via X-popup." ("bind"))) "Packages and options. This variable is not user configurable. Format is: '((PACKAGE ((OPTION-STR ..) ..))).") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; USER SPACE: CONFIGURE SETUP FOR ALL FILES ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ---------------------------------------------------------------------- ;;; ;;;###autoload (defun tiny-setup (&optional type option-list) "Tiny Tools setup controller. See Message buffer for results. Please make sure you have run the makefile.pl with build option \"all\" or \"autoload\". You can verify this by finding files which contain word \"loaddefs\". Autoload statements are always defined when this function is called, so even if you do not define any options to be installed, they will be available in callable functions that trigger loading packages. This means, that you an call e.g function \\[tinytab-mode] and the call will trigger loading package tinytab.el Please notice, that this central setup function configures only the essential packages, even with TYPE and FEATURE-LIST. The listing \\[tiny-setup-display] lists many packages that are not loaded or set up in any default way because a) package's scope is very narrow and it may not interest the majority b) there is no sensible autoload and it requires manual settings: tinyload.el and tinypath.el are good example of this. c) package is a library and it has been taken cared of by other means. Remember that all functions are autoloaded and accessible, although packages marked may not have default configurations. Here is sample listing that you may expect from \\[tiny-setup-display] which displays then content of `tiny-setup-:option-table' when no tiny-setup configure options are not defined and you should load the package as instructed in the file itself: .. tinychist ... Command history save/restore utility. tinyload Load set of packages when Emacs is idle (lazy load). tinylock Simple emacs locking utility. ... tinynbr Number conversion minor mode oct/bin/hex. ... tinypath Manage Emacs startup dynamically. Here is one way to install packages: a) configure paths automatically b) load default setup and enable some extra features c) define delayed loading for some packages that you use most of the time. (load \"/ABSOLUTE-PATH/tinypath.el\") ;; Define \"ready to use packages\" (require 'tiny-setup) (tinypath-setup 'all ;; Activate default features safely ;; plus features that you want '(tinyeat--bind tinydesk--bindforce tinymy--defadvice ;; Make M-x compile smarter tinydiff--bind tinydired--autoload tinyef--bindextra tinyeat--bindforce tinymacro--bindforce tinydesk--bindforce tinypair--activate tinylisp--activate ;; turn on on in all .el buffers ..)) ;; Delayed loading of these packages, when Emacs goes idle. (setq tinyload-:load-list '(\"tinyadvice\" ;; NOTE: for Emacs only. \"tinymy\" \"tinymail\" \"tinygnus\" \"tinyigrep\" ..)) (require 'tinyload) Here is yet another example. The `tiny-setup' function can configure only the very basic features. You can manually set default values before packages are loaded (look into each file for interesting things). ;; First, configure few packages MANUALLY (require 'tinylibm) (ti::add-hooks 'tinytf-:mode-define-keys-hook '(tinytf-mode-define-keys tinytf-mode-define-f-keys)) (setq tinymy-:define-key-force t) (setq tinyef-:mode-key \"\\C-cmr\") (setq tinylock-:auto-lock-interval1 45) ;in minutes (setq tinyef-:mode-key-table '((?\[ . step-delete-back) ;KEY -- action symbol (?\] . step-delete-fwd) (?\* . chunk-delete) (?\; . move-back) (?\' . move-fwd) (?\~ . e-tilde) (?\/ . e-slash) (?\$ . e-dollar))) ;; After that, let the central configure tool do the rest (require 'tiny-setup) (tiny-setup 'all '(tinymy--bind-bindemacs tinytab--bindforce-bindextra tinyreplace--bindemacs tinyeat--bindforce)) The major TYPE of installation can be one of the following: 'autoload Setup packages so that they are loaded when the options are needed, but do not define any key-bindings that already exist. This will bind free keys to trigger loading packages. 'all Configure with all options on. This will affect free key-bindings. nil Autoload files (functions are ready for calling), but no defaults are configured unless OPTION-LIST is set. Alternatively, you can select from OPTION-LIST what packages and what options inside it will be installed. See list of packages and their options with command \\[tiny-setup-display] The syntax for each package is the same and the symbol passed is composed from keywords: -- Name of package affected, like `tinyeat--'. activate Activate feature in all related buffers. Like turning on `tinylisp-mode' in all Emacs lisp buffers or `tinyperl-mode' in all perl files. bind Bind default keys. This will arrange package to an autoload state. When a certain key is pressed, package is loaded. bindforce Overwrite any existing Emacs binding. This is like bind, but without a safe check. bindemacs Bind keys that are known to be occupied in Emacs. load Load package. If you're tempted to use this, consider investing to more efficient method described in tinyload.el. Packages that have complex setup or which can't be autoloaded easily are categorized as \"load\". autoload Configure package so that it will get loaded if function related to a package is needed. For example, to enable options in tinyadvice.el and tinyurl.el, you could send option list below. Notice that multiple options for a package are separated by single dashes. (require 'tiny-setup) (tinypath-setup 'all '(tinyadvice--load tinyurl--autoload-bind ...)) | | | | | Option 2. | Option 1. Package." (interactive) (when (and (interactive-p) (eq type nil) (eq option-list nil)) (setq type 'all)) (tiny-setup-autoload-read) (cond ((eq type 'all) (tiny-setup-all nil)) ((eq type 'autoload) (tiny-setup-all 'autoload-bind))) (when option-list (tiny-setup-option-process option-list)) (message "TinySetup: Done.%s" (if (ti::xemacs-p) " See buffer \" *Message-Log*\"" " See buffer *Messages*"))) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-option-process (option-list) "Process OPTION-LIST described in `tiny-setup'. OPTION-LIST items items are in form: PACKAGE--OPTION-OPTION-OPTION-.. Like '(tinymy--bind-bindextra) | | | option 2 option 1 See also `tiny-setup-:option-table'." (dolist (elt option-list) (let* ((name (symbol-name elt)) (package (if (string-match "\\(^[^ \t-]+\\)--" name) (match-string 1 name)))) (if package (tiny-setup-package package elt) (message "TinySetup: Invalid setup option format %s" name))))) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-all (&optional type) "Setup all tools with TYPE." (dolist (elt tiny-setup-:option-table) (tiny-setup-package (car elt) type))) ;;; ---------------------------------------------------------------------- ;;; ;;;###autoload (defun tiny-setup-display (&optional no-descriptions) "List all packages and available setup options. With Argument, like, \\[universal-argument], list NO-DESCRIPTIONS." (interactive "P") (let* ((buffer (get-buffer-create "*tiny-setup*"))) (with-current-buffer buffer (erase-buffer) (insert "package Supported install options\n" "----------- " (make-string 30 ?-) "\n") (dolist (elt tiny-setup-:option-table) (insert (format "%-20s %s\n%-20s %s\n" (car elt) (if (null (tiny-setup-nth-options elt)) "" (mapconcat 'identity (sort (tiny-setup-nth-options elt) 'string<) " ")) "" (tiny-setup-nth-description elt)))) (insert " The options can be installed by adding code like this to .emacs: (require 'tiny-setup) (tinypath-setup nil '(tinyadvice--load tinyurl--autoload-bind ...)) ") (goto-char (point-min)) (display-buffer (current-buffer))))) ;;; ---------------------------------------------------------------------- ;;; (put 'tiny-setup-error-macro 'lisp-indent-function 0) (put 'tiny-setup-error-macro 'edebug-form-spec '(body)) (defmacro tiny-setup-error-macro (&rest body) "Show error." (` (progn (pop-to-buffer (get-buffer-create "*TinySetup Error*")) (,@ body)))) ;;; ---------------------------------------------------------------------- ;;; (put 'tiny-setup-dolist-buffer-list 'lisp-indent-function 0) (put 'tiny-setup-dolist-buffer-list 'edebug-form-spec '(body)) (defmacro tiny-setup-dolist-buffer-list (&rest body) "Run BODY in each buffer." (` (dolist (buffer (buffer-list)) (with-current-buffer buffer (,@ body))))) ;;; ---------------------------------------------------------------------- ;;; ;;;###autoload (defun tiny-setup-autoload-read () "Read all autoloads. Makefile must have been run for this to work. Syntax in Tiny Tools kit bin/ directory: perl makefile.pl autoload." (condition-case err (progn ;; It's better to use `load' and not `require' because user may run ;; makefile again. (load "tiny-autoload-loaddefs-tiny") (load "tiny-autoload-loaddefs-other")) (error (let* ((str (format (concat "\ TinySetup: Error in reading autoload loaddefs. %s Symptoms: load-path: Please check that your `load-path' contains directories tiny/lisp/tiny and tiny/lisp/other. To check your load path, run \\[tinypath-load-path-display] or run this lisp code: (insert (prin1-to-string load-path)) | Put cursor here and press C-u C-x C-e Symptoms: autoload files: Check that the tiny-autoload*el files are present in these directories. If there is no autoload files, create them by running makefile: cd bin/ perl makefile.pl --verbose 2 autoload. Symptoms: compiled files There may be problem with compiled tiny-autoload*.elc files. Please remove all *.elc files and try again.") (prin1-to-string err)))) ;; Write to *Message* buffer (message str) (tiny-setup-error-macro (insert str " Symptoms for tinypath.el usage: If you use tinypath.el, it may be possible that it didn't find the default ~/elisp or ~/lisp directories. Please move all your Emacs setup files under one of these directories. Alternatively set the location of your private lisp with: (require 'cl) (setq tinypath-:load-path-root '(\"~/your-lisp-dir-location\")) (pushnew \"/ABSOLUTE/INSTALLATION-PATH/HERE\" load-path :test 'string=) (load \"tinypath\") (require 'tiny-setup) (tiny-setup 'all) Refer to doc/txt/README.txt in tiny-tools kit and \\[tinypath-version] documentation for more instructions how to let tinypath.el set the `load-path' automatically.")) (error str))))) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-option-strings (type) "Return list of options from symbol TYPE." (setq type (symbol-name type)) (if (not (string-match "--\\(.*\\)" type)) type (split-string (match-string 1 type) "[-]"))) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-package-require (package) (message "TinySetup: %s loaded." package) (unless (featurep (intern package)) (message "TinySetup: %s LOADED." package) (require (intern package)))) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-package-option-p (package opt option-list) "Check if PACKAGE and OPT is part of user requested OPTION-LIST." (let (ret) (dolist (elt option-list) (when (string= elt opt) (setq ret t) (return))) (unless ret (message "TinySetup: [%s] No option [] found for `%s'" package (if (eq 1 (length option-list)) (car option-list) (prin1-to-string option-list)))) ret)) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-package (package &optional type) "Activate PACKAGE with TYPE. If TYPE is nil, activate all options that do not contain word `force' or `load'." (let* ((req-options (and type (tiny-setup-option-strings type))) (list (tiny-setup-package-options package))) (cond ((null list) (message "TinySetup: %-15s No options to configure." package)) (t (unless req-options ;; nil, activate almost all (dolist (option list) (unless (string-match "^load\\|force" option) (push option req-options)))) (let* (function sym) (dolist (option req-options) (cond ((not (member option list)) (message "TinySetup: Unknown option %s. Choose from %s" option (prin1-to-string list))) (t (setq function (format "tiny-setup-%s-%s" package option)) (setq sym (intern-soft function)) (cond ((and (null sym) (string= option "load")) (tiny-setup-package-require package)) ((null sym) (message "TinySetup: ERROR Unknown function %s" function)) (t (setq function sym) (message "TinySetup: %-15s configured with `%s'" package option) (funcall function))))))))))) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-nth-options (elt) "Return option list from ELT." (nth 2 elt)) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-nth-description (elt) "Return option list from ELT." (nth 1 elt)) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-package-options (package) "Return list of options for PACKAGE." (let ((elt (assoc package tiny-setup-:option-table))) (when elt (tiny-setup-nth-options elt)))) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-define-key-1 (key keymap function &optional prefix str force) "Define KEY to KEYMAP using FUNCTION if not yet occupied. Input: KEY Key definitions KEYMAP The map. FUNCTION function to bind PREFIX Message prefix. Like \"Package:\" who requested change. STR Human readable key definition. Shown to user. FORCE Override key definition without a check." (setq str (if (stringp str) (format "\"%s\"" str) "")) (let ((def (lookup-key keymap key))) (cond (force (message "%sKey %-10s%s set to `%s' (FORCED, was `%s')." (or prefix "") (prin1-to-string key) str (symbol-name function) def) (define-key keymap key function)) (t (cond ((or (eq def function) (memq def '(nil ignore)) ;; Lookup key returns NBR if the sequence of keys exceed ;; the last keymap prefix ;; C-cck --> C-cc is undefined, so there is no C-c c map yet (integerp def)) (message "%sKey %-10s%s set to `%s'." (or prefix "") (prin1-to-string key) str (symbol-name function)) (define-key keymap key function)) (t (message "%sKey %-10s%s already has a definition `%s'. Not set to `%s'" (or prefix "") (prin1-to-string key) str (prin1-to-string def) (symbol-name function)))))))) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-define-key (key keymap function &optional str force) "Define KEY to KEYMAP using FUNCTION. Display STR and FORCE binding." (tiny-setup-define-key-1 key keymap function "TinySetup: " str force)) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-alist-search (alist regexp) "Search ALIST for REGEXP." (dolist (elt alist) (if (string-match regexp (car elt)) (return elt)))) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-aput (sym regexp key value &optional force) "Search SYM's for REGEXP and set KEY to VALUE if not found. This function effectively compares each key in SYM to REGEXP and if there is no matches, it adds new (KEY . VALUE) pair. Useful, if something needs to be added to the `auto-mode-alist', but previous definitions must be preserved." (let* ((found (tiny-setup-alist-search (symbol-value sym) regexp))) (cond ((and found (eq (cdr found) value)) (message "TinySetup: `%s' now contains (%s . %s)" (symbol-name sym) key value)) (found (message "TinySetup: `%s' already contains %s. Not set to (%s . %s)" (symbol-name sym) (prin1-to-string found) key value)) (t (message "TinySetup: `%s' now contains (%s . %s)" (symbol-name sym) key value)) (push (cons key value) (symbol-value sym))))) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-defalias (symbol definition) "Like `defalias' but with verbose messages." (message "TinySetup: defalias `%s' => `%s'" (symbol-name symbol) (symbol-name definition)) (defalias symbol definition)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; TIMING UTILITIES ;; These are admistrative utilies for package maintainer(s) ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-time-difference (a b) "Calculate difference between times A and B. The input must be in form of '(current-time)' The returned value is difference in seconds. E.g. if you want to calculate days; you'd do \(/ (ti::date-time-difference a b) 86400) ;; 60sec * 60min * 24h" (multiple-value-bind (s0 s1 s2) a (setq a (+ (* (float (ash 1 16)) s0) (float s1) (* 0.0000001 s2)))) (multiple-value-bind (s0 s1 s2) b (setq b (+ (* (float (ash 1 16)) s0) (float s1) (* 0.0000001 s2)))) (- a b)) ;;; ---------------------------------------------------------------------- ;;; (defvar tiny-setup-:time nil) (put 'tiny-setup-time-this 'lisp-indent-function 0) (put 'tiny-setup-time-this 'edebug-form-spec '(body)) (defmacro tiny-setup-time-this (&rest body) "Run BODY with and time execution. Time is in `my-:tmp-time-diff'." (` (let* ((tmp-time-A (current-time)) tmp-time-B) (,@ body) (setq tmp-time-B (current-time)) (setq tiny-setup-:time (tiny-setup-time-difference tmp-time-B tmp-time-A))))) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-time-load-file (file) "Time lisp FILE loading." (interactive "fload file and time it: ") (tiny-setup-time-this (load file)) (message "Tiny: Timing %-15s took %12f secs" file tiny-setup-:time)) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-test-load-time-libraries () "Time package load times." (interactive) (message "\n\n** Tiny setup: timing test start\n") (message "load-path: %s" (prin1-to-string load-path)) (let* ((path (locate-library "tinylib.el")) (time-a (current-time)) time-b) (if (not path) (message "Tiny: [timing] Can't find tinylib.el along `load-path'") (setq path (file-name-directory path)) (dolist (pkg (directory-files path 'full "^tinylib.*el")) (tiny-setup-time-load-file pkg)) (setq time-b (current-time)) (message "Tiny: total time is %s seconds" (tiny-setup-time-difference time-b time-a)) (display-buffer "*Messages*")))) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-test-load-all () "Load each package to check against errors." (interactive) (message "\n\n** Tiny setup: load test start\n") (let* ((path (locate-library "tinylib.el"))) (if (not path) (message "Tiny: [load test] Can't find tinylib.el along `load-path'") (setq path (file-name-directory path)) (dolist (pkg (directory-files path 'full "^tiny.*el")) (load pkg)) (display-buffer "*Messages*")))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; AUTOLOAD UTILITIES ;; These are admistrative utilies for package maintainer(s) ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-directory-last (dir) "Return last directory name in DIR. /dir1/dir2/ -> dir2." (if (string-match "[/\\]\\([^/\\]+\\)[/\\]?$" dir) (match-string 1 dir) "")) ;;; ---------------------------------------------------------------------- ;;; (defun tiny-setup-directory-to-file-name (dir template) "Make file name from NAME and TEMPLATE.