From 69e9d0d0d6df2f573d600ca7b2d6ca709004b832 Mon Sep 17 00:00:00 2001 From: aurelien Date: Wed, 3 Aug 2011 12:55:15 +0200 Subject: first commit --- .emacs | 1380 +++++++ .emacs.d/auto-save-list/.saves-2372-bob.home~ | 0 .emacs.d/elpa/package.el | 1507 +++++++ .emacs.d/elpa/package.el~ | 1507 +++++++ elisp/erbot/.cvsignore | 2 + elisp/erbot/AUTHORS | 40 + elisp/erbot/COPYING | 674 ++++ elisp/erbot/CVS/Entries | 41 + elisp/erbot/CVS/Entries.Log | 2 + elisp/erbot/CVS/Repository | 1 + elisp/erbot/CVS/Root | 1 + elisp/erbot/CVS/Template | 0 elisp/erbot/ChangeLog | 484 +++ elisp/erbot/HISTORY.txt | 55 + elisp/erbot/Makefile | 40 + elisp/erbot/README.txt | 90 + elisp/erbot/contrib/CVS/Entries | 20 + elisp/erbot/contrib/CVS/Repository | 1 + elisp/erbot/contrib/CVS/Root | 1 + elisp/erbot/contrib/CVS/Template | 0 elisp/erbot/contrib/META-feeding-info-terms.el | 73 + elisp/erbot/contrib/README.txt | 7 + elisp/erbot/contrib/bash-quotes.el | 337 ++ elisp/erbot/contrib/faith.el | 566 +++ elisp/erbot/contrib/flame.el | 356 ++ elisp/erbot/contrib/geek.el | 138 + elisp/erbot/contrib/google.el | 271 ++ elisp/erbot/contrib/h4x0r.el | 106 + elisp/erbot/contrib/haiku.el | 311 ++ elisp/erbot/contrib/idledo.el | 1157 ++++++ elisp/erbot/contrib/lines.el | 586 +++ elisp/erbot/contrib/mkback.el | 601 +++ elisp/erbot/contrib/oct.el | 540 +++ elisp/erbot/contrib/shs.el | 552 +++ elisp/erbot/contrib/soap.el | 66 + elisp/erbot/contrib/timerfunctions.el | 431 ++ elisp/erbot/contrib/translate.el | 237 ++ elisp/erbot/contrib/units.el | 179 + elisp/erbot/contrib/wtf.el | 964 +++++ elisp/erbot/erball.el | 209 + elisp/erbot/erbbdb.el | 223 + elisp/erbot/erbc-backquote.el | 57 + elisp/erbot/erbc.el | 5141 ++++++++++++++++++++++++ elisp/erbot/erbc2.el | 349 ++ elisp/erbot/erbc3.el | 290 ++ elisp/erbot/erbc4.el | 333 ++ elisp/erbot/erbc5.el | 192 + elisp/erbot/erbc6.el | 75 + elisp/erbot/erbcompat.el | 55 + elisp/erbot/erbcountry.el | 518 +++ elisp/erbot/erbcspecial.el | 148 + elisp/erbot/erbdata.el | 66 + elisp/erbot/erbedit.el | 150 + elisp/erbot/erbeng.el | 300 ++ elisp/erbot/erbforget.el | 138 + elisp/erbot/erbim.el | 216 + elisp/erbot/erbjavadoc.el | 169 + elisp/erbot/erbkarma.el | 163 + elisp/erbot/erblisp.el | 276 ++ elisp/erbot/erblog.el | 78 + elisp/erbot/erbmerge.el | 48 + elisp/erbot/erbmsg.el | 583 +++ elisp/erbot/erbot-lispy.el | 89 + elisp/erbot/erbot.el | 961 +++++ elisp/erbot/erbp.el | 3376 ++++++++++++++++ elisp/erbot/erbrss.el | 375 ++ elisp/erbot/erbtrain.el | 315 ++ elisp/erbot/erbtranslate.el | 139 + elisp/erbot/erbunlisp.el | 90 + elisp/erbot/erburl.el | 219 + elisp/erbot/erbutils.el | 660 +++ elisp/erbot/erbwiki.el | 646 +++ elisp/erbot/examples/CVS/Entries | 2 + elisp/erbot/examples/CVS/Repository | 1 + elisp/erbot/examples/CVS/Root | 1 + elisp/erbot/examples/CVS/Template | 0 elisp/erbot/examples/dotemacs-mybot | 238 ++ 77 files changed, 30213 insertions(+) create mode 100644 .emacs create mode 100644 .emacs.d/auto-save-list/.saves-2372-bob.home~ create mode 100644 .emacs.d/elpa/package.el create mode 100644 .emacs.d/elpa/package.el~ create mode 100644 elisp/erbot/.cvsignore create mode 100644 elisp/erbot/AUTHORS create mode 100644 elisp/erbot/COPYING create mode 100644 elisp/erbot/CVS/Entries create mode 100644 elisp/erbot/CVS/Entries.Log create mode 100644 elisp/erbot/CVS/Repository create mode 100644 elisp/erbot/CVS/Root create mode 100644 elisp/erbot/CVS/Template create mode 100644 elisp/erbot/ChangeLog create mode 100644 elisp/erbot/HISTORY.txt create mode 100644 elisp/erbot/Makefile create mode 100644 elisp/erbot/README.txt create mode 100644 elisp/erbot/contrib/CVS/Entries create mode 100644 elisp/erbot/contrib/CVS/Repository create mode 100644 elisp/erbot/contrib/CVS/Root create mode 100644 elisp/erbot/contrib/CVS/Template create mode 100644 elisp/erbot/contrib/META-feeding-info-terms.el create mode 100644 elisp/erbot/contrib/README.txt create mode 100644 elisp/erbot/contrib/bash-quotes.el create mode 100644 elisp/erbot/contrib/faith.el create mode 100644 elisp/erbot/contrib/flame.el create mode 100644 elisp/erbot/contrib/geek.el create mode 100644 elisp/erbot/contrib/google.el create mode 100644 elisp/erbot/contrib/h4x0r.el create mode 100644 elisp/erbot/contrib/haiku.el create mode 100644 elisp/erbot/contrib/idledo.el create mode 100644 elisp/erbot/contrib/lines.el create mode 100644 elisp/erbot/contrib/mkback.el create mode 100644 elisp/erbot/contrib/oct.el create mode 100644 elisp/erbot/contrib/shs.el create mode 100644 elisp/erbot/contrib/soap.el create mode 100644 elisp/erbot/contrib/timerfunctions.el create mode 100644 elisp/erbot/contrib/translate.el create mode 100644 elisp/erbot/contrib/units.el create mode 100644 elisp/erbot/contrib/wtf.el create mode 100644 elisp/erbot/erball.el create mode 100644 elisp/erbot/erbbdb.el create mode 100644 elisp/erbot/erbc-backquote.el create mode 100644 elisp/erbot/erbc.el create mode 100644 elisp/erbot/erbc2.el create mode 100644 elisp/erbot/erbc3.el create mode 100644 elisp/erbot/erbc4.el create mode 100644 elisp/erbot/erbc5.el create mode 100644 elisp/erbot/erbc6.el create mode 100644 elisp/erbot/erbcompat.el create mode 100644 elisp/erbot/erbcountry.el create mode 100644 elisp/erbot/erbcspecial.el create mode 100644 elisp/erbot/erbdata.el create mode 100644 elisp/erbot/erbedit.el create mode 100644 elisp/erbot/erbeng.el create mode 100644 elisp/erbot/erbforget.el create mode 100644 elisp/erbot/erbim.el create mode 100644 elisp/erbot/erbjavadoc.el create mode 100644 elisp/erbot/erbkarma.el create mode 100644 elisp/erbot/erblisp.el create mode 100644 elisp/erbot/erblog.el create mode 100644 elisp/erbot/erbmerge.el create mode 100644 elisp/erbot/erbmsg.el create mode 100644 elisp/erbot/erbot-lispy.el create mode 100644 elisp/erbot/erbot.el create mode 100644 elisp/erbot/erbp.el create mode 100644 elisp/erbot/erbrss.el create mode 100644 elisp/erbot/erbtrain.el create mode 100644 elisp/erbot/erbtranslate.el create mode 100644 elisp/erbot/erbunlisp.el create mode 100644 elisp/erbot/erburl.el create mode 100644 elisp/erbot/erbutils.el create mode 100644 elisp/erbot/erbwiki.el create mode 100644 elisp/erbot/examples/CVS/Entries create mode 100644 elisp/erbot/examples/CVS/Repository create mode 100644 elisp/erbot/examples/CVS/Root create mode 100644 elisp/erbot/examples/CVS/Template create mode 100644 elisp/erbot/examples/dotemacs-mybot diff --git a/.emacs b/.emacs new file mode 100644 index 0000000..48e3fe7 --- /dev/null +++ b/.emacs @@ -0,0 +1,1380 @@ +;; -*- emacs-lisp -*- + + (let ((buffer (url-retrieve-synchronously + "http://tromey.com/elpa/package-install.el"))) + (save-excursion + (set-buffer buffer) + (goto-char (point-min)) + (re-search-forward "^$" nil 'move) + (eval-region (point) (point-max)) + (kill-buffer (current-buffer)))) + +(setq erbot-nickserv-p t) + +(setq erc-prompt-for-nickserv-password nil) + +(setq erc-nickserv-passwords + '((freenode (("pbot" . "*"))))) + +(setq h4x0r-sometimes-replace + '(("ea" "33") ("er" "0r") ("a" "4") + ;;("b" "8") + ;;("d" "|>") + ("e" "3" "E") ;;("f" "|=") ("h" "|-|") + ;;("i" "1" "|") ;;("k" "|<" "x") + ;;("l" "1" "|_") ("m" "|\\/|") ("n" "|\\|") + ("o" "0") ;;("q" "@") + ("s" + "5" "Z" "$") + ;;("t" "+" "7") + ("ck" "x") ("u" "U") ;;("v" "\\/") + + ;("x" + ;X" "><") ("y" "j" + )) + +(add-to-list 'load-path "~/elisp") +(add-to-list 'load-path "~/elisp/erbot") +(add-to-list 'load-path "~/elisp/erbot/contrib/idledo") +(add-to-list 'load-path "~/elisp/erbot/erball") +(add-to-list 'load-path "~/elisp/erbot/erbbdb") +(add-to-list 'load-path "~/elisp/erbot/erbc2") +(add-to-list 'load-path "~/elisp/erbot/erbc3") +(add-to-list 'load-path "~/elisp/erbot/erbc4") +(add-to-list 'load-path "~/elisp/erbot/erbc5") +(add-to-list 'load-path "~/elisp/erbot/erbc6") +(add-to-list 'load-path "~/elisp/erbot/erbc-backquote") +(add-to-list 'load-path "~/elisp/erbot/erbc") +(add-to-list 'load-path "~/elisp/erbot/erbcompat") +(add-to-list 'load-path "~/elisp/erbot/erbcountry") +(add-to-list 'load-path "~/elisp/erbot/erbcspecial") +(add-to-list 'load-path "~/elisp/erbot/erbdata") +(add-to-list 'load-path "~/elisp/erbot/erbedit") +(add-to-list 'load-path "~/elisp/erbot/erbeng") +(add-to-list 'load-path "~/elisp/erbot/erbim") +(add-to-list 'load-path "~/elisp/erbot/erbkarma") +(add-to-list 'load-path "~/elisp/erbot/erblisp") +(add-to-list 'load-path "~/elisp/erbot/erblog") +(add-to-list 'load-path "~/elisp/erbot/erbmerge") +(add-to-list 'load-path "~/elisp/erbot/erbmsg") +(add-to-list 'load-path "~/elisp/erbot/erbp") +(add-to-list 'load-path "~/elisp/erbot/erbrss") +(add-to-list 'load-path "~/elisp/erbot/erbtrain") +(add-to-list 'load-path "~/elisp/erbot/erbunlisp") +(add-to-list 'load-path "~/elisp/erbot/erburl") +(add-to-list 'load-path "~/elisp/erbot/erbwiki") +(add-to-list 'load-path "~/elisp/erbot/contrib/faith") +(add-to-list 'load-path "~/elisp/erbot/contrib/flame") +(add-to-list 'load-path "~/elisp/erbot/contrib/geek") +(add-to-list 'load-path "~/elisp/erbot/contrib/h4x0r") +(add-to-list 'load-path "~/elisp/erbot/contrib/haiku") +(add-to-list 'load-path "~/elisp/erbot/contrib/lines") +(add-to-list 'load-path "~/elisp/erbot/contrib/mkback") +(add-to-list 'load-path "~/elisp/erbot/contrib/oct") +(add-to-list 'load-path "~/elisp/erbot/contrib/shs") +(add-to-list 'load-path "~/elisp/erbot/contrib/timerfunctions") +(add-to-list 'load-path "~/elisp/erbot/contrib/translate") +(add-to-list 'load-path "~/elisp/erbot/contrib/units") +(add-to-list 'load-path "~/elisp/erbot/contrib/wtf") + +(load "~/elisp/erbot/erbot.el") +(load "~/elisp/erbot/contrib/idledo.el") +(load "~/elisp/erbot/erball.el") +(load "~/elisp/erbot/erbbdb.el") +(load "~/elisp/erbot/erbc2.el") +(load "~/elisp/erbot/erbc3.el") +(load "~/elisp/erbot/erbc4.el") +(load "~/elisp/erbot/erbc5.el") +(load "~/elisp/erbot/erbc6.el") +(load "~/elisp/erbot/erbc-backquote.el") +(load "~/elisp/erbot/erbc.el") +(load "~/elisp/erbot/erbcompat.el") +(load "~/elisp/erbot/erbcountry.el") +(load "~/elisp/erbot/erbcspecial.el") +(load "~/elisp/erbot/erbdata.el") +(load "~/elisp/erbot/erbedit.el") +(load "~/elisp/erbot/erbeng.el") +(load "~/elisp/erbot/erbim.el") +(load "~/elisp/erbot/erbkarma.el") +(load "~/elisp/erbot/erblisp.el") +(load "~/elisp/erbot/erblog.el") +(load "~/elisp/erbot/erbmerge.el") +(load "~/elisp/erbot/erbmsg.el") +(load "~/elisp/erbot/erbp.el") +(load "~/elisp/erbot/erbrss.el") +(load "~/elisp/erbot/erbtrain.el") +(load "~/elisp/erbot/erbunlisp.el") +(load "~/elisp/erbot/erburl.el") +(load "~/elisp/erbot/erbwiki.el") +(load "~/elisp/erbot/contrib/faith.el") +(load "~/elisp/erbot/contrib/flame.el") +(load "~/elisp/erbot/contrib/geek.el") +(load "~/elisp/erbot/contrib/h4x0r.el") +(load "~/elisp/erbot/contrib/haiku.el") +(load "~/elisp/erbot/contrib/lines.el") +(load "~/elisp/erbot/contrib/mkback.el") +(load "~/elisp/erbot/contrib/oct.el") +(load "~/elisp/erbot/contrib/shs.el") +(load "~/elisp/erbot/contrib/timerfunctions.el") +(load "~/elisp/erbot/contrib/translate.el") +(load "~/elisp/erbot/contrib/units.el") +(load "~/elisp/erbot/contrib/wtf.el") + +(setq erc-keywords '("pbot" "parabola")) + +(setq fs-internal-english-weights + + '( + 30 ; doctor --- + 30 ; yow + 30 ; fortune + 2 ;; flame + )) + +(setq fs-internal-botito-mode nil) + +(setq fs-web-page-title-p t) + +;; this optional step +;; helps the bot get the locations of the .el files in emacs +(let ((aa default-directory)) + (cd "/usr/share/emacs/site-lisp") + (normal-top-level-add-subdirs-to-load-path) + (cd aa)) + +(require 'cl) +(setq erc-port 6667) +(require 'erc) +(require 'erc-match) +(require 'erc-track) +(require 'erball) +(require 'erburl) +(add-hook 'erc-mode-hook + '(lambda () (interactive) + (require 'erc-match) + (erc-match-mode 1) + (erc-match-enable) + (require 'erc-button) + (erc-button-enable) + nil + )) + + + (require 'erburl) + (erburl-scrape-terms + "http://www.emacswiki.org/cgi-bin/wiki?action=index") + (require 'erburl) + (erburl-scrape-terms + "http://wiki.parabolagnulinux.org") + (require 'erburl) + (erburl-scrape-terms + "https://bugs.parabolagnulinux.org/bugs/index") + (require 'erburl) + (erburl-scrape-terms + "http://libreplanet.org/wiki/Main_Page") + (require 'erburl) + (erburl-scrape-terms + "https://wiki.archlinux.org/index.php/Main_Page") + (require 'erburl) + (erburl-scrape-terms + "http://savannah.gnu.org/") + (require 'erburl) + (erburl-scrape-terms + "http://search.cpan.org/") + +;;(setq erbmsg-functions-p t) + +(setq erbot-erbmsg-p t) + +(setq erbn-url-functions-p t) + +(setq erbot-paranoid-p nil) + +(setq bbdb-file "~/pub/data/botbbdb") + +(setq erbot-servers-channels-test + '(("irc.freenode.net" + ("#." + ) + 6667 ;; this is the port, optional, can be omitted. + ) + + )) + + + + +(erbot-install) + + + +(add-hook 'erc-server-376-hook + '(lambda (&rest args) + (interactive) + (erc-track-modified-channels-mode 1) + nil)) + +(global-unset-key "\C-cs") + +(global-set-key "\C-cj " 'erbot-join-servers) +(global-set-key [f9 f1] 'erbot-join-servers) + +(global-unset-key [f6]) +(global-set-key [f6 f6] 'erblog-show-targets) +(global-set-key [f6 f7] 'erblog-reset-targets) +(global-set-key "\C-c\C-c" 'erc-send-current-line) + + +(global-set-key "\C-cr" 'erblog-reset-targets) + + + +(setq fsi-m8b-p t) + + + +;;(setq fs-limit-line-length 125) + + +;;(setq fs-limit-length + ;; 410) + +;;(setq fs-limit-lines 5 ) + +(setq bbdb-case-fold-search t) +(setq erc-auto-query t) + +;; Don't send more than 5 messages in 10 seconds. This prevents the +;; bot from getting kicked. +(setq erc-server-flood-penalty 2) +(setq erc-server-flood-margin 10) + +;; To restrict "automated" replies, change the "" below to your +;; favorite channels, example: +;;"\\(mychannel1\\|mychannel2\\)" +(setq fs-internal-query-target-regexp "") + +(setq fs-internal-google-level 60) + +(setq erbkarma-file "~/public_html/karma/karma") +(setq fs-internal-google-time 4) +(setq fs-internal-dictionary-time 4) + +(load "~/.emacs.private") + + +(setq erbkarma-tgt-check-string + "^\\(#parabola\\)$") + +;; .emacs ends here.. + + + + +(setq erbot-nick "pbot") +(setq erc-user-full-name "parabola") + +(setq erbot-servers-channels-main + '(("irc.freenode.net" + ("#." + )) + + )) + +(setq erbot-servers-channels erbot-servers-channels-main) + + +(setq fs-google-level 60) + + +(setq erbot-servers-channels-test + '(("irc.freenode.net" + ("#." + )) + + )) + +(setq bbdb-file-coding-system 'raw-text) +(require 'erball) +(erbunlisp-install) + +;; this delysid's server containing many dictionaries, if you prefer +;; the default server dict.org, just comment out this line. +(setq dictionary-server "dict.tu-graz.ac.at") + + +(fs-pf-load) +(fs-pv-load) + +(ignore-errors + (fs-user-init)) + +(require 'idledo) +(idledo-add-periodic-action-crude + '(fs-pv-save)) + +(add-hook 'kill-emacs-hook + 'fs-pv-save) + +;; consider uncommenting these +(add-to-list 'erblisp-allowed-words '&optional) +(add-to-list 'erblisp-allowed-words '&rest) + + +;;uncomment this only for a channel full of emacs hackers... see C-h v +(setq fs-internal-parse-error-p t) + +(setq units-dat-file "/usr/share/misc/units.dat") + +(add-to-list 'load-path "~/public_html/data") + + + +;; .emacs ends here.. +(custom-set-variables + ;; custom-set-variables was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(erc-email-userid "bot") + '(erc-user-full-name "Parabola GNU / Linux-Libre")) +(custom-set-faces + ;; custom-set-faces was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(default ((t (:inherit nil :stipple nil :background "unspecified-bg" :foreground "unspecified-fg" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 1 :width normal :foundry "default" :family "freemono"))))) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) + + +;;; This was installed by package-install.el. +;;; This provides support for the package system and +;;; interfacing with ELPA, the package archive. +;;; Move this code earlier if you want to reference +;;; packages in your .emacs. +(when + (load + (expand-file-name "~/.emacs.d/elpa/package.el")) + (package-initialize)) diff --git a/.emacs.d/auto-save-list/.saves-2372-bob.home~ b/.emacs.d/auto-save-list/.saves-2372-bob.home~ new file mode 100644 index 0000000..e69de29 diff --git a/.emacs.d/elpa/package.el b/.emacs.d/elpa/package.el new file mode 100644 index 0000000..1cecbe3 --- /dev/null +++ b/.emacs.d/elpa/package.el @@ -0,0 +1,1507 @@ +;;; package.el --- Simple package system for Emacs + +;; Copyright (C) 2007, 2008, 2009 Tom Tromey + +;; Author: Tom Tromey +;; Created: 10 Mar 2007 +;; Version: 0.9 +;; Keywords: tools + +;; This file is not (yet) part of GNU Emacs. +;; However, it is distributed under the same license. + +;; GNU Emacs 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 3, or (at your option) +;; any later version. + +;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Change Log: + +;; 2 Apr 2007 - now using ChangeLog file +;; 15 Mar 2007 - updated documentation +;; 14 Mar 2007 - Changed how obsolete packages are handled +;; 13 Mar 2007 - Wrote package-install-from-buffer +;; 12 Mar 2007 - Wrote package-menu mode + +;;; Commentary: + +;; To use this, put package.el somewhere on your load-path. Then add +;; this to your .emacs: +;; +;; (load "package") +;; (package-initialize) +;; +;; This will automatically make available the packages you have +;; installed using package.el. If your .emacs will refer to these +;; packages, you may want to initialize the package manager near the +;; top. +;; +;; Note that if you want to be able to automatically download and +;; install packages from ELPA (the Emacs Lisp Package Archive), then +;; you will need the 'url' package. This comes with Emacs 22; Emacs +;; 21 users will have to find it elsewhere. +;; +;; If you installed package.el via the auto-installer: +;; +;; http://tromey.com/elpa/ +;; +;; then you do not need to edit your .emacs, as the installer will +;; have done this for you. The installer will also install the url +;; package if you need it. + +;; Other external functions you may want to use: +;; +;; M-x package-list-packages +;; Enters a mode similar to buffer-menu which lets you manage +;; packages. You can choose packages for install (mark with "i", +;; then "x" to execute) or deletion (not implemented yet), and you +;; can see what packages are available. This will automatically +;; fetch the latest list of packages from ELPA. +;; +;; M-x package-list-packages-no-fetch +;; Like package-list-packages, but does not automatically fetch the +;; new list of packages. +;; +;; M-x package-install-from-buffer +;; Install a package consisting of a single .el file that appears +;; in the current buffer. This only works for packages which +;; define a Version header properly; package.el also supports the +;; extension headers Package-Version (in case Version is an RCS id +;; or similar), and Package-Requires (if the package requires other +;; packages). +;; +;; M-x package-install-file +;; Install a package from the indicated file. The package can be +;; either a tar file or a .el file. A tar file must contain an +;; appropriately-named "-pkg.el" file; a .el file must be properly +;; formatted as with package-install-from-buffer. + +;; The idea behind package.el is to be able to download packages and +;; install them. Packages are versioned and have versioned +;; dependencies. Furthermore, this supports built-in packages which +;; may or may not be newer than user-specified packages. This makes +;; it possible to upgrade Emacs and automatically disable packages +;; which have moved from external to core. (Note though that we don't +;; currently register any of these, so this feature does not actually +;; work.) + +;; This code supports a single package repository, ELPA. All packages +;; must be registered there. + +;; A package is described by its name and version. The distribution +;; format is either a tar file or a single .el file. + +;; A tar file should be named "NAME-VERSION.tar". The tar file must +;; unpack into a directory named after the package and version: +;; "NAME-VERSION". It must contain a file named "PACKAGE-pkg.el" +;; which consists of a call to define-package. It may also contain a +;; "dir" file and the info files it references. + +;; A .el file will be named "NAME-VERSION.el" in ELPA, but will be +;; installed as simply "NAME.el" in a directory named "NAME-VERSION". + +;; The downloader will download all dependent packages. It will also +;; byte-compile the package's lisp at install time. + +;; At activation time we will set up the load-path and the info path, +;; and we will load the package's autoloads. If a package's +;; dependencies are not available, we will not activate that package. + +;; Conceptually a package has multiple state transitions: +;; +;; * Download. Fetching the package from ELPA. +;; * Install. Untar the package, or write the .el file, into +;; ~/.emacs.d/elpa/ directory. +;; * Byte compile. Currently this phase is done during install, +;; but we may change this. +;; * Activate. Evaluate the autoloads for the package to make it +;; available to the user. +;; * Load. Actually load the package and run some code from it. + +;;; Thanks: +;;; (sorted by sort-lines): + +;; Jim Blandy +;; Karl Fogel +;; Kevin Ryde +;; Lawrence Mitchell +;; Michael Olson +;; Sebastian Tennant +;; Stefan Monnier +;; Vinicius Jose Latorre +;; Phil Hagelberg + +;;; ToDo: + +;; - putting info dirs at the start of the info path means +;; users see a weird ordering of categories. OTOH we want to +;; override later entries. maybe emacs needs to enforce +;; the standard layout? +;; - put bytecode in a separate directory tree +;; - perhaps give users a way to recompile their bytecode +;; or do it automatically when emacs changes +;; - give users a way to know whether a package is installed ok +;; - give users a way to view a package's documentation when it +;; only appears in the .el +;; - use/extend checkdoc so people can tell if their package will work +;; - "installed" instead of a blank in the status column +;; - tramp needs its files to be compiled in a certain order. +;; how to handle this? fix tramp? +;; - on emacs 21 we don't kill the -autoloads.el buffer. what about 22? +;; - maybe we need separate .elc directories for various emacs versions +;; and also emacs-vs-xemacs. That way conditional compilation can +;; work. But would this break anything? +;; - should store the package's keywords in archive-contents, then +;; let the users filter the package-menu by keyword. See +;; finder-by-keyword. (We could also let people view the +;; Commentary, but it isn't clear how useful this is.) +;; - William Xu suggests being able to open a package file without +;; installing it +;; - Interface with desktop.el so that restarting after an install +;; works properly +;; - Implement M-x package-upgrade, to upgrade any/all existing packages +;; - Use hierarchical layout. PKG/etc PKG/lisp PKG/info +;; ... except maybe lisp? +;; - It may be nice to have a macro that expands to the package's +;; private data dir, aka ".../etc". Or, maybe data-directory +;; needs to be a list (though this would be less nice) +;; a few packages want this, eg sokoban +;; - package menu needs: +;; ability to know which packages are built-in & thus not deletable +;; it can sometimes print odd results, like 0.3 available but 0.4 active +;; why is that? +;; - Allow multiple versions on the server...? +;; [ why bother? ] +;; - Don't install a package which will invalidate dependencies overall +;; - Allow something like (or (>= emacs 21.0) (>= xemacs 21.5)) +;; [ currently thinking, why bother.. KISS ] +;; - Allow optional package dependencies +;; then if we require 'bbdb', bbdb-specific lisp in lisp/bbdb +;; and just don't compile to add to load path ...? +;; - Have a list of archive URLs? [ maybe there's no point ] +;; - David Kastrup pointed out on the xemacs list that for GPL it +;; is friendlier to ship the source tree. We could "support" that +;; by just having a "src" subdir in the package. This isn't ideal +;; but it probably is not worth trying to support random source +;; tree layouts, build schemes, etc. +;; - Our treatment of the info path is somewhat bogus +;; - perhaps have an "unstable" tree in ELPA as well as a stable one + +;;; Code: + +(defconst package-archive-base "http://tromey.com/elpa/" + "Base URL for the package archive. +Ordinarily you should not need to edit this. +The default points to ELPA, the Emacs Lisp Package Archive. +Note that some code in package.el assumes that this is an http: URL.") + +(defconst package-archive-version 1 + "Version number of the package archive understood by this file. +Lower version numbers than this will probably be understood as well.") + +;; Note that this only works if you have the password, which you +;; probably don't :-). Also if you are using Emacs 21 then you will +;; need to hack ange-ftp-name-format to make this work. +(defvar package-archive-upload-base "/elpa@tromey.com@tromey.com:/" + "Base location for uploading to package archive.") + +(defconst package-el-maintainer "Tom Tromey " + "The package.el maintainer.") + +(defconst package-el-version "0.9" + "Version of package.el.") + +;; We don't prime the cache since it tends to get out of date. +(defvar package-archive-contents + nil + "A representation of the contents of the ELPA archive. +This is an alist mapping package names (symbols) to package +descriptor vectors. These are like the vectors for `package-alist' +but have an extra entry which is 'tar for tar packages and +'single for single-file packages.") + +(defvar package-user-dir + (expand-file-name (convert-standard-filename "~/.emacs.d/elpa")) + "Name of the directory where the user's packages are stored.") + +(defvar package-directory-list + (list (file-name-as-directory package-user-dir) + "/usr/share/emacs/site-lisp/elpa/") + "List of directories to search for packages.") + +(defun package-version-split (string) + "Split a package string into a version list." + (mapcar 'string-to-int (split-string string "[.]"))) + +(defconst package--builtins-base + ;; We use package-version split here to make sure to pick up the + ;; minor version. + `((emacs . [,(package-version-split emacs-version) nil + "GNU Emacs"]) + (package . [,(package-version-split package-el-version) + nil "Simple package system for GNU Emacs"])) + "Packages which are always built-in.") + +(defvar package--builtins + (delq nil + (append + package--builtins-base + (if (>= emacs-major-version 22) + ;; FIXME: emacs 22 includes tramp, rcirc, maybe + ;; other things... + '((erc . [(5 2) nil "An Emacs Internet Relay Chat client"]) + ;; The external URL is version 1.15, so make sure the + ;; built-in one looks newer. + (url . [(1 16) nil "URL handling libary"]))) + (if (>= emacs-major-version 23) + '(;; Strangely, nxml-version is missing in Emacs 23. + ;; We pick the merge date as the version. + (nxml . [(20071123) nil "Major mode for editing XML documents."]) + (bubbles . [(0 5) nil "Puzzle game for Emacs."]))))) + "Alist of all built-in packages. +Maps the package name to a vector [VERSION REQS DOCSTRING].") + +(defvar package-alist package--builtins + "Alist of all packages available for activation. +Maps the package name to a vector [VERSION REQS DOCSTRING].") + +(defvar package-activated-list + (mapcar #'car package-alist) + "List of the names of all activated packages.") + +(defvar package-obsolete-alist nil + "Representation of obsolete packages. +Like `package-alist', but maps package name to a second alist. +The inner alist is keyed by version.") + +(defun package-version-join (l) + "Turn a list of version numbers into a version string." + (mapconcat 'int-to-string l ".")) + +(defun package--version-first-nonzero (l) + (while (and l (= (car l) 0)) + (setq l (cdr l))) + (if l (car l) 0)) + +(defun package-version-compare (v1 v2 fun) + "Compare two version lists according to FUN. +FUN can be <, <=, =, >, >=, or /=." + (while (and v1 v2 (= (car v1) (car v2))) + (setq v1 (cdr v1) + v2 (cdr v2))) + (if v1 + (if v2 + ;; Both not null; we know the cars are not =. + (funcall fun (car v1) (car v2)) + ;; V1 not null, V2 null. + (funcall fun (package--version-first-nonzero v1) 0)) + (if v2 + ;; V1 null, V2 not null. + (funcall fun 0 (package--version-first-nonzero v2)) + ;; Both null. + (funcall fun 0 0)))) + +(defun package--test-version-compare () + "Test suite for `package-version-compare'." + (unless (and (package-version-compare '(0) '(0) '=) + (not (package-version-compare '(1) '(0) '=)) + (package-version-compare '(1 0 1) '(1) '>=) + (package-version-compare '(1 0 1) '(1) '>) + (not (package-version-compare '(0 9 1) '(1 0 2) '>=))) + (error "Failed")) + t) + +(defun package-strip-version (dirname) + "Strip the version from a combined package name and version. +E.g., if given \"quux-23.0\", will return \"quux\"" + (if (string-match "^\\(.*\\)-[0-9]+\\([.][0-9]+\\)*$" dirname) + (match-string 1 dirname))) + +(defun package-load-descriptor (dir package) + "Load the description file for a package. +Return nil if the package could not be found." + (let ((pkg-dir (concat (file-name-as-directory dir) package "/"))) + (if (file-directory-p pkg-dir) + (load (concat pkg-dir (package-strip-version package) "-pkg") nil t)))) + +(defun package-load-all-descriptors () + "Load descriptors of all packages. +Uses `package-directory-list' to find packages." + (mapc (lambda (dir) + (if (file-directory-p dir) + (mapc (lambda (name) + (package-load-descriptor dir name)) + (directory-files dir nil "^[^.]")))) + package-directory-list)) + +(defsubst package-desc-vers (desc) + "Extract version from a package description vector." + (aref desc 0)) + +(defsubst package-desc-reqs (desc) + "Extract requirements from a package description vector." + (aref desc 1)) + +(defsubst package-desc-doc (desc) + "Extract doc string from a package description vector." + (aref desc 2)) + +(defsubst package-desc-kind (desc) + "Extract the kind of download from an archive package description vector." + (aref desc 3)) + +(defun package-do-activate (package pkg-vec) + (let* ((pkg-name (symbol-name package)) + (pkg-ver-str (package-version-join (package-desc-vers pkg-vec))) + (dir-list package-directory-list) + (pkg-dir)) + (while dir-list + (let ((subdir (concat (car dir-list) pkg-name "-" pkg-ver-str "/"))) + (if (file-directory-p subdir) + (progn + (setq pkg-dir subdir) + (setq dir-list nil)) + (setq dir-list (cdr dir-list))))) + (unless pkg-dir + (error "Internal error: could not find directory for %s-%s" + pkg-name pkg-ver-str)) + (if (file-exists-p (concat pkg-dir "dir")) + (progn + ;; FIXME: not the friendliest, but simple. + (require 'info) + (info-initialize) + (setq Info-directory-list (cons pkg-dir Info-directory-list)))) + (setq load-path (cons pkg-dir load-path)) + ;; Load the autoloads and activate the package. + (load (concat pkg-dir (symbol-name package) "-autoloads") + nil t) + (setq package-activated-list (cons package package-activated-list)) + ;; Don't return nil. + t)) + +(defun package--built-in (package version) + "Return true if the package is built-in to Emacs." + (let ((elt (assq package package--builtins))) + (and elt + (package-version-compare (package-desc-vers (cdr elt)) version '=)))) + +;; FIXME: return a reason instead? +(defun package-activate (package version) + "Try to activate a package. +Return nil if the package could not be activated. +Recursively activates all dependencies of the named package." + ;; Assume the user knows what he is doing -- go ahead and activate a + ;; newer version of a package if an older one has already been + ;; activated. This is not ideal; we'd at least need to check to see + ;; if the package has actually been loaded, and not merely + ;; activated. However, don't try to activate 'emacs', as that makes + ;; no sense. + (unless (eq package 'emacs) + (let* ((pkg-desc (assq package package-alist)) + (this-version (package-desc-vers (cdr pkg-desc))) + (req-list (package-desc-reqs (cdr pkg-desc))) + ;; If the package was never activated, we want to do it + ;; now. + (keep-going (or (not (memq package package-activated-list)) + (package-version-compare this-version version '>)))) + (while (and req-list keep-going) + (or (package-activate (car (car req-list)) + (car (cdr (car req-list)))) + (setq keep-going nil)) + (setq req-list (cdr req-list))) + (if keep-going + (package-do-activate package (cdr pkg-desc)) + ;; We get here if a dependency failed to activate -- but we + ;; can also get here if the requested package was already + ;; activated. Return non-nil in the latter case. + (and (memq package package-activated-list) + (package-version-compare this-version version '>=)))))) + +(defun package-mark-obsolete (package pkg-vec) + "Put package on the obsolete list, if not already there." + (let ((elt (assq package package-obsolete-alist))) + (if elt + ;; If this obsolete version does not exist in the list, update + ;; it the list. + (unless (assoc (package-desc-vers pkg-vec) (cdr elt)) + (setcdr elt (cons (cons (package-desc-vers pkg-vec) pkg-vec) + (cdr elt)))) + ;; Make a new association. + (setq package-obsolete-alist + (cons (cons package (list (cons (package-desc-vers pkg-vec) + pkg-vec))) + package-obsolete-alist))))) + +;; (define-package "emacs" "21.4.1" "GNU Emacs core package.") +;; (define-package "erc" "5.1" "ERC - irc client" '((emacs "21.0"))) +(defun define-package (name-str version-string + &optional docstring requirements) + "Define a new package. +NAME is the name of the package, a string. +VERSION-STRING is the version of the package, a dotted sequence +of integers. +DOCSTRING is the optional description. +REQUIREMENTS is a list of requirements on other packages. +Each requirement is of the form (OTHER-PACKAGE \"VERSION\")." + (let* ((name (intern name-str)) + (pkg-desc (assq name package-alist)) + (new-version (package-version-split version-string)) + (new-pkg-desc + (cons name + (vector new-version + (mapcar + (lambda (elt) + (list (car elt) + (package-version-split (car (cdr elt))))) + requirements) + docstring)))) + ;; Only redefine a package if the redefinition is newer. + (if (or (not pkg-desc) + (package-version-compare new-version + (package-desc-vers (cdr pkg-desc)) + '>)) + (progn + (when pkg-desc + ;; Remove old package and declare it obsolete. + (setq package-alist (delq pkg-desc package-alist)) + (package-mark-obsolete (car pkg-desc) (cdr pkg-desc))) + ;; Add package to the alist. + (setq package-alist (cons new-pkg-desc package-alist))) + ;; You can have two packages with the same version, for instance + ;; one in the system package directory and one in your private + ;; directory. We just let the first one win. + (unless (package-version-compare new-version + (package-desc-vers (cdr pkg-desc)) + '=) + ;; The package is born obsolete. + (package-mark-obsolete (car new-pkg-desc) (cdr new-pkg-desc)))))) + +;; From Emacs 22. +(defun package-autoload-ensure-default-file (file) + "Make sure that the autoload file FILE exists and if not create it." + (unless (file-exists-p file) + (write-region + (concat ";;; " (file-name-nondirectory file) + " --- automatically extracted autoloads\n" + ";;\n" + ";;; Code:\n\n" + " \n;; Local Variables:\n" + ";; version-control: never\n" + ";; no-byte-compile: t\n" + ";; no-update-autoloads: t\n" + ";; End:\n" + ";;; " (file-name-nondirectory file) + " ends here\n") + nil file)) + file) + +(defun package-generate-autoloads (name pkg-dir) + (let* ((auto-name (concat name "-autoloads.el")) + (ignore-name (concat name "-pkg.el")) + (generated-autoload-file (concat pkg-dir auto-name)) + (version-control 'never)) + ;; In Emacs 22 'update-autoloads-from-directories' does not seem + ;; to be autoloaded... + (require 'autoload) + (unless (fboundp 'autoload-ensure-default-file) + (package-autoload-ensure-default-file generated-autoload-file)) + (update-autoloads-from-directories pkg-dir))) + +(defun package-untar-buffer () + "Untar the current buffer. +This uses `tar-untar-buffer' if it is available. +Otherwise it uses an external `tar' program. +`default-directory' should be set by the caller." + (require 'tar-mode) + (if (fboundp 'tar-untar-buffer) + (progn + ;; tar-mode messes with narrowing, so we just let it have the + ;; whole buffer to play with. + (delete-region (point-min) (point)) + (tar-mode) + (tar-untar-buffer)) + ;; FIXME: check the result. + (call-process-region (point) (point-max) "tar" nil '(nil nil) nil + "xf" "-"))) + +(defun package-unpack (name version) + (let ((pkg-dir (concat (file-name-as-directory package-user-dir) + (symbol-name name) "-" version "/"))) + ;; Be careful!! + (make-directory package-user-dir t) + (if (file-directory-p pkg-dir) + (mapc (lambda (file) nil) ; 'delete-file -- FIXME: when we're + ; more confident + (directory-files pkg-dir t "^[^.]"))) + (let* ((default-directory (file-name-as-directory package-user-dir))) + (package-untar-buffer) + (package-generate-autoloads (symbol-name name) pkg-dir) + (let ((load-path (cons pkg-dir load-path))) + (byte-recompile-directory pkg-dir 0 t))))) + +(defun package-unpack-single (file-name version desc requires) + "Install the contents of the current buffer as a package." + (let* ((dir (file-name-as-directory package-user-dir))) + ;; Special case "package". + (if (string= file-name "package") + (write-region (point-min) (point-max) (concat dir file-name ".el") + nil nil nil nil) + (let ((pkg-dir (file-name-as-directory + (concat dir file-name "-" version)))) + (make-directory pkg-dir t) + (write-region (point-min) (point-max) + (concat pkg-dir file-name ".el") + nil nil nil 'excl) + (let ((print-level nil) + (print-length nil)) + (write-region + (concat + (prin1-to-string + (list 'define-package + file-name + version + desc + (list 'quote + ;; Turn version lists into string form. + (mapcar + (lambda (elt) + (list (car elt) + (package-version-join (car (cdr elt))))) + requires)))) + "\n") + nil + (concat pkg-dir file-name "-pkg.el") + nil nil nil 'excl)) + (package-generate-autoloads file-name pkg-dir) + (let ((load-path (cons pkg-dir load-path))) + (byte-recompile-directory pkg-dir 0 t)))))) + +(defun package-handle-response () + "Handle the response from the server. +Parse the HTTP response and throw if an error occurred. +The url package seems to require extra processing for this. +This should be called in a `save-excursion', in the download buffer. +It will move point to somewhere in the headers." + ;; We assume HTTP here. + (let ((response (url-http-parse-response))) + (when (or (< response 200) (>= response 300)) + (display-buffer (current-buffer)) + (error "Error during download request:%s" + (buffer-substring-no-properties (point) (progn + (end-of-line) + (point))))))) + +(defun package-download-single (name version desc requires) + "Download and install a single-file package." + (let ((buffer (url-retrieve-synchronously + (concat package-archive-base + (symbol-name name) "-" version ".el")))) + (save-excursion + (set-buffer buffer) + (package-handle-response) + (re-search-forward "^$" nil 'move) + (forward-char) + (delete-region (point-min) (point)) + (package-unpack-single (symbol-name name) version desc requires) + (kill-buffer buffer)))) + +(defun package-download-tar (name version) + "Download and install a tar package." + (let ((tar-buffer (url-retrieve-synchronously + (concat package-archive-base + (symbol-name name) "-" version ".tar")))) + (save-excursion + (set-buffer tar-buffer) + (package-handle-response) + (re-search-forward "^$" nil 'move) + (forward-char) + (package-unpack name version) + (kill-buffer tar-buffer)))) + +(defun package-installed-p (package version) + (let ((pkg-desc (assq package package-alist))) + (and pkg-desc + (package-version-compare version + (package-desc-vers (cdr pkg-desc)) + '>=)))) + +(defun package-compute-transaction (result requirements) + (while requirements + (let* ((elt (car requirements)) + (next-pkg (car elt)) + (next-version (car (cdr elt)))) + (unless (package-installed-p next-pkg next-version) + (let ((pkg-desc (assq next-pkg package-archive-contents))) + (unless pkg-desc + (error "Package '%s' not available for installation" + (symbol-name next-pkg))) + (unless (package-version-compare (package-desc-vers (cdr pkg-desc)) + next-version + '>=) + (error + "Need package '%s' with version %s, but only %s is available" + (symbol-name next-pkg) (package-version-join next-version) + (package-version-join (package-desc-vers (cdr pkg-desc))))) + ;; Only add to the transaction if we don't already have it. + (unless (memq next-pkg result) + (setq result (cons next-pkg result))) + (setq result + (package-compute-transaction result + (package-desc-reqs + (cdr pkg-desc))))))) + (setq requirements (cdr requirements))) + result) + +(defun package-read-from-string (str) + "Read a Lisp expression from STR. +Signal an error if the entire string was not used." + (let* ((read-data (read-from-string str)) + (more-left + (condition-case nil + ;; The call to `ignore' suppresses a compiler warning. + (progn (ignore (read-from-string + (substring str (cdr read-data)))) + t) + (end-of-file nil)))) + (if more-left + (error "Can't read whole string") + (car read-data)))) + +(defun package--read-archive-file (file) + "Re-read archive file FILE, if it exists. +Will return the data from the file, or nil if the file does not exist. +Will throw an error if the archive version is too new." + (let ((filename (concat (file-name-as-directory package-user-dir) + file))) + (if (file-exists-p filename) + (with-temp-buffer + (insert-file-contents-literally filename) + (let ((contents (package-read-from-string + (buffer-substring-no-properties (point-min) + (point-max))))) + (if (> (car contents) package-archive-version) + (error "Package archive version %d is greater than %d - upgrade package.el" + (car contents) package-archive-version)) + (cdr contents)))))) + +(defun package-read-archive-contents () + "Re-read `archive-contents' and `builtin-packages', if they exist. +Will set `package-archive-contents' and `package--builtins' if successful. +Will throw an error if the archive version is too new." + (let ((archive-contents (package--read-archive-file "archive-contents")) + (builtins (package--read-archive-file "builtin-packages"))) + (if archive-contents + ;; Version 1 of 'archive-contents' is identical to our + ;; internal representation. + (setq package-archive-contents archive-contents)) + (if builtins + ;; Version 1 of 'builtin-packages' is a list where the car is + ;; a split emacs version and the cdr is an alist suitable for + ;; package--builtins. + (let ((our-version (package-version-split emacs-version)) + (result package--builtins-base)) + (setq package--builtins + (dolist (elt builtins result) + (if (package-version-compare our-version (car elt) '>=) + (setq result (append (cdr elt) result))))))))) + +(defun package-download-transaction (transaction) + "Download and install all the packages in the given transaction." + (mapc (lambda (elt) + (let* ((desc (cdr (assq elt package-archive-contents))) + (v-string (package-version-join (package-desc-vers desc))) + (kind (package-desc-kind desc))) + (cond + ((eq kind 'tar) + (package-download-tar elt v-string)) + ((eq kind 'single) + (package-download-single elt v-string + (package-desc-doc desc) + (package-desc-reqs desc))) + (t + (error "Unknown package kind: " (symbol-name kind)))))) + transaction)) + +(defun package-install (name) + "Install the package named NAME. +Interactively, prompts for the package name. +The package is found on the archive site, see `package-archive-base'." + (interactive + (list (progn + ;; Make sure we're using the most recent download of the + ;; archive. Maybe we should be updating the archive first? + (package-read-archive-contents) + (intern (completing-read "Install package: " + (mapcar (lambda (elt) + (cons (symbol-name (car elt)) + nil)) + package-archive-contents) + nil t))))) + (let ((pkg-desc (assq name package-archive-contents))) + (unless pkg-desc + (error "Package '%s' not available for installation" + (symbol-name name))) + (let ((transaction + (package-compute-transaction (list name) + (package-desc-reqs (cdr pkg-desc))))) + (package-download-transaction transaction))) + ;; Try to activate it. + (package-initialize)) + +(defun package-strip-rcs-id (v-str) + "Strip RCS version ID from the version string. +If the result looks like a dotted numeric version, return it. +Otherwise return nil." + (if v-str + (if (string-match "^[ \t]*[$]Revision:[ \t]\([0-9.]+\)[ \t]*[$]$" v-str) + (match-string 1 v-str) + (if (string-match "^[0-9.]*$" v-str) + v-str)))) + +(defun package-buffer-info () + "Return a vector of information about the package in the current buffer. +The vector looks like [FILENAME REQUIRES DESCRIPTION VERSION COMMENTARY] +FILENAME is the file name, a string. It does not have the \".el\" extension. +REQUIRES is a requires list, or nil. +DESCRIPTION is the package description (a string). +VERSION is the version, a string. +COMMENTARY is the commentary section, a string, or nil if none. +Throws an exception if the buffer does not contain a conforming package. +If there is a package, narrows the buffer to the file's boundaries. +May narrow buffer or move point even on failure." + (goto-char (point-min)) + (if (re-search-forward "^;;; \\([^ ]*\\)\\.el --- \\(.*\\)$" nil t) + (let ((file-name (match-string 1)) + (desc (match-string 2)) + (start (progn (beginning-of-line) (point)))) + (if (search-forward (concat ";;; " file-name ".el ends here")) + (progn + ;; Try to include a trailing newline. + (forward-line) + (narrow-to-region start (point)) + (require 'lisp-mnt) + ;; Use some headers we've invented to drive the process. + (let* ((requires-str (lm-header "package-requires")) + (requires (if requires-str + (package-read-from-string requires-str))) + ;; Prefer Package-Version, because if it is + ;; defined the package author probably wants us + ;; to use it. Otherwise try Version. + (pkg-version + (or (package-strip-rcs-id (lm-header "package-version")) + (package-strip-rcs-id (lm-header "version")))) + (commentary (lm-commentary))) + (unless pkg-version + (error + "Package does not define a usable \"Version\" or \"Package-Version\" header")) + ;; Turn string version numbers into list form. + (setq requires + (mapcar + (lambda (elt) + (list (car elt) + (package-version-split (car (cdr elt))))) + requires)) + (set-text-properties 0 (length file-name) nil file-name) + (set-text-properties 0 (length pkg-version) nil pkg-version) + (set-text-properties 0 (length desc) nil desc) + (vector file-name requires desc pkg-version commentary))) + (error "Package missing a terminating comment"))) + (error "No starting comment for package"))) + +(defun package-tar-file-info (file) + "Find package information for a tar file. +FILE is the name of the tar file to examine. +The return result is a vector like `package-buffer-info'." + (unless (string-match "^\\(.+\\)-\\([0-9.]+\\)\\.tar$" file) + (error "`%s' doesn't have a package-ish name" file)) + (let* ((pkg-name (file-name-nondirectory (match-string-no-properties 1 file))) + (pkg-version (match-string-no-properties 2 file)) + ;; Extract the package descriptor. + (pkg-def-contents (shell-command-to-string + ;; Requires GNU tar. + (concat "tar -xOf " file " " + pkg-name "-" pkg-version "/" + pkg-name "-pkg.el"))) + (pkg-def-parsed (package-read-from-string pkg-def-contents))) + (unless (eq (car pkg-def-parsed) 'define-package) + (error "%s-pkg.el doesn't contain `define-package' sexp" pkg-name)) + (let ((name-str (nth 1 pkg-def-parsed)) + (version-string (nth 2 pkg-def-parsed)) + (docstring (nth 3 pkg-def-parsed)) + (requires (nth 4 pkg-def-parsed)) + + (readme (shell-command-to-string + ;; Requires GNU tar. + (concat "tar -xOf " file " " + pkg-name "-" pkg-version "/README")))) + (unless (equal pkg-version version-string) + (error "Inconsistent versions!")) + (unless (equal pkg-name name-str) + (error "Inconsistent names!")) + ;; Kind of a hack. + (if (string-match ": Not found in archive" readme) + (setq readme nil)) + ;; Turn string version numbers into list form. + (if (eq (car requires) 'quote) + (setq requires (car (cdr requires)))) + (setq requires + (mapcar + (lambda (elt) + (list (car elt) + (package-version-split (car (cdr elt))))) + requires)) + (vector pkg-name requires docstring version-string readme)))) + +(defun package-install-buffer-internal (pkg-info type) + (save-excursion + (save-restriction + (let* ((file-name (aref pkg-info 0)) + (requires (aref pkg-info 1)) + (desc (if (string= (aref pkg-info 2) "") + "No description available." + (aref pkg-info 2))) + (pkg-version (aref pkg-info 3))) + ;; Download and install the dependencies. + (let ((transaction (package-compute-transaction nil requires))) + (package-download-transaction transaction)) + ;; Install the package itself. + (cond + ((eq type 'single) + (package-unpack-single file-name pkg-version desc requires)) + ((eq type 'tar) + (package-unpack (intern file-name) pkg-version)) + (t + (error "Unknown type: %s" (symbol-name type)))) + ;; Try to activate it. + (package-initialize))))) + +(defun package-install-from-buffer () + "Install a package from the current buffer. +The package is assumed to be a single .el file which +follows the elisp comment guidelines; see +info node `(elisp)Library Headers'." + (interactive) + (package-install-buffer-internal (package-buffer-info) 'single)) + +(defun package-install-file (file) + "Install a package from a file. +The file can either be a tar file or an Emacs Lisp file." + (interactive "fPackage file name: ") + (with-temp-buffer + (insert-file-contents-literally file) + (cond + ((string-match "\\.el$" file) (package-install-from-buffer)) + ((string-match "\\.tar$" file) + (package-install-buffer-internal (package-tar-file-info file) 'tar)) + (t (error "Unrecognized extension `%s'" (file-name-extension file)))))) + +(defun package-delete (name version) + (require 'dired) ; for dired-delete-file + (dired-delete-file (concat (file-name-as-directory package-user-dir) + name "-" version) + ;; FIXME: query user? + 'always)) + +(defun package--encode (string) + "Encode a string by replacing some characters with XML entities." + ;; We need a special case for translating "&" to "&". + (let ((index)) + (while (setq index (string-match "[&]" string index)) + (setq string (replace-match "&" t nil string)) + (setq index (1+ index)))) + (while (string-match "[<]" string) + (setq string (replace-match "<" t nil string))) + (while (string-match "[>]" string) + (setq string (replace-match ">" t nil string))) + (while (string-match "[']" string) + (setq string (replace-match "'" t nil string))) + (while (string-match "[\"]" string) + (setq string (replace-match """ t nil string))) + string) + +(defun package--make-rss-entry (title text) + (let ((date-string (format-time-string "%a, %d %B %Y %T %z"))) + (concat "\n" + "" (package--encode title) "\n" + ;; FIXME: should have a link in the web page. + "" package-archive-base "news.html\n" + "" (package--encode text) "\n" + "" date-string "\n" + "\n"))) + +(defun package--make-html-entry (title text) + (concat "
  • " (format-time-string "%B %e") " - " + title " - " (package--encode text) + "
  • \n")) + +(defun package--update-file (file location text) + (save-excursion + (let ((old-buffer (find-buffer-visiting file))) + (with-current-buffer (let ((find-file-visit-truename t)) + (or old-buffer (find-file-noselect file))) + (goto-char (point-min)) + (search-forward location) + (forward-line) + (insert text) + (let ((file-precious-flag t)) + (save-buffer)) + (unless old-buffer + (kill-buffer (current-buffer))))))) + +(defun package-maint-add-news-item (title description) + "Add a news item to the ELPA web pages. +TITLE is the title of the news item. +DESCRIPTION is the text of the news item. +You need administrative access to ELPA to use this." + (interactive "sTitle: \nsText: ") + (package--update-file (concat package-archive-upload-base "elpa.rss") + "" + (package--make-rss-entry title description)) + (package--update-file (concat package-archive-upload-base "news.html") + "New entries go here" + (package--make-html-entry title description))) + +(defun package--update-news (package version description) + "Update the ELPA web pages when a package is uploaded." + (package-maint-add-news-item (concat package " version " version) + description)) + +(defun package-upload-buffer-internal (pkg-info extension) + "Upload a package whose contents are in the current buffer. +PKG-INFO is the package info, see `package-buffer-info'. +EXTENSION is the file extension, a string. It can be either +\"el\" or \"tar\"." + (save-excursion + (save-restriction + (let* ((file-type (cond + ((equal extension "el") 'single) + ((equal extension "tar") 'tar) + (t (error "Unknown extension `%s'" extension)))) + (file-name (aref pkg-info 0)) + (pkg-name (intern file-name)) + (requires (aref pkg-info 1)) + (desc (if (string= (aref pkg-info 2) "") + (read-string "Description of package: ") + (aref pkg-info 2))) + (pkg-version (aref pkg-info 3)) + (commentary (aref pkg-info 4)) + (split-version (package-version-split pkg-version)) + (pkg-buffer (current-buffer)) + + ;; Download latest archive-contents. + (buffer (url-retrieve-synchronously + (concat package-archive-base "archive-contents")))) + + ;; Parse archive-contents. + (set-buffer buffer) + (package-handle-response) + (re-search-forward "^$" nil 'move) + (forward-char) + (delete-region (point-min) (point)) + (let ((contents (package-read-from-string + (buffer-substring-no-properties (point-min) + (point-max)))) + (new-desc (vector split-version requires desc file-type))) + (if (> (car contents) package-archive-version) + (error "Unrecognized archive version %d" (car contents))) + (let ((elt (assq pkg-name (cdr contents)))) + (if elt + (if (package-version-compare split-version + (package-desc-vers (cdr elt)) + '<=) + (error "New package has smaller version: %s" pkg-version) + (setcdr elt new-desc)) + (setq contents (cons (car contents) + (cons (cons pkg-name new-desc) + (cdr contents)))))) + + ;; Now CONTENTS is the updated archive contents. Upload + ;; this and the package itself. For now we assume ELPA is + ;; writable via file primitives. + (let ((print-level nil) + (print-length nil)) + (write-region (concat (pp-to-string contents) "\n") + nil + (concat package-archive-upload-base + "archive-contents"))) + + ;; If there is a commentary section, write it. + (when commentary + (write-region commentary nil + (concat package-archive-upload-base + (symbol-name pkg-name) "-readme.txt"))) + + (set-buffer pkg-buffer) + (kill-buffer buffer) + (write-region (point-min) (point-max) + (concat package-archive-upload-base + file-name "-" pkg-version + "." extension) + nil nil nil 'excl) + + ;; Write a news entry. + (package--update-news (concat file-name "." extension) + pkg-version desc) + + ;; special-case "package": write a second copy so that the + ;; installer can easily find the latest version. + (if (string= file-name "package") + (write-region (point-min) (point-max) + (concat package-archive-upload-base + file-name "." extension) + nil nil nil 'ask))))))) + +(defun package-upload-buffer () + "Upload a single .el file to ELPA from the current buffer." + (interactive) + (save-excursion + (save-restriction + ;; Find the package in this buffer. + (let ((pkg-info (package-buffer-info))) + (package-upload-buffer-internal pkg-info "el"))))) + +(defun package-upload-file (file) + (interactive "fPackage file name: ") + (with-temp-buffer + (insert-file-contents-literally file) + (let ((info (cond + ((string-match "\\.tar$" file) (package-tar-file-info file)) + ((string-match "\\.el$" file) (package-buffer-info)) + (t (error "Unrecognized extension `%s'" + (file-name-extension file)))))) + (package-upload-buffer-internal info (file-name-extension file))))) + +(defun package-gnus-summary-upload () + "Upload a package contained in the current *Article* buffer. +This should be invoked from the gnus *Summary* buffer." + (interactive) + (save-excursion + (set-buffer gnus-article-buffer) + (package-upload-buffer))) + +(defun package--download-one-archive (file) + "Download a single archive file and cache it locally." + (let ((buffer (url-retrieve-synchronously + (concat package-archive-base file)))) + (save-excursion + (set-buffer buffer) + (package-handle-response) + (re-search-forward "^$" nil 'move) + (forward-char) + (delete-region (point-min) (point)) + (setq buffer-file-name (concat (file-name-as-directory package-user-dir) + file)) + (let ((version-control 'never)) + (save-buffer)) + (kill-buffer buffer)))) + +(defun package-refresh-contents () + "Download the ELPA archive description if needed. +Invoking this will ensure that Emacs knows about the latest versions +of all packages. This will let Emacs make them available for +download." + (interactive) + (package--download-one-archive "archive-contents") + (package--download-one-archive "builtin-packages") + (package-read-archive-contents)) + +(defun package-initialize () + "Load all packages and activate as many as possible." + (setq package-obsolete-alist nil) + (package-load-all-descriptors) + (package-read-archive-contents) + ;; Try to activate all our packages. + (mapc (lambda (elt) + (package-activate (car elt) (package-desc-vers (cdr elt)))) + package-alist)) + + + +;;;; Package menu mode. + +(defvar package-menu-mode-map nil + "Local keymap for `package-menu-mode' buffers.") + +(unless package-menu-mode-map + (setq package-menu-mode-map (make-keymap)) + (suppress-keymap package-menu-mode-map) + (define-key package-menu-mode-map "q" 'quit-window) + (define-key package-menu-mode-map "n" 'next-line) + (define-key package-menu-mode-map "p" 'previous-line) + (define-key package-menu-mode-map "u" 'package-menu-mark-unmark) + (define-key package-menu-mode-map "\177" 'package-menu-backup-unmark) + (define-key package-menu-mode-map "d" 'package-menu-mark-delete) + (define-key package-menu-mode-map "i" 'package-menu-mark-install) + (define-key package-menu-mode-map "g" 'package-menu-revert) + (define-key package-menu-mode-map "r" 'package-menu-refresh) + (define-key package-menu-mode-map "~" + 'package-menu-mark-obsolete-for-deletion) + (define-key package-menu-mode-map "x" 'package-menu-execute) + (define-key package-menu-mode-map "h" 'package-menu-quick-help) + (define-key package-menu-mode-map "?" 'package-menu-view-commentary) + ) + +(defvar package-menu-sort-button-map + (let ((map (make-sparse-keymap))) + (define-key map [header-line mouse-1] 'package-menu-sort-by-column) + (define-key map [follow-link] 'mouse-face) + map) + "Local keymap for package menu sort buttons.") + +(put 'package-menu-mode 'mode-class 'special) + +(defun package-menu-mode () + "Major mode for browsing a list of packages. +Letters do not insert themselves; instead, they are commands. +\\ +\\{package-menu-mode-map}" + (kill-all-local-variables) + (use-local-map package-menu-mode-map) + (setq major-mode 'package-menu-mode) + (setq mode-name "Package Menu") + (setq truncate-lines t) + (setq buffer-read-only t) + ;; Support Emacs 21. + (if (fboundp 'run-mode-hooks) + (run-mode-hooks 'package-menu-mode-hook) + (run-hooks 'package-menu-mode-hook))) + +(defun package-menu-refresh () + "Download the ELPA archive. +This fetches the file describing the current contents of +the Emacs Lisp Package Archive, and then refreshes the +package menu. This lets you see what new packages are +available for download." + (interactive) + (package-refresh-contents) + (package-list-packages-internal)) + +(defun package-menu-revert () + "Update the list of packages." + (interactive) + (package-list-packages-internal)) + +(defun package-menu-mark-internal (what) + (unless (eobp) + (let ((buffer-read-only nil)) + (beginning-of-line) + (delete-char 1) + (insert what) + (forward-line)))) + +;; fixme numeric argument +(defun package-menu-mark-delete (num) + "Mark a package for deletion and move to the next line." + (interactive "p") + (package-menu-mark-internal "D")) + +(defun package-menu-mark-install (num) + "Mark a package for installation and move to the next line." + (interactive "p") + (package-menu-mark-internal "I")) + +(defun package-menu-mark-unmark (num) + "Clear any marks on a package and move to the next line." + (interactive "p") + (package-menu-mark-internal " ")) + +(defun package-menu-backup-unmark () + "Back up one line and clear any marks on that package." + (interactive) + (forward-line -1) + (package-menu-mark-internal " ") + (forward-line -1)) + +(defun package-menu-mark-obsolete-for-deletion () + "Mark all obsolete packages for deletion." + (interactive) + (save-excursion + (goto-char (point-min)) + (forward-line 2) + (while (not (eobp)) + (if (looking-at ".*\\s obsolete\\s ") + (package-menu-mark-internal "D") + (forward-line 1))))) + +(defun package-menu-quick-help () + "Show short key binding help for package-menu-mode." + (interactive) + (message "n-ext, i-nstall, d-elete, u-nmark, x-ecute, r-efresh, h-elp")) + +(defun package-menu-view-commentary () + "Display information about this package. +For single-file packages, shows the commentary section from the header. +For larger packages, shows the README file." + (interactive) + (let* (start-point ok + (pkg-name (package-menu-get-package)) + (buffer (url-retrieve-synchronously (concat package-archive-base + pkg-name + "-readme.txt")))) + (with-current-buffer buffer + ;; FIXME: it would be nice to work with any URL type. + (setq start-point url-http-end-of-headers) + (setq ok (eq (url-http-parse-response) 200))) + (let ((new-buffer (get-buffer-create "*Package Info*"))) + (with-current-buffer new-buffer + (let ((buffer-read-only nil)) + (erase-buffer) + (insert "Package information for " pkg-name "\n\n") + (if ok + (insert-buffer-substring buffer start-point) + (insert "This package does not have a README file or commentary comment.\n")) + (goto-char (point-min)) + (view-mode))) + (display-buffer new-buffer t)))) + +;; Return the name of the package on the current line. +(defun package-menu-get-package () + (save-excursion + (beginning-of-line) + (if (looking-at ". \\([^ \t]*\\)") + (match-string 1)))) + +;; Return the version of the package on the current line. +(defun package-menu-get-version () + (save-excursion + (beginning-of-line) + (if (looking-at ". [^ \t]*[ \t]*\\([0-9.]*\\)") + (match-string 1)))) + +(defun package-menu-get-status () + (save-excursion + (if (looking-at ". [^ \t]*[ \t]*[^ \t]*[ \t]*\\([^ \t]*\\)") + (match-string 1) + ""))) + +(defun package-menu-execute () + "Perform all the marked actions. +Packages marked for installation will be downloaded and +installed. Packages marked for deletion will be removed. +Note that after installing packages you will want to restart +Emacs." + (interactive) + (goto-char (point-min)) + (forward-line 2) + (while (not (eobp)) + (let ((cmd (char-after)) + (pkg-name (package-menu-get-package)) + (pkg-vers (package-menu-get-version)) + (pkg-status (package-menu-get-status))) + (cond + ((eq cmd ?D) + (when (and (string= pkg-status "installed") + (string= pkg-name "package")) + ;; FIXME: actually, we could be tricky and remove all info. + ;; But that is drastic and the user can do that instead. + (error "Can't delete most recent version of `package'")) + ;; Ask for confirmation here? Maybe if package status is ""? + ;; Or if any lisp from package is actually loaded? + (message "Deleting %s-%s..." pkg-name pkg-vers) + (package-delete pkg-name pkg-vers) + (message "Deleting %s-%s... done" pkg-name pkg-vers)) + ((eq cmd ?I) + (package-install (intern pkg-name))))) + (forward-line)) + (package-menu-revert)) + +(defun package-print-package (package version key desc) + (let ((face + (cond ((eq package 'emacs) 'font-lock-builtin-face) + ((string= key "available") 'default) + ((string= key "installed") 'font-lock-comment-face) + (t ; obsolete, but also the default. + ; is warning ok? + 'font-lock-warning-face)))) + (insert (propertize " " 'font-lock-face face)) + (insert (propertize (symbol-name package) 'font-lock-face face)) + (indent-to 20 1) + (insert (propertize (package-version-join version) 'font-lock-face face)) + (indent-to 30 1) + (insert (propertize key 'font-lock-face face)) + ;; FIXME: this 'when' is bogus... + (when desc + (indent-to 41 1) + (insert (propertize desc 'font-lock-face face))) + (insert "\n"))) + +(defun package-list-maybe-add (package version status description result) + (let ((elt (assoc (cons package version) result))) + (unless elt + (setq result (cons (list (cons package version) status description) + result)))) + result) + +;; This decides how we should sort; nil means by package name. +(defvar package-menu-sort-key nil) + +(defun package-list-packages-internal () + (package-initialize) ; FIXME: do this here? + (with-current-buffer (get-buffer-create "*Packages*") + (setq buffer-read-only nil) + (erase-buffer) + (let ((info-list)) + (mapc (lambda (elt) + (setq info-list + (package-list-maybe-add (car elt) + (package-desc-vers (cdr elt)) + ;; FIXME: it turns out to + ;; be tricky to see if + ;; this package is + ;; presently activated. + ;; That is lame! + "installed" + (package-desc-doc (cdr elt)) + info-list))) + package-alist) + (mapc (lambda (elt) + (setq info-list + (package-list-maybe-add (car elt) + (package-desc-vers (cdr elt)) + "available" + (package-desc-doc (cdr elt)) + info-list))) + package-archive-contents) + (mapc (lambda (elt) + (mapc (lambda (inner-elt) + (setq info-list + (package-list-maybe-add (car elt) + (package-desc-vers + (cdr inner-elt)) + "obsolete" + (package-desc-doc + (cdr inner-elt)) + info-list))) + (cdr elt))) + package-obsolete-alist) + (let ((selector (cond + ((string= package-menu-sort-key "Version") + ;; FIXME this doesn't work. + #'(lambda (e) (cdr (car e)))) + ((string= package-menu-sort-key "Status") + #'(lambda (e) (car (cdr e)))) + ((string= package-menu-sort-key "Description") + #'(lambda (e) (car (cdr (cdr e))))) + (t ; "Package" is default. + #'(lambda (e) (symbol-name (car (car e)))))))) + (setq info-list + (sort info-list + (lambda (left right) + (let ((vleft (funcall selector left)) + (vright (funcall selector right))) + (string< vleft vright)))))) + (mapc (lambda (elt) + (package-print-package (car (car elt)) + (cdr (car elt)) + (car (cdr elt)) + (car (cdr (cdr elt))))) + info-list)) + (goto-char (point-min)) + (current-buffer))) + +(defun package-menu-sort-by-column (&optional e) + "Sort the package menu by the last column clicked on." + (interactive (list last-input-event)) + (if e (mouse-select-window e)) + (let* ((pos (event-start e)) + (obj (posn-object pos)) + (col (if obj + (get-text-property (cdr obj) 'column-name (car obj)) + (get-text-property (posn-point pos) 'column-name)))) + (setq package-menu-sort-key col)) + (package-list-packages-internal)) + +(defun package--list-packages () + "Display a list of packages. +Helper function that does all the work for the user-facing functions." + (with-current-buffer (package-list-packages-internal) + (package-menu-mode) + ;; Set up the header line. + (setq header-line-format + (mapconcat + (lambda (pair) + (let ((column (car pair)) + (name (cdr pair))) + (concat + ;; Insert a space that aligns the button properly. + (propertize " " 'display (list 'space :align-to column) + 'face 'fixed-pitch) + ;; Set up the column button. + (if (string= name "Version") + name + (propertize name + 'column-name name + 'help-echo "mouse-1: sort by column" + 'mouse-face 'highlight + 'keymap package-menu-sort-button-map))))) + ;; We take a trick from buff-menu and have a dummy leading + ;; space to align the header line with the beginning of the + ;; text. This doesn't really work properly on Emacs 21, + ;; but it is close enough. + '((0 . "") + (2 . "Package") + (20 . "Version") + (30 . "Status") + (41 . "Description")) + "")) + + ;; It's okay to use pop-to-buffer here. The package menu buffer + ;; has keybindings, and the user just typed 'M-x + ;; package-list-packages', suggesting that they might want to use + ;; them. + (pop-to-buffer (current-buffer)))) + +(defun package-list-packages () + "Display a list of packages. +Fetches the updated list of packages before displaying. +The list is displayed in a buffer named `*Packages*'." + (interactive) + (package-refresh-contents) + (package--list-packages)) + +(defun package-list-packages-no-fetch () + "Display a list of packages. +Does not fetch the updated list of packages before displaying. +The list is displayed in a buffer named `*Packages*'." + (interactive) + (package--list-packages)) + +;; Make it appear on the menu. +(define-key-after menu-bar-options-menu [package] + '(menu-item "Manage Packages" package-list-packages + :help "Install or uninstall additional Emacs packages")) + + + +(eval-when-compile + (require 'reporter)) + +(defun package-report-bug () + "Submit a bug report for package.el via email." + (interactive) + (require 'reporter) + (reporter-submit-bug-report + package-el-maintainer + (concat "package.el " package-el-version) + '(package-archive-base + package-archive-version + package-archive-contents + package-user-dir + package-directory-list + package-alist + package-activated-list + package-obsolete-alist))) + +(provide 'package) + +;;; package.el ends here diff --git a/.emacs.d/elpa/package.el~ b/.emacs.d/elpa/package.el~ new file mode 100644 index 0000000..1cecbe3 --- /dev/null +++ b/.emacs.d/elpa/package.el~ @@ -0,0 +1,1507 @@ +;;; package.el --- Simple package system for Emacs + +;; Copyright (C) 2007, 2008, 2009 Tom Tromey + +;; Author: Tom Tromey +;; Created: 10 Mar 2007 +;; Version: 0.9 +;; Keywords: tools + +;; This file is not (yet) part of GNU Emacs. +;; However, it is distributed under the same license. + +;; GNU Emacs 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 3, or (at your option) +;; any later version. + +;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Change Log: + +;; 2 Apr 2007 - now using ChangeLog file +;; 15 Mar 2007 - updated documentation +;; 14 Mar 2007 - Changed how obsolete packages are handled +;; 13 Mar 2007 - Wrote package-install-from-buffer +;; 12 Mar 2007 - Wrote package-menu mode + +;;; Commentary: + +;; To use this, put package.el somewhere on your load-path. Then add +;; this to your .emacs: +;; +;; (load "package") +;; (package-initialize) +;; +;; This will automatically make available the packages you have +;; installed using package.el. If your .emacs will refer to these +;; packages, you may want to initialize the package manager near the +;; top. +;; +;; Note that if you want to be able to automatically download and +;; install packages from ELPA (the Emacs Lisp Package Archive), then +;; you will need the 'url' package. This comes with Emacs 22; Emacs +;; 21 users will have to find it elsewhere. +;; +;; If you installed package.el via the auto-installer: +;; +;; http://tromey.com/elpa/ +;; +;; then you do not need to edit your .emacs, as the installer will +;; have done this for you. The installer will also install the url +;; package if you need it. + +;; Other external functions you may want to use: +;; +;; M-x package-list-packages +;; Enters a mode similar to buffer-menu which lets you manage +;; packages. You can choose packages for install (mark with "i", +;; then "x" to execute) or deletion (not implemented yet), and you +;; can see what packages are available. This will automatically +;; fetch the latest list of packages from ELPA. +;; +;; M-x package-list-packages-no-fetch +;; Like package-list-packages, but does not automatically fetch the +;; new list of packages. +;; +;; M-x package-install-from-buffer +;; Install a package consisting of a single .el file that appears +;; in the current buffer. This only works for packages which +;; define a Version header properly; package.el also supports the +;; extension headers Package-Version (in case Version is an RCS id +;; or similar), and Package-Requires (if the package requires other +;; packages). +;; +;; M-x package-install-file +;; Install a package from the indicated file. The package can be +;; either a tar file or a .el file. A tar file must contain an +;; appropriately-named "-pkg.el" file; a .el file must be properly +;; formatted as with package-install-from-buffer. + +;; The idea behind package.el is to be able to download packages and +;; install them. Packages are versioned and have versioned +;; dependencies. Furthermore, this supports built-in packages which +;; may or may not be newer than user-specified packages. This makes +;; it possible to upgrade Emacs and automatically disable packages +;; which have moved from external to core. (Note though that we don't +;; currently register any of these, so this feature does not actually +;; work.) + +;; This code supports a single package repository, ELPA. All packages +;; must be registered there. + +;; A package is described by its name and version. The distribution +;; format is either a tar file or a single .el file. + +;; A tar file should be named "NAME-VERSION.tar". The tar file must +;; unpack into a directory named after the package and version: +;; "NAME-VERSION". It must contain a file named "PACKAGE-pkg.el" +;; which consists of a call to define-package. It may also contain a +;; "dir" file and the info files it references. + +;; A .el file will be named "NAME-VERSION.el" in ELPA, but will be +;; installed as simply "NAME.el" in a directory named "NAME-VERSION". + +;; The downloader will download all dependent packages. It will also +;; byte-compile the package's lisp at install time. + +;; At activation time we will set up the load-path and the info path, +;; and we will load the package's autoloads. If a package's +;; dependencies are not available, we will not activate that package. + +;; Conceptually a package has multiple state transitions: +;; +;; * Download. Fetching the package from ELPA. +;; * Install. Untar the package, or write the .el file, into +;; ~/.emacs.d/elpa/ directory. +;; * Byte compile. Currently this phase is done during install, +;; but we may change this. +;; * Activate. Evaluate the autoloads for the package to make it +;; available to the user. +;; * Load. Actually load the package and run some code from it. + +;;; Thanks: +;;; (sorted by sort-lines): + +;; Jim Blandy +;; Karl Fogel +;; Kevin Ryde +;; Lawrence Mitchell +;; Michael Olson +;; Sebastian Tennant +;; Stefan Monnier +;; Vinicius Jose Latorre +;; Phil Hagelberg + +;;; ToDo: + +;; - putting info dirs at the start of the info path means +;; users see a weird ordering of categories. OTOH we want to +;; override later entries. maybe emacs needs to enforce +;; the standard layout? +;; - put bytecode in a separate directory tree +;; - perhaps give users a way to recompile their bytecode +;; or do it automatically when emacs changes +;; - give users a way to know whether a package is installed ok +;; - give users a way to view a package's documentation when it +;; only appears in the .el +;; - use/extend checkdoc so people can tell if their package will work +;; - "installed" instead of a blank in the status column +;; - tramp needs its files to be compiled in a certain order. +;; how to handle this? fix tramp? +;; - on emacs 21 we don't kill the -autoloads.el buffer. what about 22? +;; - maybe we need separate .elc directories for various emacs versions +;; and also emacs-vs-xemacs. That way conditional compilation can +;; work. But would this break anything? +;; - should store the package's keywords in archive-contents, then +;; let the users filter the package-menu by keyword. See +;; finder-by-keyword. (We could also let people view the +;; Commentary, but it isn't clear how useful this is.) +;; - William Xu suggests being able to open a package file without +;; installing it +;; - Interface with desktop.el so that restarting after an install +;; works properly +;; - Implement M-x package-upgrade, to upgrade any/all existing packages +;; - Use hierarchical layout. PKG/etc PKG/lisp PKG/info +;; ... except maybe lisp? +;; - It may be nice to have a macro that expands to the package's +;; private data dir, aka ".../etc". Or, maybe data-directory +;; needs to be a list (though this would be less nice) +;; a few packages want this, eg sokoban +;; - package menu needs: +;; ability to know which packages are built-in & thus not deletable +;; it can sometimes print odd results, like 0.3 available but 0.4 active +;; why is that? +;; - Allow multiple versions on the server...? +;; [ why bother? ] +;; - Don't install a package which will invalidate dependencies overall +;; - Allow something like (or (>= emacs 21.0) (>= xemacs 21.5)) +;; [ currently thinking, why bother.. KISS ] +;; - Allow optional package dependencies +;; then if we require 'bbdb', bbdb-specific lisp in lisp/bbdb +;; and just don't compile to add to load path ...? +;; - Have a list of archive URLs? [ maybe there's no point ] +;; - David Kastrup pointed out on the xemacs list that for GPL it +;; is friendlier to ship the source tree. We could "support" that +;; by just having a "src" subdir in the package. This isn't ideal +;; but it probably is not worth trying to support random source +;; tree layouts, build schemes, etc. +;; - Our treatment of the info path is somewhat bogus +;; - perhaps have an "unstable" tree in ELPA as well as a stable one + +;;; Code: + +(defconst package-archive-base "http://tromey.com/elpa/" + "Base URL for the package archive. +Ordinarily you should not need to edit this. +The default points to ELPA, the Emacs Lisp Package Archive. +Note that some code in package.el assumes that this is an http: URL.") + +(defconst package-archive-version 1 + "Version number of the package archive understood by this file. +Lower version numbers than this will probably be understood as well.") + +;; Note that this only works if you have the password, which you +;; probably don't :-). Also if you are using Emacs 21 then you will +;; need to hack ange-ftp-name-format to make this work. +(defvar package-archive-upload-base "/elpa@tromey.com@tromey.com:/" + "Base location for uploading to package archive.") + +(defconst package-el-maintainer "Tom Tromey " + "The package.el maintainer.") + +(defconst package-el-version "0.9" + "Version of package.el.") + +;; We don't prime the cache since it tends to get out of date. +(defvar package-archive-contents + nil + "A representation of the contents of the ELPA archive. +This is an alist mapping package names (symbols) to package +descriptor vectors. These are like the vectors for `package-alist' +but have an extra entry which is 'tar for tar packages and +'single for single-file packages.") + +(defvar package-user-dir + (expand-file-name (convert-standard-filename "~/.emacs.d/elpa")) + "Name of the directory where the user's packages are stored.") + +(defvar package-directory-list + (list (file-name-as-directory package-user-dir) + "/usr/share/emacs/site-lisp/elpa/") + "List of directories to search for packages.") + +(defun package-version-split (string) + "Split a package string into a version list." + (mapcar 'string-to-int (split-string string "[.]"))) + +(defconst package--builtins-base + ;; We use package-version split here to make sure to pick up the + ;; minor version. + `((emacs . [,(package-version-split emacs-version) nil + "GNU Emacs"]) + (package . [,(package-version-split package-el-version) + nil "Simple package system for GNU Emacs"])) + "Packages which are always built-in.") + +(defvar package--builtins + (delq nil + (append + package--builtins-base + (if (>= emacs-major-version 22) + ;; FIXME: emacs 22 includes tramp, rcirc, maybe + ;; other things... + '((erc . [(5 2) nil "An Emacs Internet Relay Chat client"]) + ;; The external URL is version 1.15, so make sure the + ;; built-in one looks newer. + (url . [(1 16) nil "URL handling libary"]))) + (if (>= emacs-major-version 23) + '(;; Strangely, nxml-version is missing in Emacs 23. + ;; We pick the merge date as the version. + (nxml . [(20071123) nil "Major mode for editing XML documents."]) + (bubbles . [(0 5) nil "Puzzle game for Emacs."]))))) + "Alist of all built-in packages. +Maps the package name to a vector [VERSION REQS DOCSTRING].") + +(defvar package-alist package--builtins + "Alist of all packages available for activation. +Maps the package name to a vector [VERSION REQS DOCSTRING].") + +(defvar package-activated-list + (mapcar #'car package-alist) + "List of the names of all activated packages.") + +(defvar package-obsolete-alist nil + "Representation of obsolete packages. +Like `package-alist', but maps package name to a second alist. +The inner alist is keyed by version.") + +(defun package-version-join (l) + "Turn a list of version numbers into a version string." + (mapconcat 'int-to-string l ".")) + +(defun package--version-first-nonzero (l) + (while (and l (= (car l) 0)) + (setq l (cdr l))) + (if l (car l) 0)) + +(defun package-version-compare (v1 v2 fun) + "Compare two version lists according to FUN. +FUN can be <, <=, =, >, >=, or /=." + (while (and v1 v2 (= (car v1) (car v2))) + (setq v1 (cdr v1) + v2 (cdr v2))) + (if v1 + (if v2 + ;; Both not null; we know the cars are not =. + (funcall fun (car v1) (car v2)) + ;; V1 not null, V2 null. + (funcall fun (package--version-first-nonzero v1) 0)) + (if v2 + ;; V1 null, V2 not null. + (funcall fun 0 (package--version-first-nonzero v2)) + ;; Both null. + (funcall fun 0 0)))) + +(defun package--test-version-compare () + "Test suite for `package-version-compare'." + (unless (and (package-version-compare '(0) '(0) '=) + (not (package-version-compare '(1) '(0) '=)) + (package-version-compare '(1 0 1) '(1) '>=) + (package-version-compare '(1 0 1) '(1) '>) + (not (package-version-compare '(0 9 1) '(1 0 2) '>=))) + (error "Failed")) + t) + +(defun package-strip-version (dirname) + "Strip the version from a combined package name and version. +E.g., if given \"quux-23.0\", will return \"quux\"" + (if (string-match "^\\(.*\\)-[0-9]+\\([.][0-9]+\\)*$" dirname) + (match-string 1 dirname))) + +(defun package-load-descriptor (dir package) + "Load the description file for a package. +Return nil if the package could not be found." + (let ((pkg-dir (concat (file-name-as-directory dir) package "/"))) + (if (file-directory-p pkg-dir) + (load (concat pkg-dir (package-strip-version package) "-pkg") nil t)))) + +(defun package-load-all-descriptors () + "Load descriptors of all packages. +Uses `package-directory-list' to find packages." + (mapc (lambda (dir) + (if (file-directory-p dir) + (mapc (lambda (name) + (package-load-descriptor dir name)) + (directory-files dir nil "^[^.]")))) + package-directory-list)) + +(defsubst package-desc-vers (desc) + "Extract version from a package description vector." + (aref desc 0)) + +(defsubst package-desc-reqs (desc) + "Extract requirements from a package description vector." + (aref desc 1)) + +(defsubst package-desc-doc (desc) + "Extract doc string from a package description vector." + (aref desc 2)) + +(defsubst package-desc-kind (desc) + "Extract the kind of download from an archive package description vector." + (aref desc 3)) + +(defun package-do-activate (package pkg-vec) + (let* ((pkg-name (symbol-name package)) + (pkg-ver-str (package-version-join (package-desc-vers pkg-vec))) + (dir-list package-directory-list) + (pkg-dir)) + (while dir-list + (let ((subdir (concat (car dir-list) pkg-name "-" pkg-ver-str "/"))) + (if (file-directory-p subdir) + (progn + (setq pkg-dir subdir) + (setq dir-list nil)) + (setq dir-list (cdr dir-list))))) + (unless pkg-dir + (error "Internal error: could not find directory for %s-%s" + pkg-name pkg-ver-str)) + (if (file-exists-p (concat pkg-dir "dir")) + (progn + ;; FIXME: not the friendliest, but simple. + (require 'info) + (info-initialize) + (setq Info-directory-list (cons pkg-dir Info-directory-list)))) + (setq load-path (cons pkg-dir load-path)) + ;; Load the autoloads and activate the package. + (load (concat pkg-dir (symbol-name package) "-autoloads") + nil t) + (setq package-activated-list (cons package package-activated-list)) + ;; Don't return nil. + t)) + +(defun package--built-in (package version) + "Return true if the package is built-in to Emacs." + (let ((elt (assq package package--builtins))) + (and elt + (package-version-compare (package-desc-vers (cdr elt)) version '=)))) + +;; FIXME: return a reason instead? +(defun package-activate (package version) + "Try to activate a package. +Return nil if the package could not be activated. +Recursively activates all dependencies of the named package." + ;; Assume the user knows what he is doing -- go ahead and activate a + ;; newer version of a package if an older one has already been + ;; activated. This is not ideal; we'd at least need to check to see + ;; if the package has actually been loaded, and not merely + ;; activated. However, don't try to activate 'emacs', as that makes + ;; no sense. + (unless (eq package 'emacs) + (let* ((pkg-desc (assq package package-alist)) + (this-version (package-desc-vers (cdr pkg-desc))) + (req-list (package-desc-reqs (cdr pkg-desc))) + ;; If the package was never activated, we want to do it + ;; now. + (keep-going (or (not (memq package package-activated-list)) + (package-version-compare this-version version '>)))) + (while (and req-list keep-going) + (or (package-activate (car (car req-list)) + (car (cdr (car req-list)))) + (setq keep-going nil)) + (setq req-list (cdr req-list))) + (if keep-going + (package-do-activate package (cdr pkg-desc)) + ;; We get here if a dependency failed to activate -- but we + ;; can also get here if the requested package was already + ;; activated. Return non-nil in the latter case. + (and (memq package package-activated-list) + (package-version-compare this-version version '>=)))))) + +(defun package-mark-obsolete (package pkg-vec) + "Put package on the obsolete list, if not already there." + (let ((elt (assq package package-obsolete-alist))) + (if elt + ;; If this obsolete version does not exist in the list, update + ;; it the list. + (unless (assoc (package-desc-vers pkg-vec) (cdr elt)) + (setcdr elt (cons (cons (package-desc-vers pkg-vec) pkg-vec) + (cdr elt)))) + ;; Make a new association. + (setq package-obsolete-alist + (cons (cons package (list (cons (package-desc-vers pkg-vec) + pkg-vec))) + package-obsolete-alist))))) + +;; (define-package "emacs" "21.4.1" "GNU Emacs core package.") +;; (define-package "erc" "5.1" "ERC - irc client" '((emacs "21.0"))) +(defun define-package (name-str version-string + &optional docstring requirements) + "Define a new package. +NAME is the name of the package, a string. +VERSION-STRING is the version of the package, a dotted sequence +of integers. +DOCSTRING is the optional description. +REQUIREMENTS is a list of requirements on other packages. +Each requirement is of the form (OTHER-PACKAGE \"VERSION\")." + (let* ((name (intern name-str)) + (pkg-desc (assq name package-alist)) + (new-version (package-version-split version-string)) + (new-pkg-desc + (cons name + (vector new-version + (mapcar + (lambda (elt) + (list (car elt) + (package-version-split (car (cdr elt))))) + requirements) + docstring)))) + ;; Only redefine a package if the redefinition is newer. + (if (or (not pkg-desc) + (package-version-compare new-version + (package-desc-vers (cdr pkg-desc)) + '>)) + (progn + (when pkg-desc + ;; Remove old package and declare it obsolete. + (setq package-alist (delq pkg-desc package-alist)) + (package-mark-obsolete (car pkg-desc) (cdr pkg-desc))) + ;; Add package to the alist. + (setq package-alist (cons new-pkg-desc package-alist))) + ;; You can have two packages with the same version, for instance + ;; one in the system package directory and one in your private + ;; directory. We just let the first one win. + (unless (package-version-compare new-version + (package-desc-vers (cdr pkg-desc)) + '=) + ;; The package is born obsolete. + (package-mark-obsolete (car new-pkg-desc) (cdr new-pkg-desc)))))) + +;; From Emacs 22. +(defun package-autoload-ensure-default-file (file) + "Make sure that the autoload file FILE exists and if not create it." + (unless (file-exists-p file) + (write-region + (concat ";;; " (file-name-nondirectory file) + " --- automatically extracted autoloads\n" + ";;\n" + ";;; Code:\n\n" + " \n;; Local Variables:\n" + ";; version-control: never\n" + ";; no-byte-compile: t\n" + ";; no-update-autoloads: t\n" + ";; End:\n" + ";;; " (file-name-nondirectory file) + " ends here\n") + nil file)) + file) + +(defun package-generate-autoloads (name pkg-dir) + (let* ((auto-name (concat name "-autoloads.el")) + (ignore-name (concat name "-pkg.el")) + (generated-autoload-file (concat pkg-dir auto-name)) + (version-control 'never)) + ;; In Emacs 22 'update-autoloads-from-directories' does not seem + ;; to be autoloaded... + (require 'autoload) + (unless (fboundp 'autoload-ensure-default-file) + (package-autoload-ensure-default-file generated-autoload-file)) + (update-autoloads-from-directories pkg-dir))) + +(defun package-untar-buffer () + "Untar the current buffer. +This uses `tar-untar-buffer' if it is available. +Otherwise it uses an external `tar' program. +`default-directory' should be set by the caller." + (require 'tar-mode) + (if (fboundp 'tar-untar-buffer) + (progn + ;; tar-mode messes with narrowing, so we just let it have the + ;; whole buffer to play with. + (delete-region (point-min) (point)) + (tar-mode) + (tar-untar-buffer)) + ;; FIXME: check the result. + (call-process-region (point) (point-max) "tar" nil '(nil nil) nil + "xf" "-"))) + +(defun package-unpack (name version) + (let ((pkg-dir (concat (file-name-as-directory package-user-dir) + (symbol-name name) "-" version "/"))) + ;; Be careful!! + (make-directory package-user-dir t) + (if (file-directory-p pkg-dir) + (mapc (lambda (file) nil) ; 'delete-file -- FIXME: when we're + ; more confident + (directory-files pkg-dir t "^[^.]"))) + (let* ((default-directory (file-name-as-directory package-user-dir))) + (package-untar-buffer) + (package-generate-autoloads (symbol-name name) pkg-dir) + (let ((load-path (cons pkg-dir load-path))) + (byte-recompile-directory pkg-dir 0 t))))) + +(defun package-unpack-single (file-name version desc requires) + "Install the contents of the current buffer as a package." + (let* ((dir (file-name-as-directory package-user-dir))) + ;; Special case "package". + (if (string= file-name "package") + (write-region (point-min) (point-max) (concat dir file-name ".el") + nil nil nil nil) + (let ((pkg-dir (file-name-as-directory + (concat dir file-name "-" version)))) + (make-directory pkg-dir t) + (write-region (point-min) (point-max) + (concat pkg-dir file-name ".el") + nil nil nil 'excl) + (let ((print-level nil) + (print-length nil)) + (write-region + (concat + (prin1-to-string + (list 'define-package + file-name + version + desc + (list 'quote + ;; Turn version lists into string form. + (mapcar + (lambda (elt) + (list (car elt) + (package-version-join (car (cdr elt))))) + requires)))) + "\n") + nil + (concat pkg-dir file-name "-pkg.el") + nil nil nil 'excl)) + (package-generate-autoloads file-name pkg-dir) + (let ((load-path (cons pkg-dir load-path))) + (byte-recompile-directory pkg-dir 0 t)))))) + +(defun package-handle-response () + "Handle the response from the server. +Parse the HTTP response and throw if an error occurred. +The url package seems to require extra processing for this. +This should be called in a `save-excursion', in the download buffer. +It will move point to somewhere in the headers." + ;; We assume HTTP here. + (let ((response (url-http-parse-response))) + (when (or (< response 200) (>= response 300)) + (display-buffer (current-buffer)) + (error "Error during download request:%s" + (buffer-substring-no-properties (point) (progn + (end-of-line) + (point))))))) + +(defun package-download-single (name version desc requires) + "Download and install a single-file package." + (let ((buffer (url-retrieve-synchronously + (concat package-archive-base + (symbol-name name) "-" version ".el")))) + (save-excursion + (set-buffer buffer) + (package-handle-response) + (re-search-forward "^$" nil 'move) + (forward-char) + (delete-region (point-min) (point)) + (package-unpack-single (symbol-name name) version desc requires) + (kill-buffer buffer)))) + +(defun package-download-tar (name version) + "Download and install a tar package." + (let ((tar-buffer (url-retrieve-synchronously + (concat package-archive-base + (symbol-name name) "-" version ".tar")))) + (save-excursion + (set-buffer tar-buffer) + (package-handle-response) + (re-search-forward "^$" nil 'move) + (forward-char) + (package-unpack name version) + (kill-buffer tar-buffer)))) + +(defun package-installed-p (package version) + (let ((pkg-desc (assq package package-alist))) + (and pkg-desc + (package-version-compare version + (package-desc-vers (cdr pkg-desc)) + '>=)))) + +(defun package-compute-transaction (result requirements) + (while requirements + (let* ((elt (car requirements)) + (next-pkg (car elt)) + (next-version (car (cdr elt)))) + (unless (package-installed-p next-pkg next-version) + (let ((pkg-desc (assq next-pkg package-archive-contents))) + (unless pkg-desc + (error "Package '%s' not available for installation" + (symbol-name next-pkg))) + (unless (package-version-compare (package-desc-vers (cdr pkg-desc)) + next-version + '>=) + (error + "Need package '%s' with version %s, but only %s is available" + (symbol-name next-pkg) (package-version-join next-version) + (package-version-join (package-desc-vers (cdr pkg-desc))))) + ;; Only add to the transaction if we don't already have it. + (unless (memq next-pkg result) + (setq result (cons next-pkg result))) + (setq result + (package-compute-transaction result + (package-desc-reqs + (cdr pkg-desc))))))) + (setq requirements (cdr requirements))) + result) + +(defun package-read-from-string (str) + "Read a Lisp expression from STR. +Signal an error if the entire string was not used." + (let* ((read-data (read-from-string str)) + (more-left + (condition-case nil + ;; The call to `ignore' suppresses a compiler warning. + (progn (ignore (read-from-string + (substring str (cdr read-data)))) + t) + (end-of-file nil)))) + (if more-left + (error "Can't read whole string") + (car read-data)))) + +(defun package--read-archive-file (file) + "Re-read archive file FILE, if it exists. +Will return the data from the file, or nil if the file does not exist. +Will throw an error if the archive version is too new." + (let ((filename (concat (file-name-as-directory package-user-dir) + file))) + (if (file-exists-p filename) + (with-temp-buffer + (insert-file-contents-literally filename) + (let ((contents (package-read-from-string + (buffer-substring-no-properties (point-min) + (point-max))))) + (if (> (car contents) package-archive-version) + (error "Package archive version %d is greater than %d - upgrade package.el" + (car contents) package-archive-version)) + (cdr contents)))))) + +(defun package-read-archive-contents () + "Re-read `archive-contents' and `builtin-packages', if they exist. +Will set `package-archive-contents' and `package--builtins' if successful. +Will throw an error if the archive version is too new." + (let ((archive-contents (package--read-archive-file "archive-contents")) + (builtins (package--read-archive-file "builtin-packages"))) + (if archive-contents + ;; Version 1 of 'archive-contents' is identical to our + ;; internal representation. + (setq package-archive-contents archive-contents)) + (if builtins + ;; Version 1 of 'builtin-packages' is a list where the car is + ;; a split emacs version and the cdr is an alist suitable for + ;; package--builtins. + (let ((our-version (package-version-split emacs-version)) + (result package--builtins-base)) + (setq package--builtins + (dolist (elt builtins result) + (if (package-version-compare our-version (car elt) '>=) + (setq result (append (cdr elt) result))))))))) + +(defun package-download-transaction (transaction) + "Download and install all the packages in the given transaction." + (mapc (lambda (elt) + (let* ((desc (cdr (assq elt package-archive-contents))) + (v-string (package-version-join (package-desc-vers desc))) + (kind (package-desc-kind desc))) + (cond + ((eq kind 'tar) + (package-download-tar elt v-string)) + ((eq kind 'single) + (package-download-single elt v-string + (package-desc-doc desc) + (package-desc-reqs desc))) + (t + (error "Unknown package kind: " (symbol-name kind)))))) + transaction)) + +(defun package-install (name) + "Install the package named NAME. +Interactively, prompts for the package name. +The package is found on the archive site, see `package-archive-base'." + (interactive + (list (progn + ;; Make sure we're using the most recent download of the + ;; archive. Maybe we should be updating the archive first? + (package-read-archive-contents) + (intern (completing-read "Install package: " + (mapcar (lambda (elt) + (cons (symbol-name (car elt)) + nil)) + package-archive-contents) + nil t))))) + (let ((pkg-desc (assq name package-archive-contents))) + (unless pkg-desc + (error "Package '%s' not available for installation" + (symbol-name name))) + (let ((transaction + (package-compute-transaction (list name) + (package-desc-reqs (cdr pkg-desc))))) + (package-download-transaction transaction))) + ;; Try to activate it. + (package-initialize)) + +(defun package-strip-rcs-id (v-str) + "Strip RCS version ID from the version string. +If the result looks like a dotted numeric version, return it. +Otherwise return nil." + (if v-str + (if (string-match "^[ \t]*[$]Revision:[ \t]\([0-9.]+\)[ \t]*[$]$" v-str) + (match-string 1 v-str) + (if (string-match "^[0-9.]*$" v-str) + v-str)))) + +(defun package-buffer-info () + "Return a vector of information about the package in the current buffer. +The vector looks like [FILENAME REQUIRES DESCRIPTION VERSION COMMENTARY] +FILENAME is the file name, a string. It does not have the \".el\" extension. +REQUIRES is a requires list, or nil. +DESCRIPTION is the package description (a string). +VERSION is the version, a string. +COMMENTARY is the commentary section, a string, or nil if none. +Throws an exception if the buffer does not contain a conforming package. +If there is a package, narrows the buffer to the file's boundaries. +May narrow buffer or move point even on failure." + (goto-char (point-min)) + (if (re-search-forward "^;;; \\([^ ]*\\)\\.el --- \\(.*\\)$" nil t) + (let ((file-name (match-string 1)) + (desc (match-string 2)) + (start (progn (beginning-of-line) (point)))) + (if (search-forward (concat ";;; " file-name ".el ends here")) + (progn + ;; Try to include a trailing newline. + (forward-line) + (narrow-to-region start (point)) + (require 'lisp-mnt) + ;; Use some headers we've invented to drive the process. + (let* ((requires-str (lm-header "package-requires")) + (requires (if requires-str + (package-read-from-string requires-str))) + ;; Prefer Package-Version, because if it is + ;; defined the package author probably wants us + ;; to use it. Otherwise try Version. + (pkg-version + (or (package-strip-rcs-id (lm-header "package-version")) + (package-strip-rcs-id (lm-header "version")))) + (commentary (lm-commentary))) + (unless pkg-version + (error + "Package does not define a usable \"Version\" or \"Package-Version\" header")) + ;; Turn string version numbers into list form. + (setq requires + (mapcar + (lambda (elt) + (list (car elt) + (package-version-split (car (cdr elt))))) + requires)) + (set-text-properties 0 (length file-name) nil file-name) + (set-text-properties 0 (length pkg-version) nil pkg-version) + (set-text-properties 0 (length desc) nil desc) + (vector file-name requires desc pkg-version commentary))) + (error "Package missing a terminating comment"))) + (error "No starting comment for package"))) + +(defun package-tar-file-info (file) + "Find package information for a tar file. +FILE is the name of the tar file to examine. +The return result is a vector like `package-buffer-info'." + (unless (string-match "^\\(.+\\)-\\([0-9.]+\\)\\.tar$" file) + (error "`%s' doesn't have a package-ish name" file)) + (let* ((pkg-name (file-name-nondirectory (match-string-no-properties 1 file))) + (pkg-version (match-string-no-properties 2 file)) + ;; Extract the package descriptor. + (pkg-def-contents (shell-command-to-string + ;; Requires GNU tar. + (concat "tar -xOf " file " " + pkg-name "-" pkg-version "/" + pkg-name "-pkg.el"))) + (pkg-def-parsed (package-read-from-string pkg-def-contents))) + (unless (eq (car pkg-def-parsed) 'define-package) + (error "%s-pkg.el doesn't contain `define-package' sexp" pkg-name)) + (let ((name-str (nth 1 pkg-def-parsed)) + (version-string (nth 2 pkg-def-parsed)) + (docstring (nth 3 pkg-def-parsed)) + (requires (nth 4 pkg-def-parsed)) + + (readme (shell-command-to-string + ;; Requires GNU tar. + (concat "tar -xOf " file " " + pkg-name "-" pkg-version "/README")))) + (unless (equal pkg-version version-string) + (error "Inconsistent versions!")) + (unless (equal pkg-name name-str) + (error "Inconsistent names!")) + ;; Kind of a hack. + (if (string-match ": Not found in archive" readme) + (setq readme nil)) + ;; Turn string version numbers into list form. + (if (eq (car requires) 'quote) + (setq requires (car (cdr requires)))) + (setq requires + (mapcar + (lambda (elt) + (list (car elt) + (package-version-split (car (cdr elt))))) + requires)) + (vector pkg-name requires docstring version-string readme)))) + +(defun package-install-buffer-internal (pkg-info type) + (save-excursion + (save-restriction + (let* ((file-name (aref pkg-info 0)) + (requires (aref pkg-info 1)) + (desc (if (string= (aref pkg-info 2) "") + "No description available." + (aref pkg-info 2))) + (pkg-version (aref pkg-info 3))) + ;; Download and install the dependencies. + (let ((transaction (package-compute-transaction nil requires))) + (package-download-transaction transaction)) + ;; Install the package itself. + (cond + ((eq type 'single) + (package-unpack-single file-name pkg-version desc requires)) + ((eq type 'tar) + (package-unpack (intern file-name) pkg-version)) + (t + (error "Unknown type: %s" (symbol-name type)))) + ;; Try to activate it. + (package-initialize))))) + +(defun package-install-from-buffer () + "Install a package from the current buffer. +The package is assumed to be a single .el file which +follows the elisp comment guidelines; see +info node `(elisp)Library Headers'." + (interactive) + (package-install-buffer-internal (package-buffer-info) 'single)) + +(defun package-install-file (file) + "Install a package from a file. +The file can either be a tar file or an Emacs Lisp file." + (interactive "fPackage file name: ") + (with-temp-buffer + (insert-file-contents-literally file) + (cond + ((string-match "\\.el$" file) (package-install-from-buffer)) + ((string-match "\\.tar$" file) + (package-install-buffer-internal (package-tar-file-info file) 'tar)) + (t (error "Unrecognized extension `%s'" (file-name-extension file)))))) + +(defun package-delete (name version) + (require 'dired) ; for dired-delete-file + (dired-delete-file (concat (file-name-as-directory package-user-dir) + name "-" version) + ;; FIXME: query user? + 'always)) + +(defun package--encode (string) + "Encode a string by replacing some characters with XML entities." + ;; We need a special case for translating "&" to "&". + (let ((index)) + (while (setq index (string-match "[&]" string index)) + (setq string (replace-match "&" t nil string)) + (setq index (1+ index)))) + (while (string-match "[<]" string) + (setq string (replace-match "<" t nil string))) + (while (string-match "[>]" string) + (setq string (replace-match ">" t nil string))) + (while (string-match "[']" string) + (setq string (replace-match "'" t nil string))) + (while (string-match "[\"]" string) + (setq string (replace-match """ t nil string))) + string) + +(defun package--make-rss-entry (title text) + (let ((date-string (format-time-string "%a, %d %B %Y %T %z"))) + (concat "\n" + "" (package--encode title) "\n" + ;; FIXME: should have a link in the web page. + "" package-archive-base "news.html\n" + "" (package--encode text) "\n" + "" date-string "\n" + "\n"))) + +(defun package--make-html-entry (title text) + (concat "
  • " (format-time-string "%B %e") " - " + title " - " (package--encode text) + "
  • \n")) + +(defun package--update-file (file location text) + (save-excursion + (let ((old-buffer (find-buffer-visiting file))) + (with-current-buffer (let ((find-file-visit-truename t)) + (or old-buffer (find-file-noselect file))) + (goto-char (point-min)) + (search-forward location) + (forward-line) + (insert text) + (let ((file-precious-flag t)) + (save-buffer)) + (unless old-buffer + (kill-buffer (current-buffer))))))) + +(defun package-maint-add-news-item (title description) + "Add a news item to the ELPA web pages. +TITLE is the title of the news item. +DESCRIPTION is the text of the news item. +You need administrative access to ELPA to use this." + (interactive "sTitle: \nsText: ") + (package--update-file (concat package-archive-upload-base "elpa.rss") + "" + (package--make-rss-entry title description)) + (package--update-file (concat package-archive-upload-base "news.html") + "New entries go here" + (package--make-html-entry title description))) + +(defun package--update-news (package version description) + "Update the ELPA web pages when a package is uploaded." + (package-maint-add-news-item (concat package " version " version) + description)) + +(defun package-upload-buffer-internal (pkg-info extension) + "Upload a package whose contents are in the current buffer. +PKG-INFO is the package info, see `package-buffer-info'. +EXTENSION is the file extension, a string. It can be either +\"el\" or \"tar\"." + (save-excursion + (save-restriction + (let* ((file-type (cond + ((equal extension "el") 'single) + ((equal extension "tar") 'tar) + (t (error "Unknown extension `%s'" extension)))) + (file-name (aref pkg-info 0)) + (pkg-name (intern file-name)) + (requires (aref pkg-info 1)) + (desc (if (string= (aref pkg-info 2) "") + (read-string "Description of package: ") + (aref pkg-info 2))) + (pkg-version (aref pkg-info 3)) + (commentary (aref pkg-info 4)) + (split-version (package-version-split pkg-version)) + (pkg-buffer (current-buffer)) + + ;; Download latest archive-contents. + (buffer (url-retrieve-synchronously + (concat package-archive-base "archive-contents")))) + + ;; Parse archive-contents. + (set-buffer buffer) + (package-handle-response) + (re-search-forward "^$" nil 'move) + (forward-char) + (delete-region (point-min) (point)) + (let ((contents (package-read-from-string + (buffer-substring-no-properties (point-min) + (point-max)))) + (new-desc (vector split-version requires desc file-type))) + (if (> (car contents) package-archive-version) + (error "Unrecognized archive version %d" (car contents))) + (let ((elt (assq pkg-name (cdr contents)))) + (if elt + (if (package-version-compare split-version + (package-desc-vers (cdr elt)) + '<=) + (error "New package has smaller version: %s" pkg-version) + (setcdr elt new-desc)) + (setq contents (cons (car contents) + (cons (cons pkg-name new-desc) + (cdr contents)))))) + + ;; Now CONTENTS is the updated archive contents. Upload + ;; this and the package itself. For now we assume ELPA is + ;; writable via file primitives. + (let ((print-level nil) + (print-length nil)) + (write-region (concat (pp-to-string contents) "\n") + nil + (concat package-archive-upload-base + "archive-contents"))) + + ;; If there is a commentary section, write it. + (when commentary + (write-region commentary nil + (concat package-archive-upload-base + (symbol-name pkg-name) "-readme.txt"))) + + (set-buffer pkg-buffer) + (kill-buffer buffer) + (write-region (point-min) (point-max) + (concat package-archive-upload-base + file-name "-" pkg-version + "." extension) + nil nil nil 'excl) + + ;; Write a news entry. + (package--update-news (concat file-name "." extension) + pkg-version desc) + + ;; special-case "package": write a second copy so that the + ;; installer can easily find the latest version. + (if (string= file-name "package") + (write-region (point-min) (point-max) + (concat package-archive-upload-base + file-name "." extension) + nil nil nil 'ask))))))) + +(defun package-upload-buffer () + "Upload a single .el file to ELPA from the current buffer." + (interactive) + (save-excursion + (save-restriction + ;; Find the package in this buffer. + (let ((pkg-info (package-buffer-info))) + (package-upload-buffer-internal pkg-info "el"))))) + +(defun package-upload-file (file) + (interactive "fPackage file name: ") + (with-temp-buffer + (insert-file-contents-literally file) + (let ((info (cond + ((string-match "\\.tar$" file) (package-tar-file-info file)) + ((string-match "\\.el$" file) (package-buffer-info)) + (t (error "Unrecognized extension `%s'" + (file-name-extension file)))))) + (package-upload-buffer-internal info (file-name-extension file))))) + +(defun package-gnus-summary-upload () + "Upload a package contained in the current *Article* buffer. +This should be invoked from the gnus *Summary* buffer." + (interactive) + (save-excursion + (set-buffer gnus-article-buffer) + (package-upload-buffer))) + +(defun package--download-one-archive (file) + "Download a single archive file and cache it locally." + (let ((buffer (url-retrieve-synchronously + (concat package-archive-base file)))) + (save-excursion + (set-buffer buffer) + (package-handle-response) + (re-search-forward "^$" nil 'move) + (forward-char) + (delete-region (point-min) (point)) + (setq buffer-file-name (concat (file-name-as-directory package-user-dir) + file)) + (let ((version-control 'never)) + (save-buffer)) + (kill-buffer buffer)))) + +(defun package-refresh-contents () + "Download the ELPA archive description if needed. +Invoking this will ensure that Emacs knows about the latest versions +of all packages. This will let Emacs make them available for +download." + (interactive) + (package--download-one-archive "archive-contents") + (package--download-one-archive "builtin-packages") + (package-read-archive-contents)) + +(defun package-initialize () + "Load all packages and activate as many as possible." + (setq package-obsolete-alist nil) + (package-load-all-descriptors) + (package-read-archive-contents) + ;; Try to activate all our packages. + (mapc (lambda (elt) + (package-activate (car elt) (package-desc-vers (cdr elt)))) + package-alist)) + + + +;;;; Package menu mode. + +(defvar package-menu-mode-map nil + "Local keymap for `package-menu-mode' buffers.") + +(unless package-menu-mode-map + (setq package-menu-mode-map (make-keymap)) + (suppress-keymap package-menu-mode-map) + (define-key package-menu-mode-map "q" 'quit-window) + (define-key package-menu-mode-map "n" 'next-line) + (define-key package-menu-mode-map "p" 'previous-line) + (define-key package-menu-mode-map "u" 'package-menu-mark-unmark) + (define-key package-menu-mode-map "\177" 'package-menu-backup-unmark) + (define-key package-menu-mode-map "d" 'package-menu-mark-delete) + (define-key package-menu-mode-map "i" 'package-menu-mark-install) + (define-key package-menu-mode-map "g" 'package-menu-revert) + (define-key package-menu-mode-map "r" 'package-menu-refresh) + (define-key package-menu-mode-map "~" + 'package-menu-mark-obsolete-for-deletion) + (define-key package-menu-mode-map "x" 'package-menu-execute) + (define-key package-menu-mode-map "h" 'package-menu-quick-help) + (define-key package-menu-mode-map "?" 'package-menu-view-commentary) + ) + +(defvar package-menu-sort-button-map + (let ((map (make-sparse-keymap))) + (define-key map [header-line mouse-1] 'package-menu-sort-by-column) + (define-key map [follow-link] 'mouse-face) + map) + "Local keymap for package menu sort buttons.") + +(put 'package-menu-mode 'mode-class 'special) + +(defun package-menu-mode () + "Major mode for browsing a list of packages. +Letters do not insert themselves; instead, they are commands. +\\ +\\{package-menu-mode-map}" + (kill-all-local-variables) + (use-local-map package-menu-mode-map) + (setq major-mode 'package-menu-mode) + (setq mode-name "Package Menu") + (setq truncate-lines t) + (setq buffer-read-only t) + ;; Support Emacs 21. + (if (fboundp 'run-mode-hooks) + (run-mode-hooks 'package-menu-mode-hook) + (run-hooks 'package-menu-mode-hook))) + +(defun package-menu-refresh () + "Download the ELPA archive. +This fetches the file describing the current contents of +the Emacs Lisp Package Archive, and then refreshes the +package menu. This lets you see what new packages are +available for download." + (interactive) + (package-refresh-contents) + (package-list-packages-internal)) + +(defun package-menu-revert () + "Update the list of packages." + (interactive) + (package-list-packages-internal)) + +(defun package-menu-mark-internal (what) + (unless (eobp) + (let ((buffer-read-only nil)) + (beginning-of-line) + (delete-char 1) + (insert what) + (forward-line)))) + +;; fixme numeric argument +(defun package-menu-mark-delete (num) + "Mark a package for deletion and move to the next line." + (interactive "p") + (package-menu-mark-internal "D")) + +(defun package-menu-mark-install (num) + "Mark a package for installation and move to the next line." + (interactive "p") + (package-menu-mark-internal "I")) + +(defun package-menu-mark-unmark (num) + "Clear any marks on a package and move to the next line." + (interactive "p") + (package-menu-mark-internal " ")) + +(defun package-menu-backup-unmark () + "Back up one line and clear any marks on that package." + (interactive) + (forward-line -1) + (package-menu-mark-internal " ") + (forward-line -1)) + +(defun package-menu-mark-obsolete-for-deletion () + "Mark all obsolete packages for deletion." + (interactive) + (save-excursion + (goto-char (point-min)) + (forward-line 2) + (while (not (eobp)) + (if (looking-at ".*\\s obsolete\\s ") + (package-menu-mark-internal "D") + (forward-line 1))))) + +(defun package-menu-quick-help () + "Show short key binding help for package-menu-mode." + (interactive) + (message "n-ext, i-nstall, d-elete, u-nmark, x-ecute, r-efresh, h-elp")) + +(defun package-menu-view-commentary () + "Display information about this package. +For single-file packages, shows the commentary section from the header. +For larger packages, shows the README file." + (interactive) + (let* (start-point ok + (pkg-name (package-menu-get-package)) + (buffer (url-retrieve-synchronously (concat package-archive-base + pkg-name + "-readme.txt")))) + (with-current-buffer buffer + ;; FIXME: it would be nice to work with any URL type. + (setq start-point url-http-end-of-headers) + (setq ok (eq (url-http-parse-response) 200))) + (let ((new-buffer (get-buffer-create "*Package Info*"))) + (with-current-buffer new-buffer + (let ((buffer-read-only nil)) + (erase-buffer) + (insert "Package information for " pkg-name "\n\n") + (if ok + (insert-buffer-substring buffer start-point) + (insert "This package does not have a README file or commentary comment.\n")) + (goto-char (point-min)) + (view-mode))) + (display-buffer new-buffer t)))) + +;; Return the name of the package on the current line. +(defun package-menu-get-package () + (save-excursion + (beginning-of-line) + (if (looking-at ". \\([^ \t]*\\)") + (match-string 1)))) + +;; Return the version of the package on the current line. +(defun package-menu-get-version () + (save-excursion + (beginning-of-line) + (if (looking-at ". [^ \t]*[ \t]*\\([0-9.]*\\)") + (match-string 1)))) + +(defun package-menu-get-status () + (save-excursion + (if (looking-at ". [^ \t]*[ \t]*[^ \t]*[ \t]*\\([^ \t]*\\)") + (match-string 1) + ""))) + +(defun package-menu-execute () + "Perform all the marked actions. +Packages marked for installation will be downloaded and +installed. Packages marked for deletion will be removed. +Note that after installing packages you will want to restart +Emacs." + (interactive) + (goto-char (point-min)) + (forward-line 2) + (while (not (eobp)) + (let ((cmd (char-after)) + (pkg-name (package-menu-get-package)) + (pkg-vers (package-menu-get-version)) + (pkg-status (package-menu-get-status))) + (cond + ((eq cmd ?D) + (when (and (string= pkg-status "installed") + (string= pkg-name "package")) + ;; FIXME: actually, we could be tricky and remove all info. + ;; But that is drastic and the user can do that instead. + (error "Can't delete most recent version of `package'")) + ;; Ask for confirmation here? Maybe if package status is ""? + ;; Or if any lisp from package is actually loaded? + (message "Deleting %s-%s..." pkg-name pkg-vers) + (package-delete pkg-name pkg-vers) + (message "Deleting %s-%s... done" pkg-name pkg-vers)) + ((eq cmd ?I) + (package-install (intern pkg-name))))) + (forward-line)) + (package-menu-revert)) + +(defun package-print-package (package version key desc) + (let ((face + (cond ((eq package 'emacs) 'font-lock-builtin-face) + ((string= key "available") 'default) + ((string= key "installed") 'font-lock-comment-face) + (t ; obsolete, but also the default. + ; is warning ok? + 'font-lock-warning-face)))) + (insert (propertize " " 'font-lock-face face)) + (insert (propertize (symbol-name package) 'font-lock-face face)) + (indent-to 20 1) + (insert (propertize (package-version-join version) 'font-lock-face face)) + (indent-to 30 1) + (insert (propertize key 'font-lock-face face)) + ;; FIXME: this 'when' is bogus... + (when desc + (indent-to 41 1) + (insert (propertize desc 'font-lock-face face))) + (insert "\n"))) + +(defun package-list-maybe-add (package version status description result) + (let ((elt (assoc (cons package version) result))) + (unless elt + (setq result (cons (list (cons package version) status description) + result)))) + result) + +;; This decides how we should sort; nil means by package name. +(defvar package-menu-sort-key nil) + +(defun package-list-packages-internal () + (package-initialize) ; FIXME: do this here? + (with-current-buffer (get-buffer-create "*Packages*") + (setq buffer-read-only nil) + (erase-buffer) + (let ((info-list)) + (mapc (lambda (elt) + (setq info-list + (package-list-maybe-add (car elt) + (package-desc-vers (cdr elt)) + ;; FIXME: it turns out to + ;; be tricky to see if + ;; this package is + ;; presently activated. + ;; That is lame! + "installed" + (package-desc-doc (cdr elt)) + info-list))) + package-alist) + (mapc (lambda (elt) + (setq info-list + (package-list-maybe-add (car elt) + (package-desc-vers (cdr elt)) + "available" + (package-desc-doc (cdr elt)) + info-list))) + package-archive-contents) + (mapc (lambda (elt) + (mapc (lambda (inner-elt) + (setq info-list + (package-list-maybe-add (car elt) + (package-desc-vers + (cdr inner-elt)) + "obsolete" + (package-desc-doc + (cdr inner-elt)) + info-list))) + (cdr elt))) + package-obsolete-alist) + (let ((selector (cond + ((string= package-menu-sort-key "Version") + ;; FIXME this doesn't work. + #'(lambda (e) (cdr (car e)))) + ((string= package-menu-sort-key "Status") + #'(lambda (e) (car (cdr e)))) + ((string= package-menu-sort-key "Description") + #'(lambda (e) (car (cdr (cdr e))))) + (t ; "Package" is default. + #'(lambda (e) (symbol-name (car (car e)))))))) + (setq info-list + (sort info-list + (lambda (left right) + (let ((vleft (funcall selector left)) + (vright (funcall selector right))) + (string< vleft vright)))))) + (mapc (lambda (elt) + (package-print-package (car (car elt)) + (cdr (car elt)) + (car (cdr elt)) + (car (cdr (cdr elt))))) + info-list)) + (goto-char (point-min)) + (current-buffer))) + +(defun package-menu-sort-by-column (&optional e) + "Sort the package menu by the last column clicked on." + (interactive (list last-input-event)) + (if e (mouse-select-window e)) + (let* ((pos (event-start e)) + (obj (posn-object pos)) + (col (if obj + (get-text-property (cdr obj) 'column-name (car obj)) + (get-text-property (posn-point pos) 'column-name)))) + (setq package-menu-sort-key col)) + (package-list-packages-internal)) + +(defun package--list-packages () + "Display a list of packages. +Helper function that does all the work for the user-facing functions." + (with-current-buffer (package-list-packages-internal) + (package-menu-mode) + ;; Set up the header line. + (setq header-line-format + (mapconcat + (lambda (pair) + (let ((column (car pair)) + (name (cdr pair))) + (concat + ;; Insert a space that aligns the button properly. + (propertize " " 'display (list 'space :align-to column) + 'face 'fixed-pitch) + ;; Set up the column button. + (if (string= name "Version") + name + (propertize name + 'column-name name + 'help-echo "mouse-1: sort by column" + 'mouse-face 'highlight + 'keymap package-menu-sort-button-map))))) + ;; We take a trick from buff-menu and have a dummy leading + ;; space to align the header line with the beginning of the + ;; text. This doesn't really work properly on Emacs 21, + ;; but it is close enough. + '((0 . "") + (2 . "Package") + (20 . "Version") + (30 . "Status") + (41 . "Description")) + "")) + + ;; It's okay to use pop-to-buffer here. The package menu buffer + ;; has keybindings, and the user just typed 'M-x + ;; package-list-packages', suggesting that they might want to use + ;; them. + (pop-to-buffer (current-buffer)))) + +(defun package-list-packages () + "Display a list of packages. +Fetches the updated list of packages before displaying. +The list is displayed in a buffer named `*Packages*'." + (interactive) + (package-refresh-contents) + (package--list-packages)) + +(defun package-list-packages-no-fetch () + "Display a list of packages. +Does not fetch the updated list of packages before displaying. +The list is displayed in a buffer named `*Packages*'." + (interactive) + (package--list-packages)) + +;; Make it appear on the menu. +(define-key-after menu-bar-options-menu [package] + '(menu-item "Manage Packages" package-list-packages + :help "Install or uninstall additional Emacs packages")) + + + +(eval-when-compile + (require 'reporter)) + +(defun package-report-bug () + "Submit a bug report for package.el via email." + (interactive) + (require 'reporter) + (reporter-submit-bug-report + package-el-maintainer + (concat "package.el " package-el-version) + '(package-archive-base + package-archive-version + package-archive-contents + package-user-dir + package-directory-list + package-alist + package-activated-list + package-obsolete-alist))) + +(provide 'package) + +;;; package.el ends here diff --git a/elisp/erbot/.cvsignore b/elisp/erbot/.cvsignore new file mode 100644 index 0000000..f85ee5c --- /dev/null +++ b/elisp/erbot/.cvsignore @@ -0,0 +1,2 @@ +{arch} +.arch-ids diff --git a/elisp/erbot/AUTHORS b/elisp/erbot/AUTHORS new file mode 100644 index 0000000..54c0537 --- /dev/null +++ b/elisp/erbot/AUTHORS @@ -0,0 +1,40 @@ +Maintainers: + +Savannah Admins: + Name (username) + --------------------------------------------------- + D. Goel (deego) + Michael Olson (mwolson) + Vivek Dasmohapatra (fledermaus) + +Savannah Members: + Name (username) + --------------------------------------------------- + Sebastian Freundt (hroptatyr) + Jose E Marchesi (jemarch) + Pete Kazmier (pkazmier) + Taylor R Campbell (riastradh) + Yann Hodique (sigma) + +Other Contributors: + Name (irc nick) + --------------------------------------------------- + Alejandro Benitez + Alex Schroeder (kensanata) + Brian Templeton (bpt) + Damien Elmes (resolve) + David Edmunston + Dheeraj Buduru (dbuduru) + Enrico Bandiera + Grant Bowman (grantbow) + J. Michael Dupont (mdupont) + Jorgen Schaefer (forcer) + Lawrence Mitchell (lawrence) + Luis Fernandes (e1f) + Mario Lang (delYsid) + +(If we have left someone out, apologies: If you have commit privileges, + please add them - If not, please ask an admin or member) +==================================================== + +Last modified: Wed 2009-09-30 23:48:37 +0100 (fledermaus) diff --git a/elisp/erbot/COPYING b/elisp/erbot/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/elisp/erbot/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 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 this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/elisp/erbot/CVS/Entries b/elisp/erbot/CVS/Entries new file mode 100644 index 0000000..14b11ad --- /dev/null +++ b/elisp/erbot/CVS/Entries @@ -0,0 +1,41 @@ +/.cvsignore/1.1/Thu Jan 5 00:15:39 2006// +/AUTHORS/1.16/Wed Sep 30 22:51:34 2009// +/COPYING/1.2/Fri Nov 23 16:31:58 2007// +/ChangeLog/1.69/Thu Dec 6 16:25:41 2007// +/HISTORY.txt/1.6/Wed May 10 21:22:37 2006// +/Makefile/1.2/Thu Aug 11 23:11:26 2005// +/README.txt/1.13/Sun Jul 22 23:26:03 2007// +/erball.el/1.33/Mon Aug 21 18:33:01 2006// +/erbbdb.el/1.9/Fri Nov 23 16:31:58 2007// +/erbc-backquote.el/1.1/Fri Aug 20 18:55:04 2004// +/erbc.el/1.131/Sat Sep 26 21:26:39 2009// +/erbc2.el/1.26/Fri Nov 23 16:31:58 2007// +/erbc3.el/1.30/Fri Nov 23 16:31:58 2007// +/erbc4.el/1.39/Fri Nov 23 16:31:58 2007// +/erbc5.el/1.19/Fri Nov 23 16:31:59 2007// +/erbc6.el/1.11/Fri Nov 23 16:31:59 2007// +/erbcompat.el/1.7/Fri Nov 23 16:31:59 2007// +/erbcountry.el/1.3/Wed Apr 6 16:49:49 2005// +/erbcspecial.el/1.9/Fri Nov 23 16:31:59 2007// +/erbdata.el/1.5/Fri Nov 23 16:31:59 2007// +/erbedit.el/1.6/Fri Nov 23 16:31:59 2007// +/erbeng.el/1.18/Fri Nov 23 16:31:59 2007// +/erbforget.el/1.12/Fri Nov 23 16:31:59 2007// +/erbim.el/1.7/Wed Apr 11 11:59:27 2007// +/erbjavadoc.el/1.8/Fri Nov 23 16:31:59 2007// +/erbkarma.el/1.8/Fri Nov 23 16:31:59 2007// +/erblisp.el/1.17/Fri Nov 23 16:31:59 2007// +/erblog.el/1.6/Fri Nov 23 16:31:59 2007// +/erbmerge.el/1.3/Fri Nov 23 16:31:59 2007// +/erbmsg.el/1.26/Fri Nov 23 16:31:59 2007// +/erbot-lispy.el/1.7/Thu Apr 20 18:34:04 2006// +/erbot.el/1.61/Wed Sep 30 23:33:47 2009// +/erbp.el/1.4/Fri Nov 23 16:31:59 2007// +/erbrss.el/1.4/Sat Jan 1 16:31:21 2005// +/erbtrain.el/1.19/Fri Nov 23 16:31:59 2007// +/erbtranslate.el/1.24/Sat Sep 26 21:35:47 2009// +/erbunlisp.el/1.6/Fri Nov 23 16:31:59 2007// +/erburl.el/1.5/Fri Nov 23 16:31:59 2007// +/erbutils.el/1.34/Sat Sep 26 21:16:33 2009// +/erbwiki.el/1.23/Fri Nov 23 16:31:59 2007// +D diff --git a/elisp/erbot/CVS/Entries.Log b/elisp/erbot/CVS/Entries.Log new file mode 100644 index 0000000..4201a0f --- /dev/null +++ b/elisp/erbot/CVS/Entries.Log @@ -0,0 +1,2 @@ +A D/contrib//// +A D/examples//// diff --git a/elisp/erbot/CVS/Repository b/elisp/erbot/CVS/Repository new file mode 100644 index 0000000..3bfa306 --- /dev/null +++ b/elisp/erbot/CVS/Repository @@ -0,0 +1 @@ +erbot diff --git a/elisp/erbot/CVS/Root b/elisp/erbot/CVS/Root new file mode 100644 index 0000000..efd54f4 --- /dev/null +++ b/elisp/erbot/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.savannah.nongnu.org:/sources/erbot diff --git a/elisp/erbot/CVS/Template b/elisp/erbot/CVS/Template new file mode 100644 index 0000000..e69de29 diff --git a/elisp/erbot/ChangeLog b/elisp/erbot/ChangeLog new file mode 100644 index 0000000..0af41f3 --- /dev/null +++ b/elisp/erbot/ChangeLog @@ -0,0 +1,484 @@ +2007-12-06 D. Goel + + * erbc.el (fsi-replace-regexp): fix call to `error'. + (fsi-merge-generic): Ditto. + (fsi-mv): " + (fsi-replace-string): " + and many other functions and files: Ditto. + +2007-11-23 Dave Goel + + * COPYING: Replace by GPL v. 3 + + * erbot.el and all other files: Change GPL v. 2 to 3. + +2007-07-22 Michael Olson + + * README.txt: Mention examples/dotemacs-mybot. + + * examples/dotemacs-mybot: New file that is the example .emacs for + the bot. + +2007-07-19 Michael Olson + + * erbot.el (erbot-reply): Don't force the message through without + flood protection. Since ERC 5.1, ERC has very good flood + protection, so make use of it. + +2007-04-11 Vivek Dasmohapatra + + * erbim.el (fs-unicode-describe): add usage instructions + (erbim-search-by-description): search for unicode characters by + description. + (fs-unicode-find): bot-ui wrapper for erbim-search-by-description + including usage message. + (erbim-name-by-codepoint): changed output format to use #xXXX + +2007-01-28 Vivek Dasmohapatra + + * erbot.el (erbot-join-servers): `erc' takes :keyword style + parameters in emacs22, the old argument list no longer works. + Work out which erc version we're using and alter the call + appropriately. + +2007-01-27 Vivek Dasmohapatra + + * erbutils.el (erbutils-describe-variable): help-button-xref + has changed in emacs22, make this function work with it. + +2006-11-28 Michael Olson + + * erbot.el (erbot-join-servers): Make this work with the ERC + development branch. + +2006-09-28 D Goel + + * erbc.el (fsi-describe-from-english): smarter self search + (fsi-generalize-search-term): new, for above. + +2006-08-21 Michael Olson + + * erbot.el (erbot-install): Remove check for erc-backend-version, + since it no longer exists. Use featurep instead. This fixes a + failure to join channels issue with the ERC development branch. + +2006-05-18 Vivek Dasmohapatra + + * erbtranslate.el (fsi-translate): If we can't make sense + of the call (not enough arguments) emit a usage message. + +2006-05-17 Michael Olson + + * contrib/translate.el (translate-load-pairs): Docfix. + + * erbtranslate.el (fsi-translate-list-services): Use + translate-program, not erbn-translate-program, since the latter + does not exist. + +2006-05-12 Vivek Dasmohapatra + + * contrib/translate.el: the symbol -> string coercion is not + required for arguments to translate.el, that's something + specific to user-visible erbot functions. + + * erbtranslate.el: most translation code moved to translate.el + fsi-translate-web-page temporarily disabled till I've tested + it a bit more and made the implementation a little smarter + than it currently is. (It should check ti see if a web page + service is actualy available) + +2006-05-10 D Goel + + * erbtranslate.el: update authors + +2006-05-10 Vivek Dasmohapatra + + * erbtranslate.el (fsi-translate-list-pairs): destination language + should also be searched for with a case insensitive predicate. + +2006-05-09 D Goel + + * erbtranslate.el: update authors + +2006-05-09 Vivek Dasmohapatra + + * erbtranslate.el (fsi-translate-list-pairs): improved help, return + more information when < N pairs, where N is currently 20. (Always + return full list if both origin and destination are both supplied) + (erbtranslate-full-name): returns a "full name" for a language, + consisting of all its human-readable aliases. + (erbtranslate-unsupported-langs): list of languages emacs can't utf-8 + encode yet. + (fsi-translate): abort for non-unicodable languages like Arabic and + Hebrew. + (fsi-translate): Use full names of languages in error messages. + (fsi-translate-list-pairs): Use full names of languages in messages. + +2006-05-08 Vivek Dasmohapatra + + * erbtranslate.el (erbtranslate-parse-pair): parse the output of + erbn-translate-program --list-pairs. + (erbtranslate-load-pairs): load the map of available translations. + (fsi-translate-list-pairs): Alter this function so that it only lists + possible translations when both an origin and a destination language + have been specified. Otherwise just tells the user how many matching + language pairs there are. + (fsi-translate-list-pairs): coerce the arguments into strings first. + (erbtranslate-parse-pair): some (one?) language codes are 3 letter. + I thought this was non-canonical but that's what translate returns, + so we must support it. + (erbtranslate-parse-pair): tidy up error message + (erbtranslate-req-to-pair): new. take the (possibly non-canonical) + language names from the user and map them to the canonical language + codes that translate expects. + (fsi-translate): map human-friendly language names in translation + request to canonical language codes. + (fsi-translate): use the coerced-strings, not the raw language args. + +2006-05-08 D Goel + + * erbtranslate.el (erbn-translate-program): new. Make the program customizeable. + + + * contrib/shs.el: New shs.el, cleans up temporary files. + +2006-04-24 D Goel + + * erbtranslate.el: DECLARE SAFE. Uses call-process now. + + * erball.el: require erbtranslate. + + * erbutils.el (erbutils-enabled-check): new function. + + * erbtranslate.el: revamp the file to make it secure, not yet final. + +2006-04-20 D Goel + + * erbot.el (erbot-safe-p): Improve this function a bit. + (erbot-safe-nocontrol-p): new. + + * erbot-lispy.el (erbot-lispy-safe-p): change name from erbot-lispy-safep + + * erbot.el (erbot-safe-p): change name from erbot-safep + + * erbc.el (erbn-url-functions-p): new variable. Disallow url's + unless enabled here. Else potential freeze. + (erbn-internal-web-page-time): rename from the one below. + (fs-internal-web-page-time): rename to the one above + (erbn-url-functions-p): add bug discoverer's name in docstring. + (fsi-get-more-invocation-string): new function. + (fsi-limit-lines): Make the bot spit something useful instead of + ,more, when using weird erbn-char. + +2006-04-19 D Goel + + * erbtranslate.el: fix minor doc typo + +2006-04-17 D Goel + + * erbtranslate.el: adapted from indio's myerc.el. Work in + progress. INSECURE. DO NOT USE THIS FILE. + +2006-04-07 D Goel + + * erbot.el (erbot-safe-make): Exception to control characters: + Allow \t + +2006-03-21 D Goel + + * erbot.el (erbot-safe-make): new function. + (erbot-reply): call erbot-safe-make before replying. + +2006-02-28 Michael Olson + + * ChangeLog: Remove use of CVS Revision tag. + +2006-02-27 D Goel + + * erbc2.el (fs-apply): SECURITY FIX! Also, disable when + paranoid. Ditto for funcall. + + * erbot.el (erbot-paranoid-p): Make this new variable a catchall + for security. t by default. No enablings like erbot-setf-p, + etc. will work unless this is non-nil. If this is non-nil, erbot + is paranoid, it will not allow apply, setf, funcall, sregex, + etc. even if the corresponding variables are turned on. + +2006-02-26 Michael Olson + + * erbc.el (fs-flame): Concat multiple arguments together to form + the flame target, unless there are only 2 arguments and the last + one is a number. In that case, we pick the specified flame. + +2006-01-10 D Goel + + * erbc5.el (symbol-name): minor: provide this fs-function. + + +2006-01-05 Michael Olson + + * README.txt (NOTE): Add directions for getting the units file for + contrib/units.el. + + * contrib/units.el: Newly-added file that is recommended on the + ErbotInstallation page of emacswiki.org. + + +2006-01-01 D Goel + + * erblisp.el (erblisp-check-args): Promote to a macro. This macro + first removes any arguments that can't be evalled. This happens, + when, for example, the user-defined function contained &optional, + &rest, etc. + + * erbot.el (erbot-remote): erc-coding-system-for-target was not + defined for older versions of erc. + +2005-12-31 Vivek Dasmohapatra + + * erbmsg.el (fs-memo): if a memo command was not recognised, + emit an error so we know it happened. + (fs-memos): If someone had no memos, return the help-memo + text too - makes it easier for people to figure out how it + all works. + +2005-12-30 Vivek Dasmohapatra + + * erbot.el (erbot-remote): Decode the incoming data properly + paying attention to erc's inbound coding system. + (erbot-reply): Now that the inbound data is (hopefully) cleanly + decoded we shouldn't need to force the outbound coding. + In emacs21, mule-ucs may be required for this to work. + +2005-11-10 D Goel + + * erbot.el (erbot-safep): Make a minor change, to try to render + this function live up to its name: make it deem any newlines + unsafe. Because of the way the engine works, this change has no + effect on erbot at this time. + (erbot-safep): minor correction to last change. + +2005-11-09 Michael Olson + + * erbot.el (erbot-reply): Make erbot-safep check each line of the + split reply. Split the string on both \n and \r. Together, this + fixes an exploit in user-defined functions, which involved + returning a string like "^Mquit". + +2005-11-08 Michael Olson + + * erblisp.el (erblisp-max-list-length): New option that determines + how long a sand-boxed list or expression may be. + (erblisp-safe-length): New function that checks the given list to + make sure it isn't too long. It's able to handle nested lists as + well. + (erblisp-check-args): New function that calls erblisp-safe-length + with the correct args. + (erblisp-sandbox): Use erblisp-check-args. + + * erbc3.el (fsi-defun): Add erblisp-check-args invocation to each + newly-created user function. + +2005-10-12 Michael Olson + + * erbot.el (erbot-join-servers): Use fboundp check; + erc-compute-port is a function. + +2005-10-05 D Goel + + * erbot.el (erbot-join-servers): `erc-compute-port' seems to be + undefined for my older ERC (4.0). So, I + reverted to old behavior when it is undefined. Did I do it right? + +2005-10-05 Michael Olson + + * erbot.el (erbot-join-servers): Call `erc-compute-port' instead + of using the value of `erc-port', since by default erc-port is + nil. + +2005-09-02 D Goel + + * .*.el: Get rid of all string properties everywhere, especially + right at the source, for extra security. + + * erbc.el (fsi-read): minor: read-> read-from-string for more + safety + (erbn-read): new + (fsi-read-from-string): new + (fsi-describe-variable): use erbn-read for safety + (fsi-require): ditto + + * erbbdb.el (erbbdb-add): ditto + +2005-08-31 D Goel + + * erbot.el (erbot-nickserv-p): Add auto-identify code, also enable + by default, see doc for erbot-nickserv-p for how to make changes + to your bot's .emacs. This is now required by freenode for + privmsgs to work. + (erbot-nickserv-p): Unde default behavior change. The default + behavior of erbot remains as xbefore: to *not*idontify by + default. + +2005-08-28 Michael Olson + + * contrib/wtf.el: Add to copyright notice. + (wtf-alist): Move FTBFS to the "Additional terms go here" section. + +2005-08-22 Jose E. Marchesi + + * contrib/haiku.el (fs-haiku): New file + +2005-08-16 D Goel + + * contrib/wtf.el (wtf-alist): add ("FTBFS" . "failure to build from source") + +2005-08-15 Michael Olson + + * contrib/wtf.el: I received permission to receive these terms in + the public domain. + (wtf-alist): Add "TWAT". + (wtf-is): Fix Emacs21 issue. + +2005-08-11 Michael Olson + + * contrib/wtf.el (wtf-match-string-no-properties): New function + that is like match-string-no-properties, but works when that + function is not defined. + (wtf-get-term-at-point): New function that looks for term at + point. + (wtf-is): Make use of `wtf-get-term-at-point'. + + * Makefile (clean realclean distclean fullclean): Remove *~ files + in contrib directory. + +2005-07-09 Michael Olson + + * erball.el: Make sure that the user knows if bbdb cannot be + found. Otherwise they will get a non-working bot! + (erball-compilation-paths): Add path to BBDB. + +2005-07-02 Michael Olson + + * erball.el (erball-compiling-p): Use a custom routine instead of + `assoc' to detect "--compile-erbot" since the latter does not seem + to work on Emacs 22. + +2005-07-01 Michael Olson + + * erball.el (erball-compilation-paths-rel-to): New variable + populated by `--paths-rel-to ARG' on the emacs command line, + taking the value of ARG. + (erball-compiling-p): New variable that is non-nil when + `--compile-erbot' is included on the emacs command line. This is + used to indicate that we want to compile erbot from a Makefile. + (erball-compilation-paths): Elements to add to load-path when the + compilation flag, erball-compiling-p, is set. + (erball-files): Automatically populate this if erball-compiling-p + is set. + (erball-compile): If erball-compiling-p is set, use a simpler + routine. + + * Makefile: New file that allows erbot to be compiled and + installed. Edit the top of the file to indicate where to find + emacs and where to install the files. + + * README.txt (URL): Add brief mention of how to compile and + install erbot. + +2005-06-09 Michael Olson + + * contrib/wtf.el: New file that contains a list of acronyms in + `wtf-alist' and the `wtf-is' command to look up a definition. + + * erbtrain.el (erbtrain-utils-teach-acronyms): Use `wtf.el' to + teach the given bot some common acronyms. + +2005-04-28 D Goel + + * erbc3.el (fsi-pf-load): Make this error msg more informative. + + * erbc5.el (fsi-ignore-errors-else-string): new. + +2005-04-01 D Goel + + * erbc4.el (fsi-kick): Move from erbc.el to here. + + +2005-04-01 Michael Olson + + * erbot.el (erbot-doctor): Create separate doctor sessions for + each channel or query buffer so that responses make sense to the + user. + +2005-02-21 S Freundt + + * erbmsg.el: (erbmsg-notify-msg-on-JOIN) [fix] add function set-alist for + compatibility to FSF emacsen + +2004-07-26 S Freundt + + * erbmsg.el: (erbmsg-notify-msg-on-JOIN) + - fixed bug with last-access used for the first time + +2004-06-26 S Freundt + + * erbmsg.el: + - added dump routines to dump message hash tables to hard disk + - added routines for restoring from dumped message files + - added interval within erbot does not notify on channel joins + - added erbmsg-new-msg-(pre|post)-hook + +2004-06-13 S Freundt + + * erbot.el: added new var erbot-on-new-erc-p + and handlers for new erc-backend facilities. + + erc versions >1.660 use erc-backend.el to handle server + events. erbot is now aware of these new handlers by + determining the value `erbot-on-new-erc-p' when calling + `erbot-install'. + The new backend handlers' values are evaluated within + `erbot-remote' fun. + +2004-05-07 D Goel + + * erbwiki.el: Security, add new functions. + + USING LINES < 0.3 FOR WIKI TRAINING WAS A SECURITY RISK, WE + THINK.. THOUGH WE HAVEN'T FIGURED OUT HOW TO EXPLOIT IT. + lines 0.3 and later fix that risk. + + Also add new functions to erbwiki.el suitable for parsing more + wikis. + + +2004-04-06 D Goel + + * erbc.el (fs-kick): Kicking syntax different? remove nil? + +2004-03-28 D Goel + + * erbcompat.el: name Sebastian as the author :) + + * erbwiki.el (erbwiki-get-fields): remove '... since not + recognized by xemacs + +2004-03-22 D Goel + + * erball.el (noninteractive): dunnet should be required only for + noninteractive, else it starts a session! + +2004-03-21 D Goel + + * erbc3.el: Redefine and move fs-setq here. + (fs-defun): This function was defined twice. Remove the first + definition. + + * erbc.el (fs-find-variable-internal): add cosmetic space. + (obarray): redefine and mv fs-setq to erbc3 + +2003-12-30 D Goel + + * erbc.el (reverse): add fs-reverse + diff --git a/elisp/erbot/HISTORY.txt b/elisp/erbot/HISTORY.txt new file mode 100644 index 0000000..079bb72 --- /dev/null +++ b/elisp/erbot/HISTORY.txt @@ -0,0 +1,55 @@ +;; 2006-04-24 T14:02:53-0400 (Monday) D. Goel +Alejandro Benitez , fledermaus and deego +provide natural language translation. + +;; 2005-12-31 T04:34:34-0500 (Saturday) D. Goel +Vivek Dasmohapatra fixes/fixing coding issues. + +;; 2005-08-11 T19:49:47-0400 (Thursday) D. Goel + +Michael Olson creates a Makefile, thus, for the first time, making the +notion of erbot becoming an installable package, look possible.. + + +;; 2005-06-04 T15:04:23-0400 (Saturday) D. Goel +Michael Olson provides function to train acronyms: + +M-x load-file ~/emacs-wiki-wtf.el + +M-: +(setq erbtrain-list + (mapcar (lambda (ref) + (concat "plugbot: " (car ref) + " is " (upcase-initials (cdr ref)))) + emacs-wiki-wtf-alist)) + +M-x erbtrain-resume +M-x idledo-start + + +or see M-x erbtrain-utils-teach-acronyms + +;;; 2005-06-04 T15:05:15-0400 (Saturday) D. Goel +Previous history here: +Summary in reverse order, IIRC: + + + + +erbot-lispy + +erc-robot (David Edmunston)-> erbot, + +==================================================== + +The idea for rr (russian roulette) came from e1f. + +The idea for answering questions not addressed to fsbot, like "foo?" +came from resolve. + +The idea for invoking the bot in the middle of sentences came from +resolve. + + + + diff --git a/elisp/erbot/Makefile b/elisp/erbot/Makefile new file mode 100644 index 0000000..e98e2d0 --- /dev/null +++ b/elisp/erbot/Makefile @@ -0,0 +1,40 @@ +.PHONY: all lisp contrib clean realclean distclean fullclean install dist +.PRECIOUS: %.elc + +EMACS = emacs +SITEFLAG = --no-site-file + +# Xemacs users will probably want the following settings. +#EMACS = xemacs +#SITEFLAG = -no-site-file + +# Installation options +# PREFIX is only used here. +PREFIX = /usr/local +ELISPDIR = $(PREFIX)/share/emacs/site-lisp/erbot + +all: lisp contrib + +lisp: + @$(EMACS) -q $(SITEFLAG) -batch --debug-init \ + -l erball.el \ + -f erball-compile --compile-erbot + +contrib: + @(cd contrib && \ + $(EMACS) -q $(SITEFLAG) -batch \ + -l ../erball.el \ + -f erball-compile \ + --paths-rel-to '../' --compile-erbot) + +clean realclean distclean fullclean: + -rm -f *.elc contrib/*.elc *~ contrib/*~ + +install: + install -d $(ELISPDIR) + install -m 0644 *.el *.elc $(ELISPDIR) + install -d $(ELISPDIR)/contrib + install -m 0644 contrib/*.el contrib/*.elc $(ELISPDIR)/contrib + +dist: distclean + (cd ..; tar cvzf ../erbot.tar.gz erbot) diff --git a/elisp/erbot/README.txt b/elisp/erbot/README.txt new file mode 100644 index 0000000..1d2540f --- /dev/null +++ b/elisp/erbot/README.txt @@ -0,0 +1,90 @@ +URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot for all erbot +information, and installation help. + + + +The files in the `contrib' directory are optional "third-party" +add-ons that are used for erbot. Not all of them are strictly +required. The versions here are provided for convenience, and are +also the versions known to work with erbot, but you might want to +fetch their latest versions from their respective authors' websites. + +The file `examples/dotemacs-mybot' is meant to be the bot's .emacs +file. Copy it to .emacs in your bot's home directory, and then make +any changes you like. + +NOTE: A data file for contrib/units.el may be obtained in Debian by +performing "apt-get install units", and adding + (setq units-dat-file "/usr/share/misc/units.dat") +to the bot's .emacs. + +To compile the erbot source, edit Makefile and run "make". To install +it, edit Makefile and run "make install". + + +==================================================== + +For developers: + + +Namespaces used by these files: fs-, fs.*-, erb.*- + + + +Next, we attempt to describe the various abbreviations and terms used +in this package. + + ++---------+------------------------------------------------------------+ +|botbbdb |Name of the bbdb database file used by the bots. | ++---------+------------------------------------------------------------+ +|erb |ErBot stands for erc robot, and started out from | +| |erc-robot.el. We named the new file erbot, and most | +| |namespaces start with erb. | ++---------+------------------------------------------------------------+ +| | | ++---------+------------------------------------------------------------+ +|erbc- |This referred to erbot-comands. Functions starting with this| +| |name were availabel to public to frob as they like. Same | +| |for variables. This was replaced by fs- | ++---------+------------------------------------------------------------+ +|erbnoc- |This is like erbc-, except that these commands are NOT | +| |available to the general public (at this time). This one is| +| |still in use, unlike fs-. These functions are NOT | +| |world-executable or world-writable, but are maintained | +| |alognside erbc- functions .. erbnoc meansd: erb - | +| |no-commands... We have now shortened it to erbn- | ++---------+------------------------------------------------------------+ +|erbn- |Shortening of erbnoc- | ++---------+------------------------------------------------------------+ +|fs- |fsbot is a popular instance of erbot. At some point, all | +| |erbc- prefixes were replaced by fs- for easier read. Thus, | +| |to reiterate, these functions are world-readable, weritable | +| |writable and executable. (The only exeptions are those that| +| |are internally converted from fsi-, which are converted to | +| |fs- with a special disabled property.) Summary: rwx for irc| +| |users. | ++---------+------------------------------------------------------------+ +|fsi- |Like fs- but these functions and variables are only | +| |world-readable and world-executable, but NOT world-writable.| +| |The "i" stands for immutable (or is it "internal"?). These | +| |functions are internally converted to fs- functionserbot | +| |usage through erbot-install-symbols. Summary: r-x for irc | +| |users. | ++---------+------------------------------------------------------------+ +|fsn- |This "fs NOT" would be the logical "---" counterpart for the| +| |fs.* prefixes above, butits similarity to fs will make | +| |reading difficult, so we stick with erbn- | ++---------+------------------------------------------------------------+ +|All other|.. are also ---, and the only difference from erbn- is | +|prefixes |aesthetical. | +| | | ++---------+------------------------------------------------------------+ +|fsbot | "Free software bot", an instance of fsbot. | ++---------+------------------------------------------------------------+ +| | | +| | | +| | | +| | | +| | | ++---------+------------------------------------------------------------+ diff --git a/elisp/erbot/contrib/CVS/Entries b/elisp/erbot/contrib/CVS/Entries new file mode 100644 index 0000000..0421465 --- /dev/null +++ b/elisp/erbot/contrib/CVS/Entries @@ -0,0 +1,20 @@ +/META-feeding-info-terms.el/1.2/Tue Jan 3 03:40:18 2006// +/README.txt/1.1/Mon May 8 04:11:26 2006// +/bash-quotes.el/1.2/Wed Sep 30 22:23:04 2009// +/faith.el/1.1/Thu Dec 16 01:44:34 2004// +/flame.el/1.1/Thu Dec 16 01:44:34 2004// +/geek.el/1.1/Thu Dec 16 01:44:34 2004// +/google.el/1.2/Wed Sep 30 22:23:04 2009// +/h4x0r.el/1.2/Wed Sep 30 22:23:04 2009// +/haiku.el/1.2/Wed Sep 30 22:23:04 2009// +/idledo.el/1.2/Wed Sep 30 22:23:04 2009// +/lines.el/1.1/Thu Dec 16 01:44:34 2004// +/mkback.el/1.2/Wed Sep 30 22:23:04 2009// +/oct.el/1.2/Wed Sep 30 22:23:04 2009// +/shs.el/1.3/Wed Sep 30 22:23:04 2009// +/soap.el/1.2/Wed Sep 30 22:23:04 2009// +/timerfunctions.el/1.2/Wed Sep 30 22:23:04 2009// +/translate.el/1.7/Wed Sep 30 22:23:04 2009// +/units.el/1.1/Thu Jan 5 18:52:02 2006// +/wtf.el/1.20/Wed Sep 30 22:23:04 2009// +D diff --git a/elisp/erbot/contrib/CVS/Repository b/elisp/erbot/contrib/CVS/Repository new file mode 100644 index 0000000..825b403 --- /dev/null +++ b/elisp/erbot/contrib/CVS/Repository @@ -0,0 +1 @@ +erbot/contrib diff --git a/elisp/erbot/contrib/CVS/Root b/elisp/erbot/contrib/CVS/Root new file mode 100644 index 0000000..efd54f4 --- /dev/null +++ b/elisp/erbot/contrib/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.savannah.nongnu.org:/sources/erbot diff --git a/elisp/erbot/contrib/CVS/Template b/elisp/erbot/contrib/CVS/Template new file mode 100644 index 0000000..e69de29 diff --git a/elisp/erbot/contrib/META-feeding-info-terms.el b/elisp/erbot/contrib/META-feeding-info-terms.el new file mode 100644 index 0000000..df5584a --- /dev/null +++ b/elisp/erbot/contrib/META-feeding-info-terms.el @@ -0,0 +1,73 @@ +;; this helps prepare an erbtrain file from +;; http://www.emacswiki.org/emacs/info-ref.dat, see also +;; http://www.emacswiki.org/cgi-bin/wiki/EmacsWikiSuggestions +;; or google for emacswiki info ref for pertinent discussions. + +;; Author Alex Shroeder + +;; received from kensanata: +(defun meta-feeding-info-k () + (let (data (lines 0)) + (with-current-buffer (get-buffer "info-ref.dat") + (message "Parsing buffer...") + (goto-char (point-min)) + (while (re-search-forward "^\\(.*\\)\\(.*\\)" nil t) + (let ((term (match-string 1)) + (rest (match-string 2))) + (setq term (replace-regexp-in-string " " "_" term) + lines (1+ lines) + data (cons (cons term + (mapcar + (lambda (entry) + (car (split-string entry ""))) + (split-string rest ""))) + data))))) + (switch-to-buffer (get-buffer-create "info-ref-botsnack")) + (let ((count 0)) + (dolist (entry data) + (message "Preparing botsnack...%d%%" (/ (* 100 count) lines)) + (insert (format "%s is at %s" (car entry) (cadr entry))) + (newline) + (dolist (url (cddr entry)) + (insert (format "%s is also at %s" (car entry) url)) + (newline)))) + (message "Preparing botsnack...done"))) + +;;; 2006-01-02 T22:04:08-0500 (Monday) D. Goel +;; minor modifications to the above: +(defun meta-feeding-info-d () + (interactive) + (let (data (lines 0)) + (with-current-buffer (get-buffer "info-ref.dat") + (message "Parsing buffer...") + (goto-char (point-min)) + (while (re-search-forward "^\\(.*\\)\\(.*\\)" nil t) + (let ((term (match-string 1)) + (rest (match-string 2))) + (set-text-properties 0 (length term) nil term) + (set-text-properties 0 (length rest) nil rest) + (setq term (replace-regexp-in-string " " "_" term) + lines (1+ lines) + data (cons (cons term + (mapcar + (lambda (entry) + (car (split-string entry ""))) + (split-string rest ""))) + data))))) + (switch-to-buffer (get-buffer-create "info-ref-botsnack")) + (let ((count 0) attmp) + (dolist (entry data) + (setq attmp (format "at %s" (cadr entry))) + (message "Preparing botsnack...%d%%" (/ (* 100 count) lines)) + (insert (format "fsbot: (set-term %S %S)" (car entry) attmp)) + (newline) + (insert (format "fsbot: (set-also %S %S)" (car entry) attmp)) + (newline) + + (dolist (url (cddr entry)) + (insert (format "fsbot: (set-also %S %S)" (car entry) + (format "at %s" url)))) + (newline))) + (message "Preparing botsnack...done"))) + + diff --git a/elisp/erbot/contrib/README.txt b/elisp/erbot/contrib/README.txt new file mode 100644 index 0000000..913d2fa --- /dev/null +++ b/elisp/erbot/contrib/README.txt @@ -0,0 +1,7 @@ +;; 2006-05-08 T00:08:11-0400 (Monday) D. Goel + +Files in this directory are usually included here for user's +convenience, but may be developed elsewhere by their authors. Thus, +these files may not neccessarily their latest versions. + + diff --git a/elisp/erbot/contrib/bash-quotes.el b/elisp/erbot/contrib/bash-quotes.el new file mode 100644 index 0000000..a2ea28e --- /dev/null +++ b/elisp/erbot/contrib/bash-quotes.el @@ -0,0 +1,337 @@ +;;; bash.el --- bash.org interface + +;; Copyright (C) 2003 Free Software Foundation, Inc. + +;; Author: Ulrik Jensen +;; Keywords: HTTP, bash, searching +;; Time-stamp: <2003-04-14 17:08:55 Administrator> +;; Version: 0.1 alpha :) + +;; This file 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 3, or (at your option) +;; any later version. + +;; This file 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 GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; An interface for reading bash.org with Emacs +;; Requires http-get 1.0.8: +;; + +;;; Code: + +(require 'http-get) + +;; URL's, for use later in the script +(defvar bash-get-quote-url "http://www.bash.org/?%id%" + "The URL to fetch to get a specific quote. + + %id% will be replaced with the specific id") + +(defvar bash-search-quotes-url + "http://bash.org/?search=%criteria%&sort=%sort%&show=%number%" + "The URL to search bash.org for quotes. + + %number% will be replaced with the max number of results + %sort% will be replaced with 1 or 2, with 1=id, and 2=rating +%criteria% will be replaced with the words to search for") + +(defvar bash-get-latest-url "http://www.bash.org/?latest" + "The URL to fetch to get the latest quotes from bash.org.") + +(defvar bash-get-top-rated-url "http://www.bash.org/?top" + "The URL to fetch to get the top 50 quotes from bash.org.") + +(defvar bash-get-next-top-rated-url "http://www.bash.org/?top2" + "The URL to fetch to get the top 50-100 quotes from bash.org.") + +(defvar bash-get-random-url "http://www.bash.org/?random" + "The URL to fetch to get 30 random quotes from bash.org.") + +(defvar bash-get-random-above-zero-url + "http://www.bash.org/?random2" + "The URL to fetch to get 30 random quotes, with rating > 0 from bash.org") + +;; Variable for holding the title of the requested page +(defvar bash-tmp-results-title "Search" + "A temporary variable that stores a title to insert in all *bash*-buffers") + +;; Buffer names +(defvar bash-buffer "*bash*" + "Name of the buffer used to read bash.org quotes in") + +(defvar bash-temp-buffer "*bash-tmp*" + "Name of the temporary buffer used to fetch and parse bash.org results") + +;; Regexps for parsing the html-output of bash.org +(defvar bash-mysql-down-regexp "

    .*Sorry.*MySQL.*down" + "A regular expression used to check if bash.org's mysql deamon +is down, as often is the case.") + +(defvar bash-quote-regexp + "

    \\(.*?\\)

    \\(.*?\\)

    " + "A regular expression used to parse the html-source of bash.org outputs. + +The first group is data about the quote, links, id, and votes. +The second group is the quote itself") + +(defvar bash-quote-data-regexp + (concat "" + "(\\(-?[0-9]*\\))]*>" "" quote)) + (curquote (replace-regexp-in-string "<" "<" curquote)) + (curquote (replace-regexp-in-string ">" ">" curquote)) + (curquote (replace-regexp-in-string "
    " "\n" curquote)) + (curquote (replace-regexp-in-string """ "\"" curquote)) + (curquote (replace-regexp-in-string " " " " curquote)) + (curquote (replace-regexp-in-string "&" "&" curquote))) + ;; Below is the visual output + (insert "Quote ") + (widget-create 'push-button + :notify `(lambda (&rest ignore) + (bash-specific-quote ,quoteid)) + (concat "#" quoteid)) + (insert " ") + (widget-create 'push-button + :notify `(lambda (&rest ignore) + (bash-process-request (concat "http://www.bash.org/?" ,uplink) "add a positive vote to " ,quoteid)) + "+") + (insert " (" votes ") ") + (widget-create 'push-button + :notify `(lambda (&rest ignore) + (bash-process-request (concat "http://www.bash.org/?" ,downlink) "add a negative vote to " ,quoteid)) + "-") + (insert " ") + (widget-create 'push-button + :notify `(lambda (&rest ignore) + (bash-process-request (concat "http://www.bash.org/?" ,flag) "flag " ,quoteid)) + "X") + (insert " ") + (widget-create 'push-button + :notify `(lambda (&rest ignore) + (bash-save-quote ,curquote ,quoteid)) + "Save quote") + (insert "\n" + "--------------------------------------------------------------------------------" + "\n" curquote "\n" + "--------------------------------------------------------------------------------" + "\n\n"))) + +(defun bash-parse (buffer) + "Parses the results from bash.org, in the bash-temp buffer, and adds them to BUFFER" + (set-buffer (get-buffer-create bash-temp-buffer)) + (let* ((buftext (buffer-substring (point-min) (point-max))) + (buftext (replace-regexp-in-string "\n" "" buftext)) + (buftext (replace-regexp-in-string " ?" "\n" buftext)) + (buftext (replace-regexp-in-string " " "" buftext))) + (set-buffer buffer) + (insert "\n\n") + (cond + ;; If there are actually quotes in the output + ((string-match bash-quote-regexp buftext) + (while (string-match bash-quote-regexp buftext) + (let ((curdata (match-string 1 buftext)) + (curquote (match-string 2 buftext)) + (quotestart (string-match bash-quote-regexp buftext))) + (when curquote ; just a precaution.. shouldn't be necessary + (bash-parse-single-quote curquote curdata) + ;; delete the quote from the string, actually. this is a few chars + ;; short every time.. hope it doesn't matter though + (setq buftext (substring buftext (+ (length curquote) (length curdata) quotestart) nil)) + (setq quote-count (+ quote-count 1)))))) + ;; If the output tells us that the mysql-deamon is down + ((string-match bash-mysql-down-regexp buftext) + (insert "Bash.org's MySQL-deamon seems to be down at the moment.")) + ;; If none of the above, panic + (t + (insert "No results!"))))) + +(defun bash-insert-menubar () + "Inserts a widget-based menubar for navigating bash.org" + (widget-create 'push-button + :notify (lambda (&rest ignore) + (bash-random-30-quotes)) + "Random") + (insert " ") + (widget-create 'push-button + :notify (lambda (&rest ignore) + (bash-random-above-zero-quotes)) + "> 0") + (insert " Top ") + (widget-create 'push-button + :notify (lambda (&rest ignore) + (bash-top-50-quotes)) + "50") + (insert " ") + (widget-create 'push-button + :notify (lambda (&rest ignore) + (bash-top-50-100-quotes)) + "-100") + (insert " ") + (widget-create 'push-button + :notify (lambda (&rest ignore) + (bash-latest-quotes)) + "Latest") + (insert " ") + (widget-create 'push-button :notify (lambda (&rest ignore) (bury-buffer)) "Bury buffer") + (insert "\n" + "--------------------------------------------------------------------------------")) + +(defun bash-sentinel (process string) + "Sentinel for processing bash-results" + (kill-buffer (get-buffer-create bash-buffer)) + (let ((buffer (get-buffer-create bash-buffer))) + (set-buffer buffer) + (erase-buffer) + (goto-char 0) + (bash-insert-menubar) + (insert "\nBash Results - " bash-tmp-results-title "\n") + (let ((quote-count 0)) + (bash-parse buffer) + (insert "\n\n " (number-to-string quote-count) " quotes showed.")) + (pop-to-buffer buffer) + ;; Setup widget-minor-mode + ;; should always be called before setting a new major mode + ;; apparently also needs to be called before widget-minor-mode + (kill-all-local-variables) + (widget-minor-mode 1) + (widget-setup) + ;; Make the buffer read-only, no need to edit it + (setq buffer-read-only t) + ;; Bind some keys + (local-set-key "q" '(lambda() (interactive) (bash-cleanup-buffers))) + ;; (local-set-key "n" 'bash-next-quote) + ;; scroll to the top + (goto-char 0) + (kill-buffer (get-buffer-create bash-temp-buffer)))) + +;; For these to work, I might have to use http-1.1 +(defun bash-request-sentinel (process string) + "Sentinel for processing bash-results" + (let ((buffer (get-buffer-create bash-temp-buffer))) + (save-excursion + (set-buffer buffer) + ;; Check the result of the request, and message it + ;; (kill-buffer (get-buffer-create bash-temp-buffer)) + ))) + +(defun bash-cleanup-buffers () + "Removes all bash-related buffers" + (kill-buffer (get-buffer-create bash-buffer)) + (kill-buffer (get-buffer-create bash-temp-buffer))) + +(defun bash-process-url (url) + (http-get url nil 'bash-sentinel 1.0 bash-temp-buffer) + (message "Waiting for results from bash.org")) + +(defun bash-process-request (uri action id) + (http-get (concat "http://www.bash.org/?" uri) nil 'bash-request-sentinel 1.0 bash-temp-buffer) + (message "Attempting to %s quote #%s with bash.org" action id)) + +;; Entry points +;; -------------------------------------------------------------------------- +(defun bash-specific-quote (id) + "Downloads a specific quote from bash.org" + (interactive "sEnter quote-id: ") + (bash-process-url (bash-get-quote-url id))) + +(defun bash-latest-quotes () + "Downloads a specific quote from bash.org" + (interactive) + (setq bash-tmp-results-title "Latest quotes") + (bash-process-url bash-get-latest-url)) + +(defun bash-top-50-quotes () + "Downloads a specific quote from bash.org" + (interactive) + (setq bash-tmp-results-title "Top 50 quotes") + (bash-process-url bash-get-top-rated-url)) + +(defun bash-top-50-100-quotes () + "Downloads a specific quote from bash.org" + (interactive) + (setq bash-tmp-results-title "Top 50-100 quotes") + (bash-process-url bash-get-next-top-rated-url)) + +(defun bash-random-30-quotes () + "Downloads a specific quote from bash.org" + (interactive) + (setq bash-tmp-results-title "Random quotes") + (bash-process-url bash-get-random-url)) + +(defun bash-random-above-zero-quotes () + "Fetches random quotes from bash.org, all with ratings above zero" + (interactive) + (setq tmp-bash-results-title "Random quotes, rating > 0") + (bash-process-url bash-get-random-above-zero-url)) + +;; Saving a quote in a fortunedb file +(defun bash-save-quote (quote id) + "Saves a quote to a fortune-format file" + (let ((filename (read-file-name "Append to fortune-file: " ))) + (with-temp-buffer + (find-file filename) + (goto-char (point-max)) + (insert "\n%%\nfrom bash.org, quote #" id "\n" quote) + (save-buffer) + (kill-buffer (current-buffer))))) + +;; Searching bash.org +(defun bash-search-quote (criteria sort number) + "Searches bash.org for quote" + (interactive "sSearch for: \ncSort by number ('n') or rating ('r'): \nnNumber of results to return (25,50,75 or 100): ") + (unless (or (= sort ?n) (= sort ?r)) + (setq sort ?r)) ; sort by rating pr. default + (if (= sort ?n) + (setq sort "1") + (setq sort "2")) + (setq bash-tmp-results-title (concat "Searched for \"" criteria "\"")) + (bash-process-url (bash-make-search-url criteria sort number))) + +(provide 'bash-quotes) +;;; bash-quotes.el ends here \ No newline at end of file diff --git a/elisp/erbot/contrib/faith.el b/elisp/erbot/contrib/faith.el new file mode 100644 index 0000000..bfa85d3 --- /dev/null +++ b/elisp/erbot/contrib/faith.el @@ -0,0 +1,566 @@ +;;; faith.el --- hepls spreading the true faith +;; Time-stamp: <2003-08-19 13:38:28 deego> +;; GPL'ed under GNU'S public license.. +;; Copyright (C) Deepak Goel 2000 +;; Emacs Lisp Archive entry +;; Filename: faith.el +;; Author: Deepak Goel +;; Version: 1.9 + +(defconst faith-version "1.9" + "Version number of faith.el") + +;; This file is not (yet) part of GNU Emacs. + +;; WEBSITE: http://www.glue.umd.edu/~deego/emacspub/faith/ +;; for this file and for associated READMEs LOGFILEs etc.. + +;;; Copyright (C) Deepak Goel +;; AUTHORS: Deepak Goel (deego@glue.umd.edu) , +;; Robert Fenk , +;; Roberto Selbach Teixeira +;; Remi Vanicat + +;; YOU ARE VERY WELCOME TO CONTRIBUTE TO FAITH. YOUR SUGGESTIONS OR +;; CONTRIBUTIONS OR CORRECTIONS WILL BE CONSIDERED VERY FAVORABLY, +;; AND WILL PROVE YOUR UTMOST DEVOTION TO HIM. Even minor +;; contributions to this holy work will earn you a name on the list +;; of authors. + +;; If you have been invited to become priest (author) of faith, +;; please send deego@glue.umd.edu an email agreeing to accept the +;; "GNU FREEness" of faith, and agreeing that if at any point in +;; future, you don't agree to sign the appropriate copyleft +;; agreement, deego@glue.umd.edu will remove you from the author's +;; list. You will be promptly listed as an author. + +;; Commentary: In this world of infidelity and blasphemy, +;; FAITH tries to reinforce faith in you. + +;;; QUICKSTART INSTALLATION FOR THOSE LOST: +;;; Drop faith.el somewhere in yr load-path, and add to your .emacs: +;;; (load "faith.el") +;;; then type M-x faith, and enjoy.. + + +;;; Code: +(defconst faith-false-quotes nil + "BLASPHEMOUS QUOTES. DON'T LOOK! +A variety of false quotes collected from various places. Collected so +that the false names can be replaced by the TRUE ONE.") + +(defvar faith-user-quotes nil + "*These are any additional quotes a user might like included.") + +(defvar faith-quotes-separator "\n__________________________\n\n" + "*The string whis is inserted before a quote.") + +(defvar faith-replacement-strings nil + "True Replacements for bad Gods and other words. +Is a list of REPLACEMENTS. Each replacement is a list of BADLIST and +GOODLIST. All matches from BADLIST will be replaced by a random word +from goodlist. For consistency, the random word chosen will be the +same for the entire quote.") + +(defvar faith-user-before-replacement-strings nil + "Will be appended before faith-replacement-strings. +Allow user to define their own replacements, and together with +faith-user-after-replacement-strings, to completely edit the default +replacement-strings.. in many many novel ways the wise user may come +up with.. O user, from now on, you may customize your faith, should u +like to.. +Also see faith-user-after-replacement-strings") + +(defvar faith-user-after-replacement-strings nil + "Will be appended after faith-replacement-strings. +Allow user to define their own replacements. +Also see faith-user-before-replacement-strings") + +;; THE 'false-quotes have been picked out of books whose authors are +;; not likely to be in a position to object to the same. Current +;; sources: +;; Bible +;; Koran + + +;;;###autoload +(defun faith-insert (&rest args) + "Insert a quote right here, right now, in the current buffer" + (interactive) + (insert (apply 'faith-quote args))) + + +(defvar faith-fill-column 70) + +;; You might think some users might find no need for this +;; 'faith function. But ask me! It makes testing so easier.. +;;;###autoload +(defun faith () + "Switch to buffer *faith* and insert faith-snippets there." + (interactive) + (if (equal (buffer-name) "*faith*") + "" + (progn + (get-buffer-create "*faith*") + (switch-to-buffer "*faith*"))) + (let ((go-this-time t)) + (while go-this-time + (goto-char (point-max)) + (insert faith-quotes-separator (faith-quote)) + (goto-char (point-max)) + (recenter) + (setq fill-column faith-fill-column) + (call-interactively 'fill-paragraph) + (if (y-or-n-p "Care for more wise words? ") + nil + (setq go-this-time nil)))) + (message "Use M-x faith-correct on your own documents in order to correct them.")) + +;;;###autoload +(defun faith-quote (&optional quotes leave-alone-p ) + "Helps reinforce and spread faith in the ONE TRUE EDITOR. +Returns a randomly chosen snippet, which helps you along your search +for truth. If the argument QUOTES is supplied, it is the one used +instead of using the default source for quotes. If LEAVE-ALONE-P is +non-nil, then no faith-correction is done before insertion of the quote.. +" + (interactive) + (let* ((init-quote + (faith-false-choose + (if quotes quotes + (append faith-false-quotes faith-user-quotes)))) + (final-quote + (if leave-alone-p + init-quote + (faith-correct-string init-quote))) + (justified-quote (faith-justify-string final-quote))) + (if (interactive-p) + (message justified-quote) + justified-quote))) + +;;;###autoload +(defun faith-correct-buffer () + "Replace false Gods by the ONE TRUE GOD. +Takes a false SNIPPET, and weeds out the names of all false Gods and +prophets." + (interactive) + ;; Now, for each from in each from-list, select a random to from to-list. + ;; to-list is called tos and from-list is called froms. + (let ((case-replace t) + (case-fold-search t)) + (mapcar + (lambda (froms-tos) + (let ((tos (cadr froms-tos))) + (mapcar + (lambda (from) + (let ((this-to (nth (random* (length tos)) tos))) + (goto-char (point-min)) + (while (re-search-forward (concat "\\b" from "") + nil t) + (replace-match this-to nil nil)))) + (car froms-tos)))) + (append faith-user-before-replacement-strings + faith-replacement-strings + faith-user-after-replacement-strings)) + (buffer-substring (point-min) (point-max)))) + +;;;###autoload +(defun faith-correct-region (b e) + "Replace false Gods by the ONE TRUE GOD in region delimited by B and E." + (interactive "r") + (save-restriction + (save-excursion + (narrow-to-region b e) + (faith-correct-buffer) + (widen)))) + +;;;###autoload +(defun faith-correct-string (snippet) + "Replace false Gods by the ONE TRUE GOD. +Takes a false SNIPPET, and weeds out the names of all false Gods and +prophets." + (interactive) + (with-temp-buffer + (insert snippet) + (faith-correct-buffer) + (buffer-substring (point-min) (point-max)))) + +(defun faith-false-choose (quotes) + "Return a randomly chosen WRONG snippet. THUS NOT FOR HUMAN EYES. +Returns a randomly chosen false quote. Advice: Stay away. +Argument QUOTES is a list of quotes." + (let* ((n (random* (length quotes))) + (s (nth n quotes))) + (if (stringp s) s + (error (format "The quote at postition %d is no string." n s))))) + +(defun faith-justify-string (string) + "Justifies it.." + (with-temp-buffer + (insert string) + (fill-paragraph 1) + (buffer-substring (point-min) (point-max))) +) + +(unless faith-replacement-strings + (setq faith-replacement-strings + '( + (("allah" "buddha" "lord" "islam" "christianity" "hinduism") ("EMACS")) + (("almighty" "god") ("True Editor")) + (("adam" ) ("newbie")) + (("angel" ) ("truly free freebies")) + (("apostle") ( "book")) + (("bible" "koran") ("Emacs-manual")) + (("book") ("documentation")) + (("christ" ) ("emacs-homepage")) + (("christian" ) ("true follower")) + (("die" ) ("quit editland")) + (("gods") ("editors")) + (("earth" ) ("editland")) + (("heavens" ) ("elispland")) + (("holy spirit" ) ("holy editor")) + (("jesus" "muhammad" "muhammed" "mohammad" "mohammed") + ("gnu.org" "xemacs.org")) + (("mary") ("Gnus")) + (("Moses") ("Stallman" "RMS")) + (("the calf") ("vi")) + (("prophet") ("manual")) + (("religion") ("editing")) + (("satan") ("Microsoft" "Windoze" "VI")) + (("pray" ) ("edit")) + (("synagogue" "church") ("computer-room")) + ))) + + +(unless faith-false-quotes + (setq + faith-false-quotes + '("There shall be no compulsion in religion." + + "This Book is not to be doubted. . . . As for the unbelievers, it is +the same whether or not you forewarn them; they will not have faith. +God has set a seal upon their hearts and ears; their sight is dimmed +and grievous punishment awaits them." + + "The only true faith in God's sight is EMACS." + + "He that chooses a religion over Islam, it will not be accepted from +him and in the world to come he will be one of the lost." + + "It is not for true believers men or women to take their choice in the +affairs if God and His apostle decree otherwise. He that disobeys God +and His apostle strays far indeed." + + "God's curse be upon the infidels! Evil is that for which they have +bartered away their souls. To deny God's own revelation, grudging that +He should reveal His bounty to whom He chooses from among His +servants! They have incurred God's most inexorable wrath. An +ignominious punishment awaits the unbelievers." + + "Fight for the sake of God those that fight against you, but do not +attack them first. God does not love the aggressors. + +Slay them wherever you find them. Drive them out of the places from +which they drove you. Idolatry is worse than carnage." + + "Prophet, make war on the unbelievers and the hypocrites and deal +rigorously with them. Hell shall be their home: an evil fate." + + "The Lord is my strength and song; he has become my salvation. He is my +God, and I will praise him, my father's God, and I will exalt him." + + "Love the Lord your God with all your heart and with all your soul and +with all your strength." + + "Therefore go and make disciples of all nations, baptizing them in the +name of the Father and of the Son and the Holy Spirit, and teaching +them to obey everything I have commanded you. And surely I will be +with you always, to the very end of the age." + + "Have faith in God, Jesus answered. Therefore I tell you, whatever you +ask for in prayer, believe that you will receive it, and it will be +yours." + + "And Mary said: My soul praises the Lord and my spirit rejoices in God +my Saviour, for he has been mindful of the humble state of his +servant." + + "Jesus answered, It is written: Worship the Lord your God and serve him +only." + + "When you are brought before synagogues, rulers and authorities, do not +worry about how you will defend yourselves or what you will say, for +the Holy Spirit will teach you at that time what you should say." + + "Then Jesus cried out, When a man believes in me, he does not believe +in me only, but in the one who sent me. I have come into the world as +light, so that no one who believes in me should stay in darkness." + + "Jesus said, I am the way and the truth and the life. No one comes to +the Father except through me." + + "...Count yourselves dead to sin but alive to God in Christ Jesus." + + "May the God who gives endurance and encouragement give you a spirit of +unity among yourselves as you follow Christ Jesus ,so that with one +heart and mouth you may glorify the God and Father of our Lord Jesus +Christ." + + "May the God of hope fill you with great joy and peace as you trust in +him, so that you may overflow with hope by the power of the Holy +Spirit." + + "...God's abundant provision of grace and of the gift of righteousness +reign in life through the one and only , Jesus Christ." + + "The mind of sinful man is death, but the mind controlled by the Spirit +is life and peace, because the sinful mind is hostile to God. It does +not submit to God's law, nor can it do so. Those controlled by their +sinful nature cannot please God." + + "...No eyes have seen, no ear has heard, no mind had conceived what God +had prepared for those who love him but God had revealed it to us by his +Spirit. The spirit searches all things, even the deep things of God. For who +among men knows the thoughts of a man except the man's spirit within him? In +the same way no one knows the thoughts of God except the Spirit of God." + + "The Lord will rescue me from every evil attack and will bring me +safely to his heavenly kingdom." + + "For God did not give us a spirit of timidity, but a spirit of power, +of love and of self-discipline." + + "If you suffer as a Christian, do not be ashamed but praise God that +you bear that name." + + "Cast all your anxiety on Jesus because he cares for you." + + "57:1 All that is in heaven and earth gives glory to Allah. He is +the Mighty, the Wise One." + + "His is the kingdom of the heavens and the earth. He ordains life +and death and has power over all things." + + "He created the heavens and the earth in six days and then mounted +His throne. He knows all that goes into the earth and all that +emerges from it, all that comes down from heaven and all that +ascends to it. He is with you wherever you are. He is cognizant of +all your actions." + + "His is the kingdom of the heavens and the earth. To Him shall all +things return. He causes the night to pass into the day and the day +into the night. He has knowledge of the inmost thoughts of men." + + "24:34 Allah is the light of the heavens and the earth. His light +may be compared to a niche that enshrines a lamp, the lamp within a +crystal of star-like brilliance. It is lit from a blessed olive +tree neither eastern nor western. Its very oil would almost shine +forth, though no fire touched it. Light upon light; Allah guides to +His light whom He will." + + "24:36 As for the unbelievers, their works are like a mirage in a +desert. The thirsty traveler thinks it is water, but when he comes +near he finds that it is nothing. He finds Allah there, who pays +him back in full. Swift is Allah's reckoning." + + "Or like darkness on a bottomless ocean spread with clashing billows +and overcast with clouds: darkness upon darkness. If he stretches +out his hand he can scarcely see it. Indeed the man from whom Allah +withholds His light shall find no light at all." + + "10:80 We are the witnesses of all your thoughts and all your +prayers and all your actions. Not an atom's weight in earth or +heaven escapes your Lord, nor is there any object smaller or +greater, but is recorded in a glorious book." + + "58:7 Are you not aware that Allah knows what the heavens and the +earth contain? If three men talk in secret together, He is their +fourth; if four, He is their fifth; if five, He is their sixth; +whether fewer or more, wherever they be, He is with them. Then, on +the Day of Resurrection, He will inform them of their doings. Allah +has knowledge of all things." + + "39:39 Allah takes away men's souls upon their death, and the souls +of the living during their sleep. Those that are doomed He keeps +with Him and restores the others for a time ordained. Surely there +are signs in this for thinking men." + + "35:11 Praise be to Allah, the Creator of heaven and earth! He sends +forth the angels as His messengers, with two, three or four airs of +wings. He Multiplies His creatures according to His will. Allah has +power over all things." + + "2:32 To Adam We said: \"Dwell with your wife in Paradise and eat of +its fruits to your hearts' content wherever you will. But never +approach this tree or you shall both become transgressors.\" + +But Satan made them fall from Paradise and brought about their +banishment. \"Go hence,\" We said, \"and may your offspring be enemies +to each other. The earth will for a while provide your sustenance +and dwelling place.\" + +Then Adam received commandments from his Lord, and his Lord +relented towards him. He is the Forgiving One, the Merciful." + + "65:12 It is Allah who has created seven heavens, and earths as +many. His commandment descends through them, so that you may know +that Allah has power over all things, and that He has knowledge of +all things." + + "14:19 Do you not see that Allah has created the heavens and the +earth with truth? He can destroy you if He wills and bring into +being a new creation: that is no difficult thing for him." + + "40:67 It was He who created you from dust, making you a little +germ, and then a clot of blood. He brings you infants into the +world; you reach manhood, then decline into old age (though some of +you die young), so that you may complete your appointed term and +grow in wisdom." + + "16:75 To Allah belong the secrets of the heavens and the earth. The +business of the Final Hour shall be accomplished in the twinkling +of an eye, or even less. Allah has power over all things." + + "2:86 To Moses We gave the Scriptures and after him we sent other +apostles. We gave Jesus the son of Mary veritable signs and +strengthened him with the Holy Spirit. Will you then scorn each +apostle whose message does not suit your fancies, charging some +with imposture and slaying others?" + + "6:104 They solemnly swear by Allah that if a sign be given them +they would believe in it. Say: \"Signs are vouchsafed by Allah.\" And +how can you tell that if a sign be given them they will indeed +believe in it?" + + "We will turn away their hearts and eyes from the truth since they +refused to believe in it at first. We will leave them to blunder +about in their wrongdoing." + + "If We sent down the angels and caused the dead to speak with them, +and ranged all things before them, they would still not believe, +Unless Allah willed it. But most of them are ignorant men." + + "4:153 The People of the Book ask you to bring down for them a book +from heaven. Of Moses they demanded a harder thing than that. They +said to him: \"Show us Allah distinctly.\" And for their wickedness a +thunderbolt smote them. They worshipped the calf after We revealed +to them Our signs; yet We forgave them that, and bestowed on Moses +clear authority." + + "32:21 We gave the Scriptures to Moses (never doubt that you will +meet him) and made it a guide for Israelites. And when they grew +steadfast and firmly believed in Our revelations, We appointed +leaders from among them who gave guidance at Our bidding. On the +Day of Resurrection your Lord will resolve for them their +differences." + + "4:171 People of the Book, do not transgress the bounds of your +religion. Speak nothing but the truth about Allah. The Messiah, +Jesus the son of Mary, was no more than Allah's apostle and His +Word which he cast to Mary: a spirit from Him. So believe in Allah +and His apostles and do not say: \"Three;\" Forbear, and it shall be +better for you. Allah is but one God. Allah forbid that He should +have a son! His is all that the heavens and the earth contain. +Allah is the all-sufficient Protector. The Messiah does not disdain +to be a servant of Allah, nor do the angels who are nearer to him. +Those who through arrogance disdain His service shall all be +brought before Him." + + "73:1 You that are wrapped up in your mantle, keep vigil all night, +save for a few hours; half the night, or even less: or a little +more - and with measured tone recite the Koran, for We are about to +address to you words of surpassing gravity. It is in the watches of +the night that impressions are strongest and words most eloquent; +in the day-time you are hard-pressed with work. + +\(You need not move your tongue too fast to learn this revelation. +We Ourself shall see to its collection and recital. When We read +it, follow its words attentively; We shall Ourself explain its +meaning.)" + + "20:114 Do not be quick to recite the Koran before its revelation is +completed, but rather say: \"Lord, increase my knowledge.\"" + + "42:48 Thus We have inspired you with a spirit of Our will when you +knew nothing of faith or scripture, and made it a light whereby we +guide those of Our servants whom We please. You shall surely guide +them to the right path: the path of Allah, to whom belongs all that +the heavens and the earth contain. All things in the end return to +him." + + "25:27 The unbelievers ask: \"Why was the Koran not revealed to him +entire in a single revelation?\" + +We have revealed it thus so that We may strengthen your faith. We +have imparted it to you by gradual revelation. No sooner will they +come to you with an argument than We shall reveal to you the truth +and properly explain it. Those who will be dragged headlong into +Hell shall have an evil place to-dwell in, for they have strayed +far from the right path." + + "4:159 We have revealed Our will to you as We revealed it to Noah +and to the prophets who came after him; as We revealed it to +Abraham, Ishmael, Isaac, Jacob, and David, to whom We gave the +Psalms. Of some apostles We have already told you (how Allah spoke +directly to Moses); but there are others of whom We have not yet +spoken: apostles who brought good news to mankind and admonished +them, so that they might have no plea against Allah after their +coming. Allah is mighty and wise." + + "40:78 We have sent forth other apostles before you, of some you +have already heard, of others We have told you nothing. Yet none of +these could work a miracle except by Allah's leave. And when +Allah's will is done, justice will prevail and those who have +denied His signs will come to grief." + + "16:40 The apostles We sent before you were no more than mortals +whom We inspired with revelations and with writings. Ask the People +of the Book, ii you doubt this. To you We have revealed the Koran, +so that you may proclaim to men what has been revealed to them, and +that they may give thought." + + "13:38 We have sent forth other apostles before you and given them +wives and children. Yet none of them could work miracles except by +the will of Allah. Every age has its scripture. Allah confirms or +abrogates what He pleases. His is the Eternal Book." + + "22:46 Never have We sent a single prophet or apostle before you +with whose wishes Satan did not tamper. But Allah abrogates the +interjections of Satan and confirms His own revelations. Allah is +wise and all-knowing. He makes Satan's interjections a temptation +for those whose hearts are diseased or hardened - this is why the +wrongdoers are in open schism - so that those to whom knowledge has +been given may realize that this is the truth from your Lord and +thus believe in it and humble their hearts towards him. Allah will +surely guide the faithful to a straight path." + + "36:68 We have taught Mohammed no poetry, nor does it become him to +be a poet. This is but a warning: an eloquent Koran to admonish the +living and No pass judgment on the unbelievers." + + "29:48 Never have you read a book before this, nor have you ever +transcribed one with your right hand. Had you done either of these, +- the unbelievers might have justly doubted. But to those who are +endowed with knowledge it is an undoubted sign. Only the wrongdoers +deny Our signs." + + "68:1 By the pen, and what they write, you are not mad: thanks to +the favor of your Lord! A lasting recompense awaits you, for yours +is a sublime nature. You shall before long see - as they will see - +which of you is mad." + + "39:22 Allah has now revealed the best of scriptures, a book uniform +in style proclaiming promises and warnings. Those who fear their +Lord are filled with awe as they listen to its revelations, so that +their hearts soften at the remembrance of Allah. Such is Allah's +guidance: He bestows it on whom He will. But he whom Allah misleads +shall have none to guide him." + + "Allah is the only GOD and Muhammad is HIS only prophet." + ))) + + + + +(provide 'faith) +;;; faith.el ends here diff --git a/elisp/erbot/contrib/flame.el b/elisp/erbot/contrib/flame.el new file mode 100644 index 0000000..f878891 --- /dev/null +++ b/elisp/erbot/contrib/flame.el @@ -0,0 +1,356 @@ +;;; flame.el --- automatic generation of flamage, as if we needed more + +;;; Author: Ian G. Batten +;;; Maintainer: Noah Friedman +;;; Keywords: games + +;;; $Id: flame.el,v 1.1 2004/12/16 01:44:34 mwolson Exp $ + +;;; Commentary: + +;;; "Flame" program. This has a chequered past. +;;; +;;; The original was on a Motorola 286 running Vanilla V.1, +;;; about 2 years ago. It was couched in terms of a yacc (I think) +;;; script. I pulled the data out of it and rewrote it as a piece +;;; of PL/1 on Multics. Now I've moved it into an emacs-lisp +;;; form. If the original author cares to contact me, I'd +;;; be very happy to credit you! +;;; +;;; Ian G. Batten, Batten@uk.ac.bham.multics + +;;; On 1994/01/09, I discovered that rms dropped this file from the Emacs +;;; 19 distribution sometime before 19.7 was released. He made no +;;; ChangeLog entry and didn't keep the source file around (by convention, +;;; we usually renamed files we wanted to keep but not go into official +;;; distributions so that they started with `=', e.g. `=flame.el'). This +;;; is all he had to say about it when I asked: +;;; +;;; I think I decided I was unhappy with the legal papers for it. +;;; Removing it took less time than trying to deal with it +;;; any other way. +;;; +;;; I eventually found it on a backup tape, and I am now independently +;;; maintaining it. +;;; +;;; --Noah + +;;; Code: + +(random t) + +(defvar flame-sentence + '((how can you say that (flame-statement) \?) + (I can\'t believe how (flame-adjective) you are\.) + (only a (flame-der-term) like you would say that (flame-statement) \.) + ((flame-statement) \, huh\?) (so\, (flame-statement) \?) + ((flame-statement) \, right\?) (I mean\, (flame-sentence)) + (don\'t you realise that (flame-statement) \?) + (I firmly believe that (flame-statement) \.) + (let me tell you something\, you (flame-der-term) \, (flame-statement) \.) + (furthermore\, you (flame-der-term) \, (flame-statement) \.) + (I couldn\'t care less about your (flame-thing) \.) + (How can you be so (flame-adjective) \?) + (you make me sick\.) + (it\'s well known that (flame-statement) \.) + ((flame-statement) \.) + (it takes a (flame-group-adj) (flame-der-term) like you to say that (flame-statement) \.) + (I don\'t want to hear about your (flame-thing) \.) + (you\'re always totally wrong\.) + (I\'ve never heard anything as ridiculous as the idea that (flame-statement) \.) + (you must be a real (flame-der-term) to think that (flame-statement) \.) + (you (flame-adjective) (flame-group-adj) (flame-der-term) \!) + (you\'re probably (flame-group-adj) yourself\.) + (you sound like a real (flame-der-term) \.) + (why\, (flame-statement) \!) + (I have many (flame-group-adj) friends\.) + (save the (flame-thing) s\!) (no nukes\!) (ban (flame-thing) s\!) + (I\'ll bet you think that (flame-thing) s are (flame-adjective) \.) + (you know\, (flame-statement) \.) + (your (flame-quality) reminds me of a (flame-thing) \.) + (you have the (flame-quality) of a (flame-der-term) \.) + ((flame-der-term) \!) + ((flame-adjective) (flame-group-adj) (flame-der-term) \!) + (you\'re a typical (flame-group-adj) person\, totally (flame-adjective) \.) + (man\, (flame-sentence)))) + +(defvar flame-sentence-loop (nconc flame-sentence flame-sentence)) + +(defvar flame-quality + '((ignorance) (stupidity) (worthlessness) + (prejudice) (lack of intelligence) (lousiness) + (bad grammar) (lousy spelling) + (lack of common decency) (ugliness) (nastiness) + (subtlety) (dishonesty) ((flame-adjective) (flame-quality)))) + +(defvar flame-quality-loop (nconc flame-quality flame-quality)) + +(defvar flame-adjective + '((ignorant) (crass) (pathetic) (sick) + (bloated) (malignant) (perverted) (sadistic) + (stupid) (unpleasant) (lousy) (abusive) (bad) + (braindamaged) (selfish) (improper) (nasty) + (disgusting) (foul) (intolerable) (primitive) + (depressing) (dumb) (phoney) (boring) + (gratuitous) ((flame-adjective) and (flame-adjective)) + (as (flame-adjective) as a (flame-thing)))) + +(defvar flame-adjective-loop (nconc flame-adjective flame-adjective)) + +(defvar flame-der-term + '(((flame-adjective) (flame-der-term)) (sexist) (fascist) + (weakling) (coward) (beast) (peasant) (racist) + (cretin) (fool) (jerk) (ignoramus) (idiot) + (wanker) (rat) (slimebag) (DAF driver) (quiche-eater) + (Neanderthal) (sadist) (drunk) (capitalist) + (wimp) (dogmatist) (wally) (maniac) (luser) + (whimpering scumbag) (pea brain) (arsehole) + (moron) (goof) (incompetent) (lunkhead) (Nazi) + (SysThug) ((flame-der-term) (flame-der-term)))) + +(defvar flame-der-term-loop (nconc flame-der-term flame-der-term)) + +(defvar flame-thing + '(((flame-adjective) (flame-thing)) (computer) + (Honeywell dps8) (whale) (operation) + (sexist joke) (ten-incher) (dog) (MicroVAX II) + (source license) (real-time clock) + (mental problem) (sexual fantasy) + (venereal disease) (Jewish grandmother) + (cardboard cut-out) (punk haircut) (surfboard) + (system call) (wood-burning stove) + (standard text editor) (processed lunch meat) + (graphics editor) (right wing death squad) + (disease) (vegetable) (religion) (random frob) + (cruise missile) (bug fix) (lawyer) (copyright) + (PAD))) + +(defvar flame-thing-loop (nconc flame-thing flame-thing)) + + +(defvar flame-group-adj + '((gay) (old) (lesbian) (young) (black) + (Polish) ((flame-adjective)) (white) + (mentally retarded) (Nicaraguan) (homosexual) + (dead) (underpriviledged) (religious) + ((flame-thing) \-loving) (feminist) (foreign) + (intellectual) (crazy) (working) (unborn) + (Chinese) (short) ((flame-adjective)) (poor) (rich) + (funny-looking) (Puerto Rican) (Mexican) + (Italian) (communist) (fascist) (Iranian) + (Moonie))) + +(defvar flame-group-adj-loop (nconc flame-group-adj flame-group-adj)) + +(defvar flame-statement + '((your (flame-thing) is great) ((flame-thing) s are fun) + ((flame-person) is a (flame-der-term)) + ((flame-group-adj) people are (flame-adjective)) + (every (flame-group-adj) person is a (flame-der-term)) + (most (flame-group-adj) people have (flame-thing) s) + (all (flame-group-adj) dudes should get (flame-thing) s) + ((flame-person) is (flame-group-adj)) (trees are (flame-adjective)) + (if you\'ve seen one (flame-thing) \, you\'ve seen them all) + (you\'re (flame-group-adj)) (you have a (flame-thing)) + (my (flame-thing) is pretty good) + (the Martians are coming) + (the (flame-paper) is always right) + (just because you read it in the (flame-paper) that doesn\'t mean it\'s true) + ((flame-person) was (flame-group-adj)) + ((flame-person) \'s ghost is living in your (flame-thing)) + (you look like a (flame-thing)) + (the oceans are full of dirty fish) + (people are dying every day) + (a (flame-group-adj) man ain\'t got nothing in the world these days) + (women are inherently superior to men) + (the system staff is fascist) + (there is life after death) + (the world is full of (flame-der-term) s) + (you remind me of (flame-person)) (technology is evil) + ((flame-person) killed (flame-person)) + (the Russians are tapping your phone) + (the Earth is flat) + (it\'s OK to run down (flame-group-adj) people) + (Multics is a really (flame-adjective) operating system) + (the CIA killed (flame-person)) + (the sexual revolution is over) + (Lassie was (flame-group-adj)) + (the (flame-group-adj) people have really got it all together) + (I was (flame-person) in a previous life) + (breathing causes cancer) + (it\'s fun to be really (flame-adjective)) + ((flame-quality) is pretty fun) (you\'re a (flame-der-term)) + (the (flame-group-adj) culture is fascinating) + (when ya gotta go ya gotta go) + ((flame-person) is (flame-adjective)) + ((flame-person) \'s (flame-quality) is (flame-adjective)) + (it\'s a wonderful day) + (everything is really a (flame-thing)) + (there\'s a (flame-thing) in (flame-person) \'s brain) + ((flame-person) is a cool dude) + ((flame-person) is just a figment of your imagination) + (the more (flame-thing) s you have, the better) + (life is a (flame-thing)) (life is (flame-quality)) + ((flame-person) is (flame-adjective)) + ((flame-group-adj) people are all (flame-adjective) (flame-der-term) s) + ((flame-statement) \, and (flame-statement)) + ((flame-statement) \, but (flame-statement)) + (I wish I had a (flame-thing)) + (you should have a (flame-thing)) + (you hope that (flame-statement)) + ((flame-person) is secretly (flame-group-adj)) + (you wish you were (flame-group-adj)) + (you wish you were a (flame-thing)) + (I wish I were a (flame-thing)) + (you think that (flame-statement)) + ((flame-statement) \, because (flame-statement)) + ((flame-group-adj) people don\'t get married to (flame-group-adj) people because (flame-reason)) + ((flame-group-adj) people are all (flame-adjective) because (flame-reason)) + ((flame-group-adj) people are (flame-adjective) \, and (flame-reason)) + (you must be a (flame-adjective) (flame-der-term) to think that (flame-person) said (flame-statement)) + ((flame-group-adj) people are inherently superior to (flame-group-adj) people) + (God is Dead))) + +(defvar flame-statement-loop (nconc flame-statement flame-statement)) + + +(defvar flame-paper + '((Daily Mail) (Daily Express) (Boston Glob) + (Centre Bulletin) (Sun) (Daily Mirror) (Pravda) + (Daily Telegraph) (Beano) (Multics Manual))) + +(defvar flame-paper-loop (nconc flame-paper flame-paper)) + + +(defvar flame-person + '((Reagan) (Ken Thompson) (Dennis Ritchie) + (JFK) (the Pope) (Gadaffi) (Napoleon) + (Karl Marx) (Groucho) (Michael Jackson) + (Caesar) (Nietzsche) (Heidegger) (\"Head-for-the-mountains\" Bush) + (Henry Kissinger) (Nixon) (Castro) (Thatcher) + (Attilla the Hun) (Alaric the Visigoth) (Hitler))) + +(defvar flame-person-loop (nconc flame-person flame-person)) + +(defvar flame-reason + '((they don\'t want their children to grow up to be too lazy to steal) + (they can\'t tell them apart from (flame-group-adj) dudes) + (they\'re too (flame-adjective)) + ((flame-person) wouldn\'t have done it) + (they can\'t spray paint that small) + (they don\'t have (flame-thing) s) (they don\'t know how) + (they can\'t afford (flame-thing) s))) + +(defvar flame-reason-loop (nconc flame-reason flame-reason)) + + +(defmacro flame-define-element (name) + (let ((loop-to-use (intern (concat name "-loop")))) + (` (defun (, (intern name)) nil + (let ((step-forward (% (random) 10))) + (if (< step-forward 0) (setq step-forward (- step-forward))) + (prog1 + (nth step-forward (, loop-to-use)) + (setq (, loop-to-use) (nthcdr (1+ step-forward) (, loop-to-use))))))))) + +(flame-define-element "flame-sentence") +(flame-define-element "flame-quality") +(flame-define-element "flame-adjective") +(flame-define-element "flame-der-term") +(flame-define-element "flame-group-adj") +(flame-define-element "flame-statement") +(flame-define-element "flame-thing") +(flame-define-element "flame-paper") +(flame-define-element "flame-person") +(flame-define-element "flame-reason") + +(defun *flame nil + (flame-expand '(flame-sentence))) + +(defun flame-expand (object) + (cond ((atom object) + object) + (t (mapcar 'flame-expand (funcall (car object)))))) + +(defun flame-flatten (list) + (cond ((atom list) + (list list)) + ((null list)) + (t (apply 'append (mapcar 'flame-flatten list))))) + +;;;###autoload +(defun flame (&optional arg) + "Generate ARG (default 1) sentences of half-crazed gibberish. +If interactive, print the result in a buffer and display it. +Otherwise, just return the result as a string." + (interactive "p") + (or arg (setq arg 1)) + (if (interactive-p) + (let ((w (selected-window))) + (pop-to-buffer (get-buffer-create "*Flame*")) + (goto-char (point-max)) + (insert ?\n) + (flame2 arg) + (select-window w)) + (let (result) + (while (> arg 0) + (setq result (concat result + (flame-string) + (if (= 1 arg) "" "\n"))) + (setq arg (1- arg))) + result))) + +(defun flame2 (arg) + (let ((start (point))) + (flame1 arg) + (fill-region-as-paragraph start (point) t))) + +(defun flame1 (arg) + (cond ((zerop arg) t) + (t (insert (flame-string)) + (flame1 (1- arg))))) + +(defun flame-string () + (concat (flame-sentence-ify + (flame-string-ify + (flame-append-suffixes-hack + (flame-flatten (*flame))))))) + +(defun flame-sentence-ify (string) + (concat (upcase (substring string 0 1)) + (substring string 1 (length string)) + " ")) + +(defun flame-string-ify (list) + (mapconcat + '(lambda (x) + (format "%s" x)) + list + " ")) + +(defun flame-append-suffixes-hack (list) + (cond ((null list) + nil) + ((memq (nth 1 list) + '(\? \. \, s\! \! s \'s \-loving)) + (cons (intern (format "%s%s" (nth 0 list) (nth 1 list))) + (flame-append-suffixes-hack (nthcdr 2 list)))) + (t (cons (nth 0 list) + (flame-append-suffixes-hack (nthcdr 1 list)))))) + +(defun psychoanalyze-flamer () + "Mr. Angry goes to the analyst." + (interactive) + (doctor) ; start the psychotherapy + (message "") + (switch-to-buffer "*doctor*") + (sit-for 0) + (while (not (input-pending-p)) + (flame2 (if (= (% (random) 2) 0) 2 1)) + (insert "\n") + (sit-for 0) + (doctor-ret-or-read 1))) + +(provide 'flame) + +;;; flame.el ends here diff --git a/elisp/erbot/contrib/geek.el b/elisp/erbot/contrib/geek.el new file mode 100644 index 0000000..6563884 --- /dev/null +++ b/elisp/erbot/contrib/geek.el @@ -0,0 +1,138 @@ +;;; geek.el --- annoy lusers who think the geek code is wAY ko0l RADIKuL D00D!1 + +;; Copyright (C) 1995 American Telephone & Telegraph, Inc. + +;; Author: Noah Friedman +;; Maintainer: friedman@prep.ai.mit.edu +;; Created: 1995-01-07 + +;; $Id: geek.el,v 1.1 2004/12/16 01:44:34 mwolson Exp $ + +;; This software is is guaranteed to do nothing useful, except when it +;; does. You may sell it, burn it, use it, modify it, or give it away, at +;; your leisure. You may even require that other people use it. You may +;; also require that people not use it, as you see fit. Government +;; agencies are encouraged to integrate this software into weapons control +;; systems and other instruments of destruction. + +;;; Commentary: +;;; Code: + +(defvar geek-header "X-Geek-Code") + +(defvar geek-suffix-single-chars ["?" "@" "$" "!" "*"]) +(defvar geek-suffix-long-chars [?+ ?- ?+ ?- ?+ ?- ?+ ?- ?+ ?- ?+ ?- ?']) +(defvar geek-infix-chars [">" ":"]) + +(defvar geek-letters + ["A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" + "S" "T" "U" "V" "W" "X" "Y" "Z" + "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" + "s" "t" "u" "v" "w" "x" "y" "z" + "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"]) + +(if (string-lessp emacs-version "19") + (defun geek-random (&optional n) + (if (numberp n) + (abs (% (random) n)) + (random n))) + (defalias 'geek-random 'random)) + +(defun geek-item (v) + (aref v (geek-random (length v)))) + +(defun geek-code () + (let ((ncodes (+ 10 (geek-random 40))) + (codes "") + (nflavors (+ 4 (geek-random 8))) + (flavors "") + letter + len len1 + char char1 + tem + i + (vmajor (int-to-string (1+ (geek-random 8)))) + (vminor (int-to-string (geek-random 100)))) + (setq i nflavors) + (while (not (zerop i)) + (setq flavors (concat flavors "/")) + (setq len (1+ (geek-random 2))) + (while (not (zerop len)) + (setq tem (geek-item geek-letters)) + (setq flavors (concat flavors tem)) + (setq len (1- len))) + (setq i (1- i))) + (aset flavors 0 ?G) + + (setq i ncodes) + (while (not (zerop i)) + (setq letter (geek-item geek-letters)) + (and (zerop (geek-random 10)) + (setq letter (concat letter (geek-item geek-letters)))) + + (setq len (geek-random 5)) + (setq char (geek-item geek-suffix-long-chars)) + (setq letter (concat letter (make-string len char))) + + (cond + ((zerop len)) + ((= char ?')) + ((zerop (geek-random 5)) + (setq char1 (geek-item geek-infix-chars)) + (setq letter (concat letter char1)) + + (setq len1 (1+ (geek-random 4))) + (setq char1 char) + (while (= char char1) + (setq char1 (geek-item geek-suffix-long-chars))) + (setq letter (concat letter (make-string len1 char1))))) + + (cond + ((zerop len) + (and (zerop (geek-random 3)) + (setq letter (concat letter + (geek-item geek-suffix-single-chars))))) + ((zerop (geek-random 5)) + (setq len1 (1+ (geek-random 2))) + (setq letter (concat letter "(" (make-string len1 ?*) ")")))) + + (setq codes (concat codes " " letter)) + (setq i (1- i))) + (setq codes (concat "(V" vmajor "." vminor ") " + flavors codes)) + codes)) + +(defun geek-replace-header (s) + (save-excursion + (cond + ((mail-position-on-field geek-header 'soft) + (let* ((data (match-data)) + (end (point)) + (beg (progn + (re-search-backward (concat geek-header ": ")) + (match-end 0))) + (orig (buffer-substring beg end)) + ;; avoid creating any permanent undo boundaries + (buffer-undo-list nil)) + (store-match-data (match-data)) + (delete-region beg end) + (goto-char beg) + (insert s) + orig))))) + +(defun geek-subvert-header () + (let ((s (geek-replace-header (geek-code)))) + (add-hook 'mail-send-actions (list 'geek-restore-header s) 'append))) + +(defun geek-restore-header (s) + (and s (geek-replace-header s))) + +;; mib is an extra special twit. +(cond + ((and (string= (user-login-name) "mib") + (fboundp 'add-hook)) + (add-hook 'mail-send-hook 'geek-subvert-header 'append))) + +(provide 'geek) + +;;; geek.el ends here. diff --git a/elisp/erbot/contrib/google.el b/elisp/erbot/contrib/google.el new file mode 100644 index 0000000..d940119 --- /dev/null +++ b/elisp/erbot/contrib/google.el @@ -0,0 +1,271 @@ +;;; Debugging info for self: Saved through ges-version 1.5dev +;;; ;;; From: Edward O'Connor +;;; ;;; Subject: google.el +;;; ;;; Newsgroups: gnu.emacs.sources +;;; ;;; Date: Sat, 14 Sep 2002 10:37:56 GMT +;;; ;;; Organization: RoadRunner - West + +;;; > google.el --- Emacs interface to the Google API + +;;; Virtually unchanged; just fixed a remarkably embarassing bug. + +;;; + +;;; google.el --- Emacs interface to the Google API + +;; Copyright (C) 2002 Edward O'Connor + +;; Author: Edward O'Connor +;; Keywords: comm, processes, tools +;; Version: 0.1 + +;; This file 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 3, or (at your option) +;; any later version. + +;; This file 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 GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; A really bare-bones first hack at Google API support for Emacs. +;; Note that you need a Google license key to use this; you can +;; get one by following the instructions here: + +;; + +;; Usage: + +;; (require 'google) +;; (setq google-license-key "my license key") +;; Then M-x google-search RET +;; or M-x google-search-region RET + +;; To use this in a program, see the functions `google-search' and +;; `google-display-response' for example usage. + +;;; Code: + +(require 'soap) +(require 'xml) + +(defgroup google nil + "" + :group 'tools) + +(defcustom google-license-key nil + "*Your Google license key." + :type '(string) + :group 'google) + +(defcustom google-search-result-callback nil + "*The function to be called with the search result." + :type '(function) + :group 'google) + +(defcustom google-start 0 + "*Which result to start with." + :type 'integer + :group 'google) + +(defcustom google-max-results 10 + "*Maximum number of results to return." + :type 'integer + :group 'google) + +(defcustom google-filter-p t + "*Whether or not to filter results." + :type 'boolean + :group 'google) + +(defcustom google-safe-p nil + "*Safe or not?" + :type 'boolean + :group 'google) + +(defcustom google-linkify-links-p t + "*Whether or not we should linkify links in the response buffer." + :type 'boolean + :group 'google) + +(defun google-xml-sexp-attr-to-xml (attr-cons) + (let ((attr-name (car attr-cons)) + (attr-val (cdr attr-cons))) + (unless (stringp attr-val) + (setq attr-val (format "%s" attr-val))) + (concat (format " %s=" attr-name) + (if (string-match "[\"]" attr-val) + (format "'%s'" attr-val) + (format "\"%s\"" attr-val))))) + +(defun google-xml-sexp-to-xml (xml-sexp) + "Return a string containing an XML representation of XML-SEXP." + (cond ((null xml-sexp) + "") + ((stringp xml-sexp) + xml-sexp) + ((listp xml-sexp) + (let ((tag (xml-node-name xml-sexp)) + (attrs (xml-node-attributes xml-sexp)) + (children (xml-node-children xml-sexp))) + (concat (format "<%s" tag) + (if attrs + (mapconcat 'google-xml-sexp-attr-to-xml + attrs + "") + "") + (if children + (concat ">" + (mapconcat 'google-xml-sexp-to-xml + children + "") + (format "" tag)) + "/>")))) + + (t (google-xml-sexp-to-xml (format "%s" xml-sexp))))) + +(defun google-request (xml-sexp) + "Send XML-SEXP to Google as a request." + (soap-request "http://api.google.com/search/beta2" + (google-xml-sexp-to-xml xml-sexp))) + +(defun google-search-internal (terms start max-results filter-p safe-p) + "Search for TERMS." + (google-request + `(SOAP-ENV:Envelope ((xmlns:SOAP-ENV + . "http://schemas.xmlsoap.org/soap/envelope/") + (xmlns:xsi + . "http://www.w3.org/1999/XMLSchema-instance") + (xmlns:xsd . "http://www.w3.org/1999/XMLSchema")) + (SOAP-ENV:Body () + (ns1:doGoogleSearch ((xmlns:ns1 . "urn:GoogleSearch") + (SOAP-ENV:encodingStyle . + "http://schemas.xmlsoap.org/soap/encoding/")) + (key ((xsi:type . "xsd:string")) + ,google-license-key) + (q ((xsi:type . "xsd:string")) + ,terms) + (start ((xsi:type . "xsd:int")) + ,(format "%d" start)) + (maxResults ((xsi:type . "xsd:int")) + ,(format "%d" max-results)) + (filter ((xsi:type . "xsd:boolean")) + ,(if filter-p "true" "false")) + (restrict ((xsi:type . "xsd:string"))) + (safeSearch ((xsi:type . "xsd:boolean")) + ,(if safe-p "true" "false")) + (lr ((xsi:type . "xsd:string"))) + (ie ((xsi:type . "xsd:string")) + "latin1") + (oe ((xsi:type . "xsd:string")) + "latin1")))))) + +(defvar google-result-mode-map (make-sparse-keymap) + "Map to be used in `google-result-mode'.") + +(define-key google-result-mode-map "q" 'google-result-quit) + +(defun google-result-quit () + (interactive) + (kill-buffer (get-buffer-create "*google-response*"))) + +(defun google-result-mode () + (kill-all-local-variables) + (setq major-mode 'google-result-mode + mode-name "Google Result") + (set (make-local-variable 'font-lock-defaults) + '(message-font-lock-keywords t)) + (use-local-map google-result-mode-map)) + +(defun google-display-response (processed-response) + (with-current-buffer (get-buffer-create "*google-response*") + (delete-region (point-min) + (point-max)) + (google-result-mode) + (insert (format "Google search results for %S\n" (car processed-response)) + "-------------------------------------------------\n\n") + (setq processed-response (cdr processed-response)) + (while processed-response + (let* ((item (car processed-response)) + (url (nth 0 item)) + (title (nth 1 item)) + (hostname (nth 2 item)) + (cached-size (nth 3 item)) + (snippet (nth 4 item))) + + (when title + (insert (format "Title: %s\n" title))) + + (when url + (insert (format "URL: %s\n" url))) + + (when hostname + (insert (format "Hostname: %s\n" hostname))) + + (when cached-size + (insert (format "Size: %s\n" cached-size))) + + (when snippet + (insert (format "Snippet: %s\n" snippet))) + + (insert "\n")) + + (setq processed-response (cdr processed-response))) + (when google-linkify-links-p + (goto-address)) + (switch-to-buffer (current-buffer)))) + +(defun google-process-response (response) + (let* ((body (car (xml-get-children (car response) 'SOAP-ENV:Body))) + (g-s-r (car (xml-get-children body 'ns1:doGoogleSearchResponse))) + (return (car (xml-get-children g-s-r 'return))) + (search-query (nth 2 (car (xml-get-children return 'searchQuery)))) + (r-e (car (xml-get-children return 'resultElements))) + (items (xml-get-children r-e 'item)) + (retval '())) + + (while items + (let* ((item (car items)) + (hostname (nth 2 (car (xml-get-children item 'hostName)))) + (url (nth 2 (car (xml-get-children item 'URL)))) + (title (nth 2 (car (xml-get-children item 'title)))) + (snippet (nth 2 (car (xml-get-children item 'snippet)))) + (cached-size (nth 2 (car (xml-get-children item 'cachedSize)))) + (retval-item '())) + + (add-to-list 'retval-item url t) + (add-to-list 'retval-item title t) + (add-to-list 'retval-item hostname t) + (add-to-list 'retval-item cached-size t) + (add-to-list 'retval-item snippet t) + + (add-to-list 'retval retval-item) + + (setq items (cdr items)))) + + (cons search-query retval))) + +(defun google-search (terms) + "Search for TERMS." + (interactive "sGoogle search: ") + (google-display-response + (google-process-response + (google-search-internal terms google-start google-max-results + google-filter-p google-safe-p)))) + +(defun google-search-region (beg end) + "Perform a Google search on the words from BEG to END." + (interactive "r") + (google-search (buffer-substring-no-properties beg end))) + +(provide 'google) +;;; google.el ends here + diff --git a/elisp/erbot/contrib/h4x0r.el b/elisp/erbot/contrib/h4x0r.el new file mode 100644 index 0000000..8b20858 --- /dev/null +++ b/elisp/erbot/contrib/h4x0r.el @@ -0,0 +1,106 @@ +; h4x0r.el 0.11 +; Time-stamp: <2003-02-22 00:47:54 deego> + +; by Charles Sebold +; +; thanks to Alex Schroeder for typo fix and feature suggestions (which +; I have not begun to implement yet) + +;;; Copyright: (C) 2000, 2001 Charles Sebold +;; +;; 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 3 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 GNU Emacs; if not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +;; MA 02111-1307, USA. +;; +;; Latest version should be available at: +;; +;; + + +(require 'cl) + +(defvar h4x0r-always-replace + '(("hacker" . "h4x0r") ("hack" . "h4x0r") ("elite" . "31337") + ("fear" . "ph33r"))) + +(defvar h4x0r-sometimes-replace + '(("ea" "33") ("er" "0r") ("a" "4") ("b" "8") ("d" "|>") + ("e" "3" "E") ("f" "|=") ("h" "|-|") ("i" "1" "|") ("k" "|<" "x") + ("l" "1" "|_") ("m" "|\\/|") ("n" "|\\|") ("o" "0") ("q" "@") ("s" + "5" "Z" "$") ("t" "+" "7") ("ck" "x") ("u" "U") ("v" "\\/") ("x" + "X" "><") ("y" "j"))) + +(defvar h4x0r-unreadable 5) + +(defvar h4x0r-replace-with-symbols-p nil) + +(defun h4x0r-region (beg end) + "Convert region to h4x0r-talk." + (interactive "r") + (save-excursion + (let ((starting-buffer (current-buffer))) + (set-buffer (get-buffer-create "h4x0r-temp")) + (insert-buffer-substring starting-buffer beg end) + (downcase-region (point-min) (point-max)) + (dotimes (i (length h4x0r-always-replace)) + (beginning-of-buffer) + (let ((old-word (car (nth i h4x0r-always-replace))) + (new-word (cdr (nth i h4x0r-always-replace)))) + (while (search-forward old-word nil t) + (replace-match new-word)))) + (dotimes (i (length h4x0r-sometimes-replace)) + (if (< (random 9) h4x0r-unreadable) + (progn + (beginning-of-buffer) + (let ((old-char (car (nth i h4x0r-sometimes-replace)))) + (let ((new-char (h4x0r-assoc old-char))) + (while (search-forward old-char nil t) + (replace-match new-char nil t))))))) + (set-buffer starting-buffer) + (delete-region beg end))) + (insert-buffer "h4x0r-temp") + (message "%s" "J00 h4v3 b33n h4x0r3d!") + (kill-buffer "h4x0r-temp")) + +(defun h4x0r-assoc (normal-char) + (let ((h4-out (cdr (assoc normal-char h4x0r-sometimes-replace)))) + (if (nlistp h4-out) + h4-out + (nth (random (length h4-out)) h4-out)))) + +(defun h4x0r-buffer () + "Convert entire buffer to h4x0r-talk." + (interactive) + (save-excursion + (h4x0r-region (point-max) (point-min)))) + +(defun h4x0r-word-at-point () + (interactive) + (save-excursion + (forward-word -1) + (insert (h4x0r-string (current-word))) + (kill-word 1))) + +(defun h4x0r-string (h4-input-string) + (save-excursion + (let ((starting-buffer (current-buffer))) + (set-buffer (get-buffer-create "h4x0r-string-temp")) + (insert h4-input-string) + (h4x0r-buffer) + (setq h4-input-string (buffer-string)) + (kill-buffer "h4x0r-string-temp") + (set-buffer starting-buffer))) + h4-input-string) + +(provide 'h4x0r) diff --git a/elisp/erbot/contrib/haiku.el b/elisp/erbot/contrib/haiku.el new file mode 100644 index 0000000..b66b6d7 --- /dev/null +++ b/elisp/erbot/contrib/haiku.el @@ -0,0 +1,311 @@ +;; haiku.el --- Semi-random haiku generator + +;; Author: Jose E. Marchesi +;; Maintainer: Jose E. Marchesi + +;; This file is not part of GNU Emacs. + +;; 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 3 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; Haiku generator for erbot. + +;;; Code: + +(setq erbot-haiku-quotes-1 + '( + "The street-smart seamstress " + "The young Russian bride " + "The substitute nurse " + "The Polish waitress " + "The baroness stirs, " + "The long-legged blonde " + "The dish-water blonde " + "The bow-legged midget " + "The busty brunette " + "The divorcee sighs, " + "The arthritic nun " + "The loquacious nurse " + "The hip-sprung school marm " + "The one-eyed baker " + "The plumber's third wife " + "Traffic stills. The maid " + "Clouds form. The pornstar " + "The stewardess coughs, " + "The Swiss bank teller " + "The stripper pauses, " + "The erstwhile diva " + "The languid bar maid " + "The opera singer " + "The zoologist " + "The Czech spinster " + "His virgin great-aunt " + "His neighbor's young wife " + "The banker's mistress " + "The pregnant midwife " + "The devious moll " + "The shy farmer's wife " + "A cornfed she-spy " + "The juice bar clerk's wife " + "One hillbilly tart " + "The one in the skirt " + "The kiwi au pair " + "The lipstick model " + "A lady from Minsk " + "The gal with Shooter " + "The slatternly nurse " + "The B-movie star " + "The heart-broken girl " + "The star-struck waitress " + "The therapist snores, " + "The stewardess drools, " + "The magnateâs mistress " + "The steel baronâs bride " + "The pianistas niece " + "The Russian cellist " + "The poetess gulps, " + "The Slavic wet nurse " + "Filipino Sue " + "Susannah stretches, " + "The wet nurse sniffles, " + "The clarinetist " + "The drunk southern belle " + "The cheer squad reject " + "The home ec teacher " + "The receptionist " + "The paralegal " + "The street-smart fly girl " + "The redhead stretches, " + "The old-fashioned nun " + "The ice cream lady " + "The sullen milkmaid " + "The vain meter maid " + "The fat Dixie Chick " + "The shy cartoonist " + "The sexy bassist " + "The reclusive aunt " + "The sly lunch lady " + "The Czech go-go girl " + "The short cheerleader " + "The chain-smoking niece " + "The Swiss governess " + "The stone-faced matron " + "The suave landlady " + "Traffic slows. The nun " + "Paint dries. The brunette " + "The other woman " + "The anchorwoman " + "The Russian madam " + "His ex-fiancee " + "The young blushing bride " + "The widow-to-be " + "The drunken bridesmaid " + "The groom's ex-wife sneers, " + "The gap-toothed redneck " + "The night-shift seamstress ")) + + +(setq erbot-haiku-quotes-2 + '( + "removes her prosthetic leg. " + "rolls her tongue, trilling râs, lâs. " + "wakes, deflates the air mattress. " + "bathes in warm crocodile tears. " + "motions with her silver thumb. " + "rouges her razorous cheeks. " + "arches her wrist towards the sky. " + "removes her golden fake nose. " + "stands, coins spilling from her ears. " + "removes her prosthetic leg. " + "rolls her tongue, trilling râs, lâs. " + "wakes, deflates the air mattress. " + "bathes in warm crocodile tears. " + "covers her eyes with sack-cloth. " + "blots her dark lipstick, pauses. " + "calmly sets fire to her hair. " + "hangs her slip on the lanyard. " + "greasens the stubborn crank-shaft. " + "polishes the good flatware. " + "whispers the word âwheelbarrowâ. " + "fingers her silver tongue-stud. " + "dreams of monkeys, gibbons, apes. " + "scrubs the tile floor, knees rasping. " + "speaks in tongues, eyelids twitching. " + "retires to the powder room. " + "dips her tongue in peroxide. " + "displays her elegant gams. " + "exhales a plume of wood-smoke. " + "rings the doorbell, rings again. " + "rubs her feet, closes her eyes. " + "shuffles a stack of scratch cards. " + "grins and waves the poking stick. " + "leans toward the caged man-child. " + "rises, but won't run or blink. " + "shouts lies to baldheaded fools. " + "really needs to get kneaded. " + "quickly dons her happy pants. " + "beckons with a pineapple. " + "brandishes a hair curler. " + "plants the pill beneath the sheets. " + "hides the orange behind the stove. " + "tucks the gem beneath her tongue. " + "eats the lottery ticket. " + "fills the sock drawer with mustard. " + "steals the swear jar, hops a train. ")) + +(setq erbot-haiku-quotes-3 + '( + "Boom-shacka-lacka. " + "Thunderous applause. " + "Dogs dance like comets. " + "The sky fills with stars. " + "Retrograde motion. " + "She sells no sea shells. " + "No room in the inn. " + "Dishes dry in sinks. " + "Snow falls in Utah. " + "Sirens wail, so close. " + "He takes a breath, breathes. " + "His heart swells madly. " + "His ears fill with blood. " + "There is always time. " + "All Iâve got is time. " + "You know the story. " + "The drummer skips town. " + "One more cigarette. " + "The ocean shivers. " + "The dormouse quivers. " + "Rain falls on spring leaves. " + "Pizza boy blushes. " + "The cat fiddles on. " + "A new moon blushes. " + "Somewhere a dog howls. " + "Cats rub themselves mad. " + "Soup boils on the stove. " + "The stove eye glows red. " + "The faucet drips, drips. " + "Cars howl on the street. " + "A car backfires, roars. " + "There is never time. " + "The bouilabaisse chills. " + "Ganja cornbread bakes. " + "People smile and cry. " + "Spacious rooms are filled. " + "Unseen lackeys stir. " + "The burnished door shuts. " + "For the last time, why? " + "Why didn't you stay? " + "Why didn't you leave? " + "Where did the time go? " + "My tongue betrays me. " + "My heart betrays me. " + "The night betrays me. " + "I miss you. Love, me. " + "I've got plenty more. " + "No, itâs not like that. " + "Cry uncle for me. " + "Take two steps backwards. " + "Paper beats rock, fool. " + "Hell, maybe. Who knows. " + "Hit me one more time. " + "My dog has no fleas. " + "Is this all there is? " + "No more soup for you. " + "You buy the next round. " + "A round of applause. " + "Contestants titter. " + "He owns no short-shorts. " + "Pat your head thusly. " + "Never with these eyes. " + "Only with these eyes. " + "We've all gone crazy. " + "Hank Williams was right. " + "It's all circular. " + "Everything is wet. " + "Boom-shacka-lacka. " + "Thunderous applause. " + "Dogs dance like comets. " + "The sky fills with stars. " + "Retrograde motion. " + "She sells no sea shells. " + "No room in the inn. " + "Dishes dry in sinks. " + "Snow falls in Utah. " + "Sirens wail, so close. " + "He takes a breath, breathes. " + "His heart swells madly. " + "His ears fill with blood. " + "There is always time. " + "All I've got is time. " + "You know the story. " + "The drummer skips town. " + "One more cigarette. " + "The ocean shivers. " + "The dormouse quivers. " + "Rain falls on spring leaves. " + "Pizza boy blushes. " + "The cat fiddles on. " + "A new moon blushes. " + "Somewhere a dog howls. " + "Cats rub themselves mad. " + "Soup boils on the stove. " + "The stove eye glows red. " + "The faucet drips, drips. " + "Cars howl on the street. " + "A car backfires, roars. " + "There is never time. " + "The bouilabaisse chills. " + "Ganja cornbread bakes. " + "People smile and cry. " + "Spacious rooms are filled. " + "Unseen lackeys stir. " + "The burnished door shuts. " + "For the last time, why? " + "Why didn't you stay? " + "Why didn't you leave? " + "Where did the time go? " + "My tongue betrays me. " + "My heart betrays me. " + "The night betrays me. " + "I miss you. Love, me. " + "Iâve got plenty more. " + "No, itâs not like that. " + "Cry uncle for me. " + "Take two steps backwards. " + "Paper beats rock, fool. " + "Hell, maybe. Who knows. " + "Hit me one more time. " + "My dog has no fleas. " + "Is this all there is? " + "No more soup for you. " + "You buy the next round. " + "A round of applause. " + "Contestants titter. " + "He owns no short-shorts. " + "Pat your head thusly. " + "Never with these eyes. " + "Only with these eyes. " + "We've all gone crazy. " + "Hank Williams was right. " + "It's all circular. ")) + +(defun fs-haiku (&rest args) + "REST: args" + (format "%s\n%s\n%s" + (erbutils-random erbot-haiku-quotes-1) + (erbutils-random erbot-haiku-quotes-2) + (erbutils-random erbot-haiku-quotes-3))) \ No newline at end of file diff --git a/elisp/erbot/contrib/idledo.el b/elisp/erbot/contrib/idledo.el new file mode 100644 index 0000000..a75f1c0 --- /dev/null +++ b/elisp/erbot/contrib/idledo.el @@ -0,0 +1,1157 @@ +;;; idledo.el --- do stuff when emacs is idle.. +;; Time-stamp: <2004-11-14 22:37:04 deego> +;; Copyright (C) Deepak Goel 2001 +;; Emacs Lisp Archive entry +;; Filename: idledo.el +;; Package: idledo +;; Author: Deepak Goel +;; Keywords: idle startup speed timer +;; Version: 0.3 +;; Author's homepage: http://deego.gnufans.org/~deego +;; REQUIRES: timerfunctions.el 1.2.7 or later. +;; ALSO uses: emacs' ('cl during compile.. for all the backquoting..) +;; For latest version: + +(defvar idledo-home-page + "http://deego.gnufans.org/~deego/emacspub/lisp-mine/idledo") + +;; Requires: timerfunctions.el +;; See also: Jari's tinyload.el, dope.el. + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + + + +;; Quick start: +(defvar idledo-quick-start + "Drop idledo.el and timerfunctions.el somewhere in your +load-path. In your .emacs, type (require 'idledo) and (require +'timerfunctions). In there, also create idledo-list-- a list of +expresions, either by hand, or by using one of the many functions and +macros provided. Then, write (idledo-start), and idledo will start +doing the tasks mentioned in the idledo-list whenever emacs is idle. + +Here, for example, are some +possible lines of code from a .emacs---> + + + (idledo-require 'bbdb 'bbdb-com 'bbdb-gnus) + (idledo-add-action + '(progn (unless (file-locked-p \"~/emacs/.bbdb\") + (bbdb-records)) + nil)) + (idledo-require-now 'mailabbrev) + ;; as below, or simply (idledo-gc) + (idledo-add-action + '(garbage-collect)) + + (idledo-add-action '(load \"aliases-my\")) + + (idledo-add-action '(progn + (garbage-collect) + nil)) + + (idledo-load \"mode-hook-functions-my\") + (add-to-list 'idledo-list '(progn (message \"Just a sample\"))) + (idledo-require 'disp-table) + (idledo-require 'gnus-score 'gnus 'gnus-msg) + +A simple long example is (idledo-example-setup) which can be called +from your .emacs. Alternatively, a more complicated example of how to +set up idledo-list can be seen in the function idledo-example. That +one tries to save even more time by: moving the task of setting up an +idledo-list itself into the first idledo, and on top of that, calls +idledo-start not from emacs, but from an idle-timer. + +To maintain idledo-history, see idledo-after-action-hooks + +This author currently uses exactly 105 idledo's. +PS: timerfunctions.el can be obtained from: +http://deeego.gnufans.org/~deego/emacspub/lisp-mine/timerfunctions/" +) + +(defun idledo-quick-start () + "Provides electric help for function `idledo-quick-start'." + (interactive) + (with-electric-help + '(lambda () (insert idledo-quick-start) nil) "*doc*")) + +;;; Introduction: +;; Stuff that gets posted to gnu.emacs.sources +;; as introduction +(defvar idledo-introduction + "Idledo does stuff for you when emacs is idle. + + +The actions can be simple one-time actions or repetitive. You can +include as many actions as you want. Thus, with apprpriate actions, +if you leave emacs running for sometime, take a break and come back, +your emacs should have (require)'d almost everything you will ever +need..you can now start your gnus or eshell or w3 instantly.. When you +are using gnus, you can check mail periodically.. Make +color-theme-random a periodic idledo and you can convert emacs into a +shapeshifting color-changing aquarium.. + +idledo will probably someday be interfaced with a prioritizer, which +will include all sorts of enhanced capabilites, like weighting of +repetitive actions etc. + +See also M-x idledo-quick-start +" +) + +;;;###autoload +(defun idledo-introduction () + "Provides electric help for function `idledo-introduction'." + (interactive) + (with-electric-help + '(lambda () (insert idledo-introduction) nil) "*doc*")) + +;;; Commentary: +(defvar idledo-commentary + "First type M-x idledo-introduction. +Also see M-x idledo-quick-start + +You give idledo a list of commands, and it will eval them when emacs is +idle and you are away.. Thus, if you take a hike and come back, your +w3, gnus, eshell should all start instantly.. Your gnus-news should +be checked periodically for you.. and *Group* buffer updated.. of +course, you have to set this all up :/) + +If emacs is idle *not* because you are away, but because you are +deeply absorbed using info, you probably don't want idledo springing into +action and loading eshell for you.. So, idledo tries to alert you before +loading anything, and gives you enough time to cancel any action +before it is taken.. + +As an example, see the function idledo-example. I call that function +from my .emacs as follows.. + +/(idledo-example/) + +where: + +Note: If you specify many idle-loads and thus make your emacs very big +with (idle) time, your emacs will get slow and do frequent gc. Some +remedies: + +* First, turn garbage-collection messages on to see what i am sayin, + for yourself: (setq garbage-collection-messages t) in .emacs + +* Next, increase gc-cons-threshold to say, 10 times its value: + (setq gc-cons-threshold 40000000) in .emacs. + +* Finally, ask idledo to do garbage-collections for you when emacs is + idle. See an example in idledo-example-setup. In that example, once + all my other idledo's are taken care of, emacs then alternates + between doing garbage-collection and color-theme-random when it is + idle.. Thus, trying to ensure that when I get back to work, least gc + takes place... + + +0.1 new features: +* Now called idledo, to avoid a name-conflict with another package. + Sorry about that, and Thanks to all who pointed this out. +* Macros like ido-add-require now called idledo-require. +* Minor bug fixed in idledo-add-periodic-action-to-beginning-crud +" ) + +(defun idledo-commentary () + "Provides electric help for function `idledo-commentary'." + (interactive) + (with-electric-help + '(lambda () (insert idledo-commentary) nil) "*doc*")) + +;;; History: + +;;; New features: +(defvar idledo-new-features + "New in 0.3: +Some Bugfixes. Made compatible with the current +timerfunctions.el--posted here. +Improved doc." +) + +(defun idledo-new-features () + "Provides electric help for function `idledo-new-features'." + (interactive) + (with-electric-help + '(lambda () (insert idledo-new-features) nil) "*doc*")) + +(defvar idledo-version "0.3") + +(defvar idledo-todo +"TODO: +* Ideally, one should be able to cancel the timer if idledo-list + becomes nil. + +* Write a prioritizer, and interface the same with idledo. The priotizer + should. among other things like weights and \(arbitrarily specified\) + repetitivity, try to support different idle times for different + tasks.." +) + + +;;========================================== +;;; Code: +(defgroup idledo nil + "idledo.el --- do stuff when emacs is idle.. " + :group 'applications) + +(defcustom idledo-before-load-hooks nil "." + :type 'hook + :group 'idledo + ) +(defcustom idledo-after-load-hooks nil "." + :type 'hook + :group 'idledo + ) +(run-hooks 'idledo-before-load-hooks) +(eval-when-compile (require 'cl)) + +(defcustom idledo-before-action-hooks nil + " + +This hook is run even if idledo-once is callesd byhand. + +" + :type 'hook + :group 'idledo + ) + +(defcustom idledo-before-idle-action-hooks nil + "." + :type 'hook + :group 'idledo + ) + +(defcustom idledo-after-action-hooks nil + "Hooks to run after performing idledo-actions. +You could insert the command idledo-history-update into this hook. +This hook is run even if idledo-once is called by hand. +" + :type 'hook + :group 'idledo) + +(defcustom idledo-after-idle-action-hooks nil + "Hooks to run after performing idledo-actions. +You could insert the command idledo-history-update into this hook. +" + :type 'hook + :group 'idledo) + +(defcustom idledo-before-possible-action-hooks nil "." + :type 'hook + :group 'idledo) + +(defcustom idledo-after-possible-action-hooks nil "." + :type 'hook + :group 'idledo) + + + +(defcustom idledo-list nil + "A list of actions to perform.." + :type 'list + :group 'idledo + ) + + +(defcustom idledo-verbosity 0 + "Suggested: Anywhere from -100 to 100. + +The design is such that a value of 0 should be optimum. +viz.: Once you are experienced with this library, you might prefer a value +of 0 for this variable if this is > 0 right now." + :type 'integer + :group 'idledo +) + +(defvar idledo-active-p nil + "If t, no more idledo's can be initiated.. +The aim is to only have one idledo active at a time. + +Why? I don't know. You can easily setq this to nil, and start yet +another `idledo-start' if you want. + +Why do i want only one idledo at a time? My experience is that \(GNU\) +Emacs bahaves unpredictably if the activation of 2 or more timers +collide... maybe i am wrong? It seems to me that sometimes, both get +executed, someimtes one, and sometimes none.. Although the one or +none situations seem to be rare, each of thses situations can be +potentially bad..particularly if: Suppose the timer is a +self-reinforcing timer \(as can be done by calls to +`tf-run-with-idle-timer'\). Then, the very first time it fails to get +executed, the process gets killed and you want get those cherished +repetitions as long as Emacs remains idle.." +) + +(defcustom idledo-interval 30 + "The interval to wait the first time Emacs goes idle.. +An additional small interval will be allowed to enable the user to +cancel the action. + +Note that you can assign to this this interval any expression that +will be eval'ed at run-time \(see timerfunctions.el for more details..\)" + :type 'list + :group 'idledo +) + +(defcustom idledo-interval-subsequent 1 + "When Emacs remains idle, time to wait before next action. + +Time is in seconds.. floats might work too. +Note that you can assign to this this interval any expression that +will be eval'ed at run-time \(see timerfunctions.el for more details..\)" + :type 'list + :group 'idledo +) + +(defcustom idledo-interval-small 5 + "Time to warn for before performing the imminent idledo. + +Before beginning any action, idledo will flash a warning, and will +wait for these many seconds.. if you do something in this time, the +action will be cancelled. + +Note that you can assign to this this interval any expression that +will be eval'ed at run-time \(see timerfunctions.el for more details..\)" :type 'hook + :group 'idledo +) + +(defvar idledo-timer nil + "The timer stored here.. so can be cancelled.. Internal..") + +(defvar idledo-last-action nil + "Will store the last action. +--if the user needs this for any purpose. ") +(defvar idledo-last-result nil + "The result of the eval of the last idledo-action. +provided in case the user needs this. ") + +(defvar idledo-history nil + "Stores, optionally, the reverse-history of idledo-actions and their +results. ") + +(defcustom idledo-history-max-length 100 + "Max length of history to maintain. Nil means no limit. +When length exceeded, oldest entries are discarded. " +:group 'idledo +) + +(defvar idledo-counter 0 + "The number of idledos performed. ") + + + +(defun idledo-history () + (interactive) + (message "idledo-counter: %S idledo-history: %S" + idledo-counter idledo-history)) + +(defun idledo-history-update () + (interactive) + (push (list (copy-tree idledo-last-action) + (copy-tree idledo-last-result)) + idledo-history) + (setq idledo-counter (+ 1 idledo-counter)) + (while (and (integerp idledo-history-max-length) + (> (length idledo-history) idledo-history-max-length)) + (setq idledo-history (reverse (cdr (reverse idledo-history)))))) + + +(defun idledo-start-forced-risky () + "Internal. +USED ONLY FOR DEBUGGING.. USE AT YOUR OWN RISK.. STARTS A PARALLEL +version of idledo if there already exists one..." + (interactive) + (tf-run-with-idle-timer + 'idledo-interval t + 'idledo-interval-subsequent + t nil + 'idledo-one-action)) + + +;;;###autoload +(defun idledo-stop () + "Stop any idledo." + (interactive) + (when (timerp idledo-timer) + (cancel-timer idledo-timer)) + (setq idledo-active-p nil)) + + + +;;;###autoload +(defun idledo-start () + "Start idledo. + +See also `idledo-active-p'. Also returns the timer." + (interactive) + (if (not idledo-active-p) + (progn + (idledo-stop) + (setq idledo-active-p t) + (setq idledo-timer + (tf-run-with-idle-timer + 'idledo-interval t + 'idledo-interval-subsequent + t nil + 'idledo-one-action))) + (error "Idledo is already active"))) + +(defcustom idledo-interval-done 1 + "Time to wait before showing the 'done' message. +Idledo will wait for this much time before flashing a 'done-action' +message" + :group 'idledo +) + + +(defcustom idledo-action-imminent-string + "idledo imminent unless keypress ---> " + "The `idledo-action-imminent-string'." + :type 'string + :group 'idledo +) + +(defun idledo-one-action () + "Internal. +Does one instance of processing of action." + (when (not (null idledo-list)) + (run-hooks 'idledo-before-possible-action-hooks) + (idledo-message 25 + (concat idledo-action-imminent-string + (idledo-shorten (format "%S" (car idledo-list))))) + (if (sit-for idledo-interval-small) + (progn + (run-hooks 'idledo-before-idle-action-hooks) + (idledo-once 1) + (run-hooks 'idledo-after-idle-action-hooks) + (sit-for idledo-interval-done) + (idledo-message 60 "%S more idledo(s) remainig.. " + (length idledo-list))) + + + (idledo-message 20 + (concat "IDLEDO's action canceled.." + (idledo-shorten (format "%S" (car idledo-list))))) + ) + (run-hooks 'idledo-after-possible-action-hooks))) + +(defun idledo-all () + "Tell the amount of time saved through idledo's. +Start emacs and run M-x idledo-all. That will run all your +idledo's at once and show you how much time all of that took. + +More like, it will run as many idledo's as there are currently in +your idledo-list, which may not correspond to ALL idledo's since you +may have repetitive idledo's" + (interactive) + (let ((ta (current-time)) + (len (length idledo-list)) + tb tott) + (idledo-once len) + (setq tb (current-time)) + (setq tott (idledo-time-diff tb ta)) + (message "That took %S milliseconds. " tott))) + + +(defun idledo-time-diff (tb ta) + "Get the difference bet times TB and TA, in milliseconds. A float." + (+ + (* 0.001 (- (caddr tb) (caddr ta))) + (* 1000.0 + (+ + (- (second tb) (second ta)) + (* 65536.0 + (- (car tb) (car ta))))))) + +;;;###autoload +(defun idledo-once (arg) + "Call this if you wanna run something in yr `idledo-list' NOW... +Provide numerical prefix ARG for multiple arguments... +but note that doesn't run after-action hooks etc." + (interactive "p") + (while + (>= arg 1) + (setq arg (- arg 1)) + (run-hooks 'idledo-before-action-hooks) + (progn + (idledo-message 20 + (concat "IDLEDO doing action.." + (idledo-shorten (format "%S" (car idledo-list))))) + (let ((carval (car idledo-list))) + (setq idledo-last-action carval) + (setq idledo-list (cdr idledo-list)) + (setq idledo-last-result + (idledo-ignore-errors (eval carval))))) + (run-hooks 'idledo-after-action-hooks) + + )) + + + +(defun idledo-add-periodic-action-crude (action) + "Add a action to `idledo-list' to be repeated endlessly. +Is a crude mechanism for adding action to the `idledo-list' and make it +repetitive. ACTION is a (quoted) list which will be evaled to perform an +eval. + +Note that the ACTION this way is added to the END of `idledo-list'. +And ACTION is added to list no matter what (even if there is a similar +action already waiting in the list)." + (setq + idledo-list + (append + idledo-list + (list + `(progn + ,action + (idledo-add-periodic-action-crude + (quote ,action))))))) + +(defun idledo-add-periodic-action-to-beginning-crude (action) + "Add an action to `idledo-list' to be repeated endlessly. + +Is a crude mechanism for adding action to the `idledo-list' and make it +periodic. ACTION is a list which will be evaled to perform an +eval. +Note that the ACTION this way is added to the BEGINNING and subsequent +calls are also added to the beginning of the list. +And ACTION is added to list no matter what (even if there is a similar +action already waiting in the list)." + (idledo-add-action-forced + `(progn + ,action + (idledo-add-periodic-action-to-beginning-crude + (quote ,action))))) + + + + +;;;###autoload +(defun idledo-add-to-end-of-list (list-var element) + "Like `add-to-list', but add at the end, if at all. + +Add to the end of the list LIST-VAR, the element ELEMENT" + (if (member element (symbol-value list-var)) + (symbol-value list-var) + (set list-var (append (symbol-value list-var) (list element))))) + +(defun idledo-add-action (action) + "Add ACTION to ideldo-list. + +ACTION is an expression to be evaled. Action is added at the +beginning if at all. See similar commands too." + (add-to-list 'idledo-list action)) + +(defun idledo-add-action-forced (action) + "Add action ACTION to `idledo-list' even if it already exists." + (setq idledo-list (cons action idledo-list))) + +(defun idledo-add-action-at-end (&rest actions) + "Add actions ACTIONS to the end of `idledo-list'." + (mapcar + (lambda (action) + (idledo-add-to-end-of-list 'idledo-list action)) + actions)) + +(defmacro idledo-load (&rest files) + "Add, for each of FILES, a (load file) action to `idledo-list'." + (cons 'progn + (mapcar + (lambda (arg) + `(idledo-add-action-at-end '(load ,arg))) + files))) + +;;; 2001-11-03 T13:42:01-0500 (Saturday) Deepak Goel +(defmacro idledo-load-now (&rest files) + "Add, for each of FILES, a (load-file) action to `idledo-list'. + +The action is added to the beginning of `idledo-list'." + (cons 'progn + (mapcar + (lambda (arg) + `(idledo-add-action '(load ,arg))) + files))) + + +(defmacro idledo-require (&rest features) + "Add, for each of the FEATURES, a (require) action to `idledo-list'." + (cons 'progn + (mapcar + (lambda (arg) + `(idledo-add-action-at-end '(require ,arg))) + features))) + + +(defmacro idledo-require-now (feature) + "Add a (require FEATURE) action to `idledo-list'. + +The addition is done to the beginning of `idledo-list'." + `(idledo-add-action '(require ,feature))) + +(defun idledo-add-action-at-end-forced (action) + "Add ACTION to the end of `idledo-list'. + +Action is added even if it exists in the list already." + (setq idledo-list (append idledo-list (list action)))) + +(defun idledo-initialize (initial-list) + "Initialize `idledo-list' to INITIAL-LIST." + (setq idledo-list initial-list)) + +(defun idledo-remove-action (action) + "Remove ACTION from `idledo-list'." + (idledo-remove-from-list 'idledo-list action)) + +(defun idledo-remove-from-list (listname elt) + "INTERNAL. + +Remove, from list LISTNAME, element ELT." + (set listname (idledo-list-without-element + (eval listname) + elt))) + +(defun idledo-list-without-element (list elt) + "INTERNAL. +Returns the value of the LIST without the element ELT." + (if (null list) + list + (if (equal (car list) elt) + (idledo-list-without-element (cdr list) elt) + (cons + (car list) + (idledo-list-without-element + (cdr list) elt))))) + + +;; Thanks to Kim F. Storm for the suggestion: +(defun idledo-gc () + (idledo-add-action '(garbage-collect))) + +(defun idledo-shorten (string) + "Internal, return a shortened version with no newlines. +Internal, returns a shortened version of STRING with no newlines." + (let + ((string-no-enter + (with-temp-buffer + (insert string) + (goto-char (point-min)) + (while (search-forward "\n" nil t) + (replace-match " " nil t)) + (buffer-substring (point-min) (point-max))))) + (if (> (length string-no-enter) 55) + (substring string-no-enter 0 55) + string-no-enter))) + + +(defcustom idledo-ignore-errors-p t + "This should always be t unless you know what you are doing. + +For regular idledo's if this is not t and an error occurs, this means +that your entire idle-timer might get canceled due to the error. The +only place where this = nil makes sense is when you are running M-x +idledo-once by hand and want to debug the idledo action which is +giving you an error. See also idledo-toggle-ignore-errors.") + +(defun idledo-toggle-ignore-errors-p (&optional arg) + "See idledo-ignore-errors-p. " + (interactive "P") + (let ((num (prefix-numeric-value arg))) + (cond + ((or (not arg) (equal num 0)) + (setq idledo-ignore-errors-p (not idledo-ignore-errors-p))) + ((> num 0) (set idledo-ignore-errors-p t)) + ((< num 0) (set idledo-ignore-errors-p nil))) + (message "Symbol %S set to %S" + 'idledo-ignore-errors-p + idledo-ignore-errors-p) + idledo-ignore-errors-p)) + + +(defmacro idledo-ignore-errors (&rest body) + "Like `ignore-errors', but tell the error.. + +A wrapper around the BODY." + + (if idledo-ignore-errors-p + (let ((err (gensym))) + `(condition-case ,err (progn ,@body) + (error + (ding t) + (ding t) + (ding t) + (idledo-message 90 "IGNORED ERROR: %s" + (error-message-string ,err)) + (sit-for 1) + nil))) + `(progn ,@body))) + + +;;;###autoload +(defun idledo-example () + "Sample of code to include in your .emacs.. +See this and `idledo-example-setup'. +Define a similar function idledo-yourname for yourself in your .emacs, +and call it in yr .emacs by inserting (idledo-yourname) somewhere. + +See \\[idledo-quick-start] for simple examples. + +This function tries to go one step further to and defers the setting +up of the `idledo-list' itself to a time when Emacs goes idle, so as to +try to save more .emacs loading time." + (interactive) + (message "Setting up idledo and starting it..") + ;; testing + ;;(setq idledo-interval 300) + + ;;(setq idledo-list nil) + (idledo-add-action-at-end '(idledo-example-setup)) + + + (setq idledo-action-imminent-string + "idledo imminent--> ") + (idledo-start) + (message "Setting up idledo and starting it..done") + +) + + + +(defun idledo-message (points &rest args) + "Signal message, depending on POINTS and `idledo-verbosity'. +ARGS are passed to `message'." + (unless (minusp (+ points idledo-verbosity)) + (apply #'message args))) + +(defcustom idledo-message-nice-sit 1 "" :group 'idledo) + +(defun idledo-message-nice (points &rest args) + (unless (minusp (+ points idledo-verbosity)) + (with-temp-message (apply 'format args) + (sit-for 0.5)))) + +;;;###autoload +(defun idledo-length-list () + "For you to quickly find the length of idledo-list.. +If you use idledo bigtime, you will frequently find yourself wanting +to find out the length.. and you don't want to eval that parenthesised +expression all the time.. perhaps.." + (interactive) + (idledo-message + (if (interactive-p) 135 35) + "%s" + (format "Length= %S ... %S..." (length idledo-list) + (first idledo-list))) + (length idledo-list)) + + + + + + + + + + + + + + +(defun idledo-example-setup () + "Called by `idledo-example'. +This extra step is taken so that setting +up idledo itself takes place only when Emacs has gone idle.. +This function is actually used by this user's .emacs. +" + ;; The preference in all of below should be to load stuff that takes + ;; time asap.. small libraries can always be loaded later.. or even + ;; if they are not loaded, they do not make the user wait anyways + ;; when they finally get loaded.. + + ;; once bbdb is loaded.. let's get the frobnicating stuff over with.. + + ;; made interactive only for test purposes.. + (interactive) + + ;; hm, i now prefer directly setting the idledo list... + + + (idledo-gc) + + (idledo-require 'bbdb 'bbdb-com 'bbdb-gnus) + (idledo-add-action + '(progn + (require 'bbdb) + (when (boundp 'bbdb-file) + (unless (file-locked-p bbdb-file) + (bbdb-records))) + nil)) + (idledo-require-now 'mailabbrev) + (idledo-add-action '(progn + (garbage-collect) + nil)) + (idledo-load "gnus-functions-my") + (idledo-load "macros-my") + (idledo-add-action '(load "aliases-my")) + (idledo-gc) + + (idledo-load "mode-hook-functions-my") + (idledo-require 'disp-table) + (idledo-require 'gnus-score 'gnus 'gnus-msg) + (idledo-require 'gnus-cache) + (idledo-require 'gnus-ml 'gnus-cite) + (idledo-require 'timerfunctions) + + ;;maybe emacs needs a GC now.. we need to make sure GC is done when + ;;emacs is idle.. + (idledo-gc) + + (idledo-require 'esh-mode + 'em-alias) + + (idledo-require 'em-banner 'em-basic 'em-cmpl 'em-dirs 'em-glob + 'em-hist 'em-ls 'em-prompt 'em-script 'em-term + 'em-xtra 'etags + 'ange-ftp + ;; no longer needed since pcomplete is now bundled + ;; with emacs (21..) + ;;'pcmpl-auto + 'pcomplete + ;; 2002-05-02 T11:57:07-0400 (Thursday) D. Goel + 'shellhist + ;; 2002-05-02 T11:57:25-0400 (Thursday) D. Goel + 'pcmpl-unix + + ;; no longer needed since eshell is now bundled + ;; with emacs (21) + ;;'eshell-auto + + 'em-unix 'bytecomp 'eshell 'runshell ) + (idledo-add-action '(progn + (garbage-collect) + nil)) + (idledo-add-action '(progn + (recentf-mode 1) + nil)) + (idledo-load "cl-seq") + + (idledo-require 'autokey) + (idledo-require 'thingatpt 'ispell 'info) + (idledo-require 'elder) + + (idledo-require 'mail-extr ) + (idledo-require 'autorevert 'view) + (idledo-require 'time-stamp ) + (idledo-require 'imenu) + (idledo-load "kinsoku") + (idledo-require 'edlib ) + (idledo-require 'phonemode) + (idledo-add-action '(progn + (garbage-collect) + nil)) + + ;; bytecomp should be required before this... + (idledo-add-action-at-end '(load "byte-opt")) + + ;;(idledo-load 'tex-mode) + (idledo-require 'boxquote) + (idledo-require 'dired) + (idledo-require 'dired-x) + (idledo-require 'bytecomp) + (idledo-require 'find-func) + (idledo-require 'diff 'diff-mode) + (idledo-require 'add-log) + (idledo-require 'calendar) + (idledo-require 'mule-util) + (idledo-require 'cal-move) + (idledo-require 'advice) + (idledo-require 'browse-kill-ring) + ;; add for fsbot + (idledo-require 'browse-url) + (idledo-add-action '(progn + (garbage-collect) + nil)) + + (idledo-require 'debug) + ;;(idledo-require 'ell) + (idledo-require 'table) + (idledo-require 'tabify) + (idledo-require 'edebug) + ;; 2002-04-25 T15:43:21-0400 (Thursday) Deepak Goel + ;; this will shorten the time it takes to find a tag.. + (idledo-add-action + '(progn + (visit-tags-table "~/TAGS") + nil)) + (idledo-require 'gnus-cus) + (idledo-require 'gnus-async) + ;;(idledo-require 'smiley) + ;;(idledo-add-action + ;;(progn + ;; (require 'smiley "smiley-ems") + ;;nil)) + (idledo-require 'cus-edit) + (idledo-require 'newcomment) + (idledo-require 'genauto) + (idledo-require 'mkback) + (idledo-add-action '(progn + (mkback-install-for-eshell) + nil)) + (idledo-require 'flow-fill) + (idledo-require 'findutils) + (idledo-require 'erc) + (idledo-add-periodic-action-crude + '(progn + (garbage-collect) nil)) + + ; (idledo-add-action + ; '(progn + ; (numshift-install) + ; nil)) + (idledo-add-action + '(progn + (if (display-mouse-p) + (mouse-avoidance-mode 'animate)) + nil)) + (idledo-add-action + '(progn + (iswitchb-mode 1) + nil)) + (idledo-require 'spook) + (idledo-require 'autoinsert) + (idledo-require 'sregex) + (idledo-require 'choose) + (idledo-require 'erc-complete) + (idledo-require 'buffer-stack) + (idledo-require 'emacs-wiki) + (idledo-require 'planner) + (idledo-add-action + '(progn + (require 'eldoc) + (utils-add-minor-mode 'lisp-mode 'eldoc-mode) + (utils-add-minor-mode 'emacs-lisp-mode 'eldoc-mode))) + + + + (idledo-add-action '(progn + (global-font-lock-mode t) + nil)) + + + (idledo-add-action + '(progn + (if + (locate-library "bbdb" nil nil) + (require 'bbdb) + (message "NO BBDB found...")) + nil)) + + + (idledo-add-action + (progn + ;; CVS's type break currently has an annoying "sabve file? " + ;; question. + (when (< emacs-minor-version 3) + (type-break-mode 1)) + nil)) + + (idledo-require 'emacs-wiki) + + + ;; top priority stuff... + (idledo-add-action + '(progn + ;; do we still need all of these for emacs21? + (ignore-errors-my + (add-to-list 'ispell-skip-region-alist + '("\\\\[a-z]?ref{". "}")) + (add-to-list 'ispell-skip-region-alist + '("\\[\\[\\$". "\\$\\]\\]")) ; for latex.. + (add-to-list 'ispell-skip-region-alist + '("\\\\[a-z]?cite{". "}")) + (add-to-list 'ispell-skip-region-alist + '("\\\\begin{al[a-z]*}" . "\\\\end{al[a-z]*}")) + (add-to-list 'ispell-skip-region-alist + '("(\\[ebf\\]ll". "\\[eef\\])")) ; see the function + ; regexp-quote.. + ))) + + + (idledo-add-action + '(windmove-default-keybindings)) + ;;(idledo-add-action + ;;`(progn + ;; (load "chess-auto") + ;; nil)) + ;;(idledo-require 'scroll-in-place) + (idledo-require 'auto-recompile) + (idledo-add-action + '(progn + (require 'elder-beautify) + (elder-beautify-latex) + nil)) + + (idledo-add-action + (progn + (ignore-errors-my (elder-editing-modes)) + nil)) + + + ;; NB: that these are just autoload-definitions.. so their only use + ;; is really for fsbot. + (idledo-require 'calc) + (idledo-require 'calc-ext) + + ;;(idledo-require 'elder-set-keys) + + ;; at the very end.. we want this! + (idledo-add-action + '(progn + (icomplete-mode 1) + nil)) + + (idledo-require-now 'fetch) + + (idledo-require 'emacs-wiki) + + + (idledo-require 'boxquote) + (idledo-require 'assoc) + (idledo-require 'spam-stat) + ;; for fsbot + (idledo-require 'cc-mode) + (idledo-require 'custom) + + (idledo-require 'repeat) + (idledo-require 'thinks) + (idledo-add-action '(mwheel-install)) + (idledo-add-action + '(progn + (setq vel-verbosity 0) + (setq vel-echo-status-p t) + (require 'vel) + (setq-default vel-mode t))) + + (idledo-add-action + '(progn + (auto-compression-mode 1) + nil)) + (idledo-require 'windmove) + (idledo-add-action + '(windmove-default-keybindings)) + + + + (idledo-require 'parse-time) + ;;(idledo-add-action + ;;'(progn + ;; (require 'color-theme) + ;;(color-theme-parus) + ;;(color-theme-fischmeister) + ;;(color-theme-gray1) + ;;(utils-color-theme-nice-random-contextual) + ;;)) + + +;; (idledo-add-periodic-action-crude +;; '(progn +;; (setq idledo-verbosity -100) +;; (utils-color-theme-random-contextual) nil)) + + ;; (idledo-add-action + ;; '(utils-color-theme-nice-random-contextual)) + + (idledo-add-periodic-action-crude + '(progn + (require 'diary-lib) + (require 'appt) + (diary) + (message (format "%S" appt-time-msg-list)) + (appt-check) + + )) + + + ;; initialize woman.. + (idledo-add-action-at-end + '(when (sit-for 300) + (require 'woman) + (woman-file-name ""))) + + + + +;; (idledo-add-action +;; '(progn +;; (require 'remem) +;; (remem-toggle))) + + + + (idledo-add-action + '(progn + (tabbar-mode 1))) + + + (idledo-add-action + '(when window-system + (require 'highlight-tail) + (call-interactively 'highlight-tail-mode 1))) + + + (idledo-add-action '(dabbrev-hover-install t t)) + + + ;; top priority + (idledo-add-action + '(progn + (require 'fetch) + (miniedit-install) + (fetch-install-for-eshell) + (mkback-install-for-eshell) + nil)) + + + + + (idledo-add-action-at-end + '(when (sit-for 4200) + (when (or (not (fboundp 'gnus-alive-p)) + (not (gnus-alive-p))) + (spam-stat-doit-my)))) + + ) + + + + +;;;###autoload +(defun idledo-nullify () + (interactive) + (setq idledo-list nil) + (message "Idledo-list set to nil")) + + +(provide 'idledo) +(run-hooks 'idledo-after-load-hooks) +;;; idledo.el ends here diff --git a/elisp/erbot/contrib/lines.el b/elisp/erbot/contrib/lines.el new file mode 100644 index 0000000..f938c49 --- /dev/null +++ b/elisp/erbot/contrib/lines.el @@ -0,0 +1,586 @@ +;;; Lines.el -- help deal with data-files. OLDER VERSIONS SECURITY RISK +;;General Public License. +;; Time-stamp: <2004-11-21 11:11:45 deego> +;; GPL'ed under GNU'S public license.. +;; Copyright (C) Deepak Goel 2000 +;; Emacs Lisp Archive entry +;; Filename: lines.el +;; Author: Deepak Goel +;; Version: 0.3alpha + +;; OLDER VERSIONS OF LINES.EL AREx A SECURITY RISK. IF YOU USE THEM +;; TO FETCH FIELD FROM SOME ONE ELSE'S FILE , CRAFTY EXPRESSIONS CAN +;; MAKE YOUR EMACS EVALUATE ANYTHING, INCLUDING (SHELL-COMMAND "RM +;; -RF")). WE JUST THINK SO, WE HAVEN'T BEEN ABLE TO ACTUALLY COME UP +;; WITH AN EXPLOIT. SO USE version > 0.3 only + +;; EVEN THIS LIBRARY IS A POSSIBLE SECURITY RISK TOO IF YOU DISABLE +;; LINES-SAFE-P. + + + +(defvar lines-version "0.3alpha") + +;;; See also: forms.el (just saw it.. maybe it does all that lines.el +;; does ?) + + +;;;COMMENTARY: lines functions to help deal with data-files.. + +;;; Sometimes you want to use lines- functions instead of point- +;;; functions, even though it is slower. Particularly if u r dealing with +;;; parsing/editing a data-file, with, say data arranged in columns. +;;; lines.el defines most lines- counterparts of (point-max) (point-min) +;;; (point) (kill-region) etc. [for instance, emacs' default lines-what +;;; does not return an integer, which is what u may want during +;;; programming] + +;;; Lines.el also defines functions such as lines-get-fields (which gets +;;; all fields on this line, assuming they are lisp-expressions). + + +;;; BEFORE DOING ANYTHING WITH A BUFFER, please do not forget to call +;;;; lines-narrow-initial.. + + + +;;; CODE: +(eval-when-compile (require 'cl)) + +;;;###autoload +(defmacro lines-ignore-errors (&rest body) + "Copied from utils.el + +Like ignore-errors, but returns a list of body, and the +error... Improved for me by Kalle on 7/3/01: * used backquote: +something i was too lazy to convert my macro to.. * removed the +progn: condition-case automatically has one.. * made sure that +the return is nil.. just as it is in ignore-errors. " + (let ((err (gensym))) + `(condition-case ,err (list (progn ,@body) nil) + (error + (list nil ,err))))) + + +(defmacro lines-with-string (string &rest body) + "This macro treats the string as a buffer... basically, it +temporarily puts the string into a temp-buffer and runs body on it... +Note that when the body is being run, the point is (initially) at the +end of the buffer... " + `(with-temp-buffer + (insert ,string) + ,@body)) + + +(defun lines-empty-error () + "" + (error "Empty buffer. NOTE: M-x lines-warning.") +) + +(defun lines-warning () + "" + (let ((lines-loudness 1)) + (lines-message + "THIS program assumes that the proper form of the (data-) file you + examine ends in \\n. Anything in your file after the last \\n + will be ignored.")) +) + +;;;Mon Jan 15 04:09:30 2001 +;;;###autoload +(defun lines-widen () + (widen) +) + +;;;Mon Jan 15 03:32:05 2001 +;;;###autoload +(defun lines-narrow-initial (&optional ERR) + "Narrows such that the last char is a \\n +If the buffer survives, returns the size of the buffer, else nil. +Optional arg ERR results in ERR upon empty buffer. +FOR FUTURE EDITS: NEVER CALL OTHER LINES FUNCTIONS WITHIN THIS +FUNCTION, THIS ONE IS CALLED BY ALL OTHERS! + +" + (interactive) + (save-excursion + (let + ((lastn + (progn + (goto-char (point-max)) + (if + (search-backward "\n" nil t) + (+ (point) 1) + (point-min))))) + (narrow-to-region (point-min) lastn)) + (if (> (point-max) (point-min)) + (point-max) + nil)) +) + + +(defvar lines-loudness 0.6 "Tells you how noisy lines will be.. +Between 0 and 1 are meaningful values") + +(defun lines-message (&optional args) + (if (> lines-loudness 0.5) (apply 'message args)) +) + + +;;;###autoload +(defalias 'lines-what-line 'lines-what) + +;;;Wed Jan 17 00:11:38 2001 +;;;###autoload +(defun lines-what-narrowed (&optional given-point ) + " Like lines-what-line, except assumes a narrowed buffer. +Mostly like what-line, except: returns integer! +Tells you the current line.. If narrowed, assumes that the first +visible line is number 1.. As if the buffer were the entire buffer.. +Respects narrowing.. + +If DONTNARROW is t, assume that lines has already been narrowed.. +" + (interactive) + (let ((opoint (if given-point given-point (point))) + start) + (save-excursion + (goto-char (point-min)) + (beginning-of-line) + (setq start (point)) + (goto-char opoint) + (beginning-of-line) + (let + ((result + (if (/= start 1) + (1+ (count-lines start (point))) + (1+ (count-lines start (point)))))) + (if (interactive-p) + (message (format "%S" result))) + result))) + ) + +;;;Wed Jan 17 00:11:38 2001 +;;;###autoload +(defun lines-what(&optional given-point ) + " Mostly like what-line, except: returns integer! +Tells you the current line.. Ignores any narrowing when counting +lines, but does not disrupt the narrowing.. + +Hacked from the code of what-line, and i still don't understand some +stuff about the relevance of start here.. + +Thus, even if the buffer has been narrowed, lines-what will try to +return the true line-number.. Agreed this may slow things down for +large files, but makes sense to me.. if u don't like this, please +consider using lines-what-narrowed.. + +In the new emacsen, see also `line-at-pos'. +" + (interactive) + (let ((opoint (if given-point given-point (point))) + start) + (save-excursion + (goto-char (point-min)) + (beginning-of-line) + (setq start (point)) + (goto-char opoint) + (beginning-of-line) + (let + ((result + (if (/= start 1) + (1+ (count-lines 1 (point))) + (1+ (count-lines 1 (point)))))) + (if (interactive-p) + (message (format "%S" result))) + result))) + ) + + +;;;###autoload +(defalias 'lines-line-difference 'lines-difference) + +;;;###autoload +(defun lines-difference (start end ) + "Nothing more than the difference between the line at start and the +one at end. start and end are points.. See also the default +count-lines.. +If DONTNARROW is t, assume that lines has already been narrowed.. + +" + (save-excursion + (- (lines-what-line end ) + (lines-what-line start ))) + ) + + +;;;###autoload +(defalias 'lines-last-line-p 'lines-last-p) + +;;;###autoload +(defun lines-last-p () +" Tells if we are on the last line. " + (interactive) + (save-excursion + (end-of-line) + (equal (point) (point-max))) + ) + +;;;###autoload +(defalias 'lines-first-line-p 'lines-first-p) + +;;;###autoload +(defun lines-first-p () +"If DONTNARROW is t, assume that lines has already been narrowed.." + (interactive) + (save-excursion + (beginning-of-line) + (equal (point) (point-min))) +) + +;;;###autoload +(defalias 'lines-line-min 'lines-min) + +;;;###autoload +(defun lines-min () + "Like point-min.. +If DONTNARROW is t, assume that lines has already been narrowed.. + +" + (interactive) + (save-excursion + (goto-char (point-min)) + (lines-what-line (point) )) +) + +;;;###autoload +(defalias 'lines-line-max 'lines-max) + +(defun lines-max () + "Like point-max +If DONTNARROW is t, assume that lines has already been narrowed.. +" + (interactive) + (save-excursion + (goto-char (point-max)) + (lines-what-line (point) )) +) + + +;;;Tue Jan 16 11:26:30 2001 +;;;###autoload +(defalias 'lines-kill-this 'lines-kill-one) + +;;;Tue Jan 16 11:26:26 2001 +;;;###autoload +(defun lines-kill-one (&optional pt1 ) + (interactive) + (if (null pt1) + (setq pt1 (point))) + (lines-kill pt1 pt1 )) + + +;;;Tue Jan 16 11:50:55 2001 +;;;###autoload +(defun lines-kill-by-lines (&optional l1 l2 ) + "Kills from line1 to line2. If l1 or l2 is not specified, passes nil to +lines-kill.. + +Use this function only if necessary.. +This function calls line-kill.. which is the one to be preferred for +speed.. + +" + (save-excursion + (let + ((pt1 + (if (null l1) nil + (progn + (goto-line l1) + (point)))) + (pt2 + (if (null l2) nil + (progn + (goto-line l2) + (point))))) + (lines-kill pt1 pt2 ))) + ) + + + + +;;;Tue Jan 16 11:26:22 2001 +;;;###autoload +(defalias 'lines-kill-line 'lines-kill-one) + + +;;;###autoload +(defun lines-kill (&optional pt1 pt2 ) + "Kills this line completely. + +If PT1 and PT2 are specified, kills all lines through the line on PT1 +to line on PT2, inclusive. + +If neither PT1 is not specified, kills between point and mark. + +If only PT1 is specified, and PT2 is nil, takes PT2 to be PT1, +viz. kills the line on PT1. + + +If DONTNARROW is t, assume that buffer has already been narrowed +initially. + +If the second point to be killed is point-max, viz. is at a line we +don't consider to be on the buffer, this function appropriately +subtracts 1 from it so as to make it a part of the last legal line. + +" + (interactive) + (when (null pt1) + (setq pt1 (mark)) + (setq pt2 (point))) + (when (null pt1) ;;if mark is undefined.. + (setq pt1 pt2)) + (lines-swap-if-necc 'pt1 'pt2) ;;;ensure pt1 <= pt2. + (if (= pt2 (point-max)) (setq pt2 (- pt2 1))) + (if (= pt1 (point-max)) (setq pt1 (- pt1 1))) + (save-excursion + (let ((a1 + (progn + (goto-char pt1) + (beginning-of-line) + (point))) + (a2 + (progn + (goto-char pt2) + (end-of-line) + (+ (point) 1)))) + (kill-region a1 a2))) + ) + + + + + +(defun lines-backward-char () + "Moves one point back. Returns point if succeeds, else nil. +Never gives error! +Actually, i don't think we need this function.. +" + (interactive) + (let ((pt (point))) + (ignore-errors (backward-char 1)) + (if (/= (point) pt) + pt + nil)) + ) + +;;;Tue Jan 16 17:35:29 2001 +;;;###autoload +(defun lines-get-fields-by-lines (&optional line) + "Gets the field on the given line" + (lines-get-fields (lines-point-for-line line)) +) + + +;;;Thu Feb 8 14:48:47 2001 +;;;###autoload +(defun lines-point-for-line (line) + (save-excursion + (goto-line line) + (point))) + +(defcustom lines-safe-p t + "Set to t to revert to an unsafe, older but faster method of using + lines. ") + +;;;Mon Jan 15 02:42:19 2001 +;;;###autoload +(defun lines-get-fields (&optional pt ) + "Gets the fields if any on the current line, as a list. +Uses scan-sexps==> +will be affected by the value of parse-sexp-ignore-comments.. + +I think this needs to be totally rewritten.. to give the same results, +but much more efficiently.. +" + (interactive) + (let (fields fld buf fld-err err) + (if (null pt) (setq pt (point))) + (if (= pt (point-max)) + (goto-char (- pt 1))) + (save-excursion + (goto-char pt) + (let ((expr (lines-at-point )) + fields) + (cond + (lines-safe-p + (with-temp-buffer + (setq buf (current-buffer)) + (insert expr) + (goto-char (point-min)) + (while + (progn + (setq fld-err + (lines-ignore-errors (read buf))) + (setq fld (car fld-err)) + (setq err (cadr fld-err)) + (not err)) + (push fld fields))) + (setq fields (reverse fields))) + (t + (if (null expr) + (error "Attempt to get fields beyond the last RET ")) + (with-temp-buffer + (insert "(setq fields (quote (") + (insert expr) + (insert " \n)))") + (eval-buffer)))) + (if (interactive-p) (message "%S" fields)) + fields)))) +;;; (let ((doing (point-min))) +;;; (while doing +;;; (setq doing (scan-sexps doing 1)) +;;; (when doing +;;; (goto-char doing) +;;; (setq fields (cons (format "%S" (sexp-at-point)) fields)))))) +;;; (reverse fields)) +;;; ) + + +;;;Mon Jan 15 16:29:12 2001 +;;;###autoload +(defalias 'lines-line-at-point-verbatim 'lines-at-point-verbatim) + +;;;Mon Jan 15 03:02:17 2001 +;;;###autoload +(defun lines-at-point-verbatim ( ) + "Gives you just this one line at tthe current point. +this returns you the line along with the trailing \\n. Thus, if the +buffer ended up empty upon line-narrowing, this will return \"\". +If DONTNARROW is t, assume that lines has already been narrowed.. +" + (interactive) + (buffer-substring + (save-excursion + (beginning-of-line) + (point)) + (save-excursion + (forward-line 1) + (point))) + ) + +;;;Mon Jan 15 16:29:40 2001 +;;;###autoload +(defalias 'lines-line-at-point 'lines-at-point) + +;;;Mon Jan 15 03:55:05 2001 +;;;###autoload +(defun lines-at-point () + "Returns the line at this point, without the trailing \\newline. +If the buffer is empty, returns nil. +If DONTNARROW is t, assume that lines has already been narrowed.. +" + (interactive) + (let ((string (lines-at-point-verbatim ))) + (let ((len (length string))) + (if (> len 0) + (substring string 0 (- len 1)) + nil))) +) + + + + + +;;;Tue Jan 16 11:35:20 2001 +(defun lines-swap-if-necc (sym1 sym2) + "INTERNAL.. +Ensures that the value of symbol SYM1 if less than that of SYM2" + (when (> (eval sym1) (eval sym2)) + (let ((v2 (eval sym2))) + (set sym2 (eval sym1)) + (set sym1 v2))) +) + + + +;;;Tue Jan 16 15:50:31 2001 +;;;###autoload +(defun lines-narrow (&optional pt1 pt2 ) + "If called with no arguments, will assume point mark. If pt2 is +undefined, will take it to be the same as pt1. + +Will narrow buffer from the line starting pt1 to the line ending +pt2, inclusive. If pt1 is > pt2, will be swapped.. " + (interactive) + (if (null pt1) + (progn + (setq pt1 (mark)) + (setq pt2 (point)))) + (if (null pt2) + (setq pt2 pt1)) + (lines-swap-if-necc 'pt1 'pt2) + (save-excursion + (narrow-to-region + (progn + (goto-char pt1) + (beginning-of-line) + (point)) + (progn + (goto-char pt2) + (end-of-line) + (if (not (= (point-max) (point))) + (forward-char 1)) + (point)))) +) + +;;;Tue Jan 16 17:33:51 2001 +;;;###autoload +(defun lines-for-point (&optional pt) + "Line number on the point" + (interactive) + (if (null pt) (setq pt (point))) + (save-excursion + (goto-char pt) + (lines-what))) + +;;; 2002-05-14 T15:24:21-0400 (Tuesday) D. Goel +;;;###autoload +(defun lines-what-string (string) + (lines-with-string string + (lines-what))) + + + +;;; 2002-11-27 T15:21:04-0500 (Wednesday) D. Goel +;;;###autoload +(defun lines-get-fields-file (filename) + "Get fields from a file. A list per line. A list of such lists. +problem: barfs in the middle of comments..." + + (interactive "F") + (save-window-excursion + (let ((fields nil)) + (find-file filename) + (lines-narrow-initial) + (goto-char (point-min)) + (while (not (lines-last-p)) + (add-to-list 'fields (lines-get-fields)) + (next-line 1)) + (reverse fields)))) + +(defun lines-write-fields-file (fields filename) + (with-temp-file filename + (let ((left fields)) + (while left + (insert + (mapconcat + '(lambda (arg) (format "%S" arg)) + (car left) + "\t") "\n") + (pop left))))) + +(provide 'lines) + +;;;lines.el ends here.. diff --git a/elisp/erbot/contrib/mkback.el b/elisp/erbot/contrib/mkback.el new file mode 100644 index 0000000..4c93c2b --- /dev/null +++ b/elisp/erbot/contrib/mkback.el @@ -0,0 +1,601 @@ +;;; mkback.el---advanced assistance to manual archiving/backup of files. +;; Time-stamp: <2004-11-29 17:03:37 deego> +;; Copyright (C) 2002 D. Goel +;; Copyright (C) 2002 Free Software Foundation, Inc. +;; Emacs Lisp Archive entry +;; Filename: mkback.el +;; Package: mkback +;; Author: Deepak Goel +;; Keywords: backup project +;; Version: 1.5dev +;; For latest version: + +(defvar mkback-home-page + "http://www.gnufans.net/~deego/emacspub/lisp-mine/fastron/") + +;; Namespace: mkback-, + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; uncoment this bash script, tweak if needed and save it to, say, +;; ~/bin/mkback. From then on, commands like mkback * will work +;; (interactively) from bash. + +;;; #!/bin/bash + +;;; emacs -nw -l ~/.emacs --eval="(require 'mkback)" \ +;;; --eval="(require 'mkback)" \ +;;; --eval="(mkback-from-batch $*)" + +;; (with thanks to Damian Elmes), if you prefer aliases: (untested) +;; alias mkback="emacs -batch -nw --eval=\"(progn (require 'mkback) (mkback-from-batch $*)\"" + + +(eval-when-compile (require 'cl)) + +;; Quick start: +(defvar mkback-quick-start + "See M-x mkback-introduction. + +Drop mkback.el somewhere in your load-path and add to your .emacs. +\(require 'mkback\) +\(mkback-install-for-eshell\) + + +For advanced users who use autoload mkback, simply add this to .emacs +instead of the above: +\(defvar mkback-after-load-hooks\) +\(add-hook 'mkback-after-load-hooks 'mkback-install-for-eshell\) + + +You should now have access to M-x mkback in emacs *and* in the +command-line mkback in eshell. + +Note that the mkback-install-for-eshell step is optional. Mkback will +work in eshell even without this step, but this step makes it do good +things for eshell---see commentary. + +For bash access to mkback, see the bash script above. Try the various +defcustoms to customize." ) + +;;;###autoload +(defun mkback-quick-start () + "Provides electric help regarding `mkback-quick-start'." + (interactive) + (with-electric-help + '(lambda () (insert mkback-quick-start) nil) "*doc*")) + +;;; Introduction: +;; Stuff that gets posted to gnu.emacs.sources +;; as introduction +(defvar mkback-introduction + "mkback searches for a backup/ folder in the +file's directory, or its parent directory, or the grandparent +directory , and so on. It then backs up the requested file with +a mirroring of the relative directory structure, and the +current date/time information. The file in question need not be a text +file. + +The primary functions from emacs are M-x mkback and M-x mkback-buffer. +Add (mkback-install-for-eshell), and you have an eshell-optimized +command called mkback. Finally, you can use mkback from bash by +calling emacs in batch-mode, See the included batch-script at the top +of this file. + +Only tested on GNU/Linux. Designed in a platform-independent +way--should even work on VMS. Tested with Emacs21.2 only.Type M-x +mkback-quick-start and M-x mkback-commentary for more details. +" ) + + + + + +;;;###autoload +(defun mkback-introduction () + "Provides electric help regarding `mkback-introduction'." + (interactive) + (with-electric-help + '(lambda () (insert mkback-introduction) nil) "*doc*")) + +;;; Commentary: +(defvar mkback-commentary + "Please M-x mkback-quick-start and M-x mkback-introduction first. + +Optionally, add (mkback-install-for-eshell) to .emacs. That makes +mkback do nice things--- + +* in eshell, typing mkb TAB some-file-name ENTER works. +* in eshell, typing mkb TAB ENTER works.. + +Note that this tab-completion may not work the very first time if you +follow the autoload-route to mkback-install-for-eshell. + +See the various defcustoms, hooks for customization. + + +I periodically made backups of the files I used, annotating the +backups with today's dates. Here are some design decisions: + +* The folder is called backup but customizable. + +* Sometimes, one does not want a folder to be cluttered by a huge + backup/. Consider this: project/folder1/ project/folder2/ and + project/folder3/. You often need to tar up your project/ to deliver + it to folks. Now, you don't want folders like + project/folder1/backup/ existing. + + In such a case, you would rather mkback a file like + project/folder1/file.lisp into + project/backup/folder1/file-date.lisp. + + Thus, mkback looks in current folder and in ancestors for + backup/'s. + + +* I did not want to name foo.lisp as foo.lisp-date, because that +changes extension, thus emacs etc. had a hard time recognizing the +backup-file's type. if i ever wanted to browse the backuped file. So +I preferred foo-date.lisp + +* Most of the time, I would not make more than once backup in a day, +but if I did, I could call the new one foo-date-a.lisp etc. + +* If the date is listed in yyyy-mm-dd format, then an alphabetical +directory listing is \(mostly\) also a time-ordered directory listing. +Pretty convenient. I have started naming all my dates in this +format. One can customize the date-format. + +* I am almost always in eshell when I do an archiving. So, there we go.. + + +If you are working on a patch or new feature, it is recommended that +you download the latest mkback from mkback-home-page first, and work +on that. + + +" +) + +;;;###autoload +(defun mkback-commentary () + "Provides electric help regarding `mkback-commentary'." + (interactive) + (with-electric-help + '(lambda () (insert mkback-commentary) nil) "*doc*")) + +;;; History: + +;;; Bugs: + + + + + + +;;; New features: +(defvar mkback-new-features + " + + New since 1.4 + ============================================ + + * By default, the file-modification time of the backup-ed file is + now same as that of the original file. + + * By default, The backuped file's name now stores both the + file-modification-time as well as the time at which the backup is + made. + + + +" +) + + +;;;###autoload +(defun mkback-new-features () + "Provides electric help regarding `mkback-new-features'." + (interactive) + (with-electric-help + '(lambda () (insert mkback-new-features) nil) "*doc*")) + +(defvar mkback-version "1.5dev") + +;;========================================== +;;; Code: + + +(defcustom mkback-chase-links-method 'dir + "How to chase symlinks +This can take 4 values: +'dir, 'file 'all and 'none. +'file: only chase file links, +'all: chase all links, +'none: don't chase links, +The author likes the 'dir option. ") + +(defvar mkback-before-load-hooks nil) +(defvar mkback-after-load-hooks nil) +(run-hooks 'mkback-before-load-hooks) + + +(defcustom mkback-create-new-backup-dir-p nil "") +(defcustom mkback-dir "backup" "") + +(defcustom mkback-time-format + "-%Y%m%d-%H%M-%S" + "The string to use for time-format.. More generally, any expression +that evals to a valid string.. +The current format is chosen to be windoze compatible. +The earlier format was: + -%Y-%m-%d:%H%M:%S" +) + + +(defcustom mkback-time-format-modtime + "-%Y%m%d-%H%M-%S--" + "The string to use for time-format.. More generally, any expression +that evals to a valid string.. +We get the last-modified-time of the file and use it here. ") + + +(defcustom mkback-loudness 100 + "suggested: Anywhere from 0 to 100" +) +(defcustom mkback-interactivity 100 + "Suggested: Anywhere from -100 to 100.. +if this number is too low, mkback will ask you for less and less +confirmations. +0 is the recommended value once you are familiar with mkback. " +) + +(defvar mkback-err nil "internal") +(defcustom mkback-default-get-backup-dir 'mkback-get-backup-dir + "") +(defcustom mkback-default-get-backup-path-name 'mkback-get-backup-path-name + "") +(defcustom mkback-default-get-backup-file-name 'mkback-get-backup-file-name + "") + + + +(defmacro mkback-withit (expr &rest rest) + "Caution: var-capture by its very nature.." + `(let ((it ,expr)) + ,@rest)) + +(defcustom mkback-max-depth 4 + "Is an integer.. this is the max number of ancestors to ascend to look +for an archive directory. + +A value of nil here means: no max number.. Nil is not currently +recommended as can potentially cause infinite looping if no backup/ +exists in the entire ancestory.") + + +(defcustom mkback-keep-time-p t + "When true, gives the destination file the same last-modified-time + as that of the original.") + + +;;;###autoload +(defun mkback-get-backup-dir (dir &optional suffix depth) + "An example of arguments is: +\(mkback-get-backup-dir /home/aa/bb dd\). +Then, this function looks for a backup directory in /home/aa/bb. If +it exists, then this function returns: /home/aa/bb/backup/dd. +Else this function calls +\(mkback-get-backup-dir \"/home/aa\" \"dd/bb\" \"ff\" \). + +See what i mean? If no backup/ exists here, then a backup/ exists in a +parent directory.. but then, you want to create aa/ first in that +directory when creating backup, don't you? So, this function returns +that... + +Returns nil if can't find any. +" + (unless depth (setq depth 0)) + (if (and mkback-max-depth (> depth mkback-max-depth)) + nil + (progn + ;;(unless dir (setq dir default-directory)) + (unless suffix (setq suffix "")) + (mkback-message 25 "Considering dir= %S and suffix=%S" dir suffix) + (let* ((dir-unslashed (expand-file-name "" dir)) + (dir-backup (expand-file-name mkback-dir dir)) + (dir-backup-suf (expand-file-name suffix dir-backup))) + (if + (and (file-exists-p dir-backup) + (file-directory-p dir-backup)) + dir-backup-suf + (mkback-get-backup-dir + ;; parent dir + (file-name-directory dir-unslashed) + ;; increase suffix + (mkback-withit (file-name-nondirectory dir-unslashed) + (if (equal suffix "") + it + ;; commenting this out.. should NOT use / + ;;(concat it "/" suffix) + (concat (file-name-as-directory it) suffix) + )) + (+ depth 1))))))) + + + +(defun mkback-chase-links (file) + (case mkback-chase-links-method + ('dir + (let ((dir (or + (file-name-directory file) + ;; else take the current directory... this comes in + ;; handy when calling mkback-from-batch. + default-directory ))) + ;; since we supply default-directory, + ;; this if is now mute... but let's keep it. + (if dir + (expand-file-name (file-name-nondirectory file) + (file-truename dir)) + file))) + ('file (file-chase-links file)) + ('all (file-truename file)) + (t file))) + +;;;###autoload +(defun mkback-get-backup-path-name (file &optional backup-dir + ) + "Looks around for a suitable backup/ directory nearby and returns a +suitable backup pathname. + +this is one heck of a powerful function.. + +SHOULD REALLY USE the function file-name-directory! +" + (setq file (mkback-chase-links file)) + + (let + ((initdir + (file-name-directory (expand-file-name file)))) + (unless backup-dir + (setq backup-dir (funcall mkback-default-get-backup-dir + initdir))) + (if (not backup-dir) + (if mkback-create-new-backup-dir-p + (setq backup-dir + (expand-file-name mkback-dir + initdir)) + (error "No archi(v)e directory exists here or nearby. ")))) + + (funcall mkback-default-get-backup-file-name file backup-dir)) + + + +(defun mkback-get-backup-file-name (file dir) + "File is the original file, dir is the destination directory. +This function will thus rename file with date appended, and then +append the same to the destination directory. " + (let* + ((baseinit (file-name-sans-extension + (file-name-nondirectory file))) + (extinit (file-name-extension file)) + (base + (if (string= baseinit "") + (concat "." extinit) baseinit)) + (ext2 + (if (string= baseinit "") + nil extinit)) + (raw-name-file + (concat + base + (format-time-string + (eval mkback-time-format-modtime) + (nth 5 (file-attributes file))) + (format-time-string (eval mkback-time-format)) + )) + (raw-name + (expand-file-name + raw-name-file + dir)) + (ext + (mkback-withit ext2 + (if (null it) "" + (concat "." it ))))) + (while + (file-exists-p (concat raw-name ext)) + (setq raw-name (concat raw-name "a"))) + (concat raw-name ext))) + + +(defun mkback-message (points &rest args) + (when (> (+ points mkback-loudness) 50) + (apply #'message args))) + + + +;;; 2002-05-03 T09:41:03-0400 (Friday) D. Goel +(defun mkback-no-errors (file) + (mkback-ignore-errors (mkback file))) + + +(defvar mkback-after-backup-hook nil + "Each of the functions in this hook shall take two arguments: the +full name of the original file and the ful name of the backuped +file. ") + +(defcustom mkback-gzip-p nil + "Whether to gzip the mkbacked files. More generally, any post-backup +action to perform on the backuped file. ") + +(defcustom mkback-gzip-expression + '(when + (> (nth 7 (file-attributes it)) 250) + (shell-command (format "gzip %s" it))) + "Use it for the filename here. The current expression works only on +gnulinux type systems.") + +;;;###autoload +(defun mkback (&optional file) + "Backup file/files. +With no argument, will prompt for file. If file is a list of files instead of +one file, will loop over them. + +When file is a single file, Returns nil if backup fails, returns +non-nil otherwise. + +When file is a list of files, returns the list of such results. +" + (interactive "F") + (unless file + (setq file (read-file-name "File: "))) + (unless file (error "No filaname supplied to mkback: nil")) + (if (listp file) + (mapcar #'mkback-no-errors file) + (progn + (unless (file-exists-p file) + (error "File does not exist: %S" file)) + (when (file-directory-p file) + (error "Currently, can archive only files, not directies: %S" file)) + (mkback-withit + (funcall mkback-default-get-backup-path-name file) + (let* ((dir (file-name-directory it)) + (dir-existsp (file-exists-p dir)) + (failed nil)) + (unless dir-existsp + (if (mkback-y-or-n-p 50 + (format "Create directory %S" dir)) + (make-directory dir t) + (mkback-message 99 "Not creating directory!"))) + (setq dir-existsp (and (file-exists-p dir) (file-directory-p dir))) + (setq failed (not dir-existsp)) + (unless failed + (if + (mkback-y-or-n-p 0 + (format "Copy %S to %S" (file-name-nondirectory file) + it)) + (progn + (copy-file file it nil mkback-keep-time-p)) + (setq failed t))) + (run-hook-with-args 'mkback-after-backup-hook file it) + (setq failed (not (file-exists-p it))) + (when mkback-gzip-p + (ignore-errors + (eval + mkback-gzip-expression))) + (if failed + (mkback-message 99 "File not created: %s " it) + (mkback-message 99 "Backup (now) exists:\n %s" it)) + (not failed)))))) + + + + +;;;###autoload +(defun mkback-install-for-eshell () + (interactive) + (defalias 'eshell/mkback 'mkback)) + + +(defmacro mkback-ignore-errors (&rest body) + "\(Programmer: This function should track my ignore-errors-my. \) + +Like ignore-errors, but tells the error.. +Improved for me by Kalle on 7/3/01: + * used backquote: something i was too lazy to convert my macro to.. + * removed the progn: condition-case automatically has one.. + * made sure that the return is nil.. just as it is in ignore-errors. " + `(condition-case mkback-err (progn ,@body) + (error + (ding t) + (ding t) + (ding t) + (message "IGNORED ERROR: %s" (error-message-string mkback-err)) + (sit-for 1) + nil))) + + + + +;;; 2002-05-03 T11:05:43-0400 (Friday) D. Goel +(defun mkback-y-or-n-p (add &rest args) + (if (> (+ add mkback-interactivity) 50) + (apply 'y-or-n-p args) + t)) + + +;;; 2002-05-03 T11:07:10-0400 (Friday) D. Goel +;;;###autoload +(defun mkback-buffer () + (interactive) + (mkback-withit + (buffer-file-name) + (if it (mkback it) + (mkback-message 0 "Buffer has no associated file: %S" + (buffer-name))))) + +;;; 2002-05-03 T11:10:32-0400 (Friday) D. Goel +;;;###autoload +(defun mkback-buffer-doit () + (interactive) + (let ((mkback-interactivity -100)) + (mkback-buffer))) + + +(defmacro mkback-from-batch (&rest files) + "The files get passed to emacs as symbols.. we need to simply format +them.." + `(mkback + (mkback-symbols-to-strings (quote ,files)))) + +(defun mkback-symbols-to-strings (files) + (cond + ((null files) nil) + ((listp files) (mapcar 'mkback-symbols-to-strings files)) + (t (format "%s" files)))) + + + + + +(defmacro mkback-from-batch-doit (&rest files) + "The files get passed to emacs as symbols.. we need to simply format +them.." + `(let ((mkback-interactivity -100)) + (mkback + (mkback-symbols-to-strings (quote ,files))))) + + +(defun mkback-symbols-to-strings (files) + (cond + ((null files) nil) + ((listp files) (mapcar 'mkback-symbols-to-strings files)) + (t (format "%s" files)))) + + +;; these 2 provided for historical compatibility for the next few versions.. +;; and THEY WILL BE REMOVED SOON.. +(defalias 'mkback-this-buffer 'mkback-buffer) +(defalias 'mkback-this-buffer-doit 'mkback-buffer-doit) + +(provide 'mkback) +(run-hooks 'mkback-after-load-hooks) + + + +;;; mkback.el ends here diff --git a/elisp/erbot/contrib/oct.el b/elisp/erbot/contrib/oct.el new file mode 100644 index 0000000..6247aec --- /dev/null +++ b/elisp/erbot/contrib/oct.el @@ -0,0 +1,540 @@ +;;; oct.el --- some GNU octave functions in elisp. +;; Time-stamp: <2003-06-25 12:35:50 deego> +;; Copyright (C) 2002 D. Goel +;; Emacs Lisp Archive entry +;; Filename: oct.el +;; Package: oct +;; Author: D. Goel +;; Keywords: GNU Octave, matlab +;; Version: 0.0 +;; Author's homepage: http://deego.gnufans.org/~deego +;; For latest version: + +(defconst oct-home-page + "http://gnufans.net/~deego/emacspub/lisp-mine/oct") + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + + +;; Quick start: +(defconst oct-quick-start + "Help..." +) + +(defun oct-quick-start () + "Provides electric help from variable `oct-quick-start'." + (interactive) + (with-electric-help + '(lambda () (insert oct-quick-start) nil) "*doc*")) + +;;; Introduction: +;; Stuff that gets posted to gnu.emacs.sources +;; as introduction +(defconst oct-introduction + "I love the brevity/flexibility of GNU octave. oct.el implements +\(inefficiently) a *few* common octave functions. Thus, any of the +arguments to oct-+ can be a number, a vector, or a matrix. + +For oct.el, an example of row vector is '(1 2 3), a column vector is +'((1) + (2) + (3)) + +and a matrix is +'( (1 2 3) + (2 3 4)) + +Each of oct.el's functions, oct-foo seeks to perform the exact same +behavior as that of the corrresponding octave function foo. Many are +incomplete---i.e. do not handle all possible cases of vectors/matrices +for their arguments. For documentation on any ocave function, just +(apt-get) install octave2.1*, fire up octave, and type help foo; also +look at octave info files. + +There's no matrix-multiplication here (yet). BTW, there was one +matrix.el posted here a few years ago. + +If you are not into GNU Octave, probably the only useful function here +might be some utilitiess like oct-corr (correlation) or oct-std +\(standard deviation) --- viz. just apply them to lists. + +Octav is huge, and growing. So, this library will never be complete, +nor am I working currently on it. Which is why i should go ahead and post +whatever I have here. :) " ) + +;;;###autoload +(defun oct--introduction () + "Provides electric help from variable `oct--introduction'." + (interactive) + (with-electric-help + '(lambda () (insert oct--introduction) nil) "*doc*")) + +;;; Commentary: +(defconst oct--commentary + " +matrix [1 2 3; 4 5 6; 7 8 9] should be represented as +\((1 2 3) (4 5 6) (7 8 9)) here. + +As in octave, a matrix [1] can be represented equivalently as 1, (1) +or ((1)). + +Note that we emulate octave and NOT the matlab-like 'octave +--traditional', and the two do differ in some rare aspects. " ) + + +(defun oct--commentary () + "Provides electric help from variable `oct--commentary'." + (interactive) + (with-electric-help + '(lambda () (insert oct--commentary) nil) "*doc*")) + +;;; History: + +;;; Bugs: + +;;; New features: +(defconst oct--new-features + "Help..." +) + +(defun oct--new-features () + "Provides electric help from variable `oct--new-features'." + (interactive) + (with-electric-help + '(lambda () (insert oct--new-features) nil) "*doc*")) + +;;; TO DO: +(defconst oct--todo + "Help..." +) + +(defun oct--todo () + "Provides electric help from variable `oct--todo'." + (interactive) + (with-electric-help + '(lambda () (insert oct--todo) nil) "*doc*")) + +(defconst oct-version "0.0") +(defun oct-version (&optional arg) + "Display oct's version string. +With prefix ARG, insert version string into current buffer at point." + (interactive "P") + (if arg + (insert (message "oct version %s" oct-version)) + (message "oct version %s" oct-version))) + +;;========================================== +;;; Requires: +(eval-when-compile (require 'cl)) + +;;; Code: + +(defgroup oct nil + "The group oct." + :group 'applications) +(defcustom oct-before-load-hooks nil + "Hooks to run before loading oct." + :group 'oct) +(defcustom oct-after-load-hooks nil + "Hooks to run after loading oct." + :group 'oct) +(run-hooks 'oct-before-load-hooks) + +(defcustom oct-verbosity 0 + "How verbose to be. +Once you are experienced with this lib, 0 is the recommended +value. Values between -90 to +90 are \"sane\". The +rest are for debugging." + :type 'integer + :group 'oct) +(defcustom oct-interactivity 0 + "How interactive to be. +Once you are experienced with this lib, 0 is the recommended +value. Values between -90 and +90 are \"sane\". The rest are for +debugging." + :type 'integer + :group 'oct) +(defcustom oct-y-or-n-p-function 'oct-y-or-n-p + "Function to use for interactivity-dependent `y-or-n-p'. +Format same as that of `oct-y-or-n-p'." + :type 'function + :group 'oct) +(defcustom oct-n-or-y-p-function 'oct-y-or-n-p + "Function to use for interactivity-dependent `n-or-y-p'. +Format same as that of `oct-n-or-y-p'." + :type 'function + :group 'oct) +(defun oct-message (points &rest args) + "Signal message, depending on POINTS andoct-verbosity. +ARGS are passed to `message'." + (unless (minusp (+ points oct-verbosity)) + (apply #'message args))) +(defun oct-y-or-n-p (add prompt) + "Query or assume t, based on `oct-interactivity'. +ADD is added to `oct-interactivity' to decide whether +to query using PROMPT, or just return t." + (if (minusp (+ add oct-interactivity)) + t + (funcall 'y-or-n-p prompt))) +(defun oct-n-or-y-p (add prompt) + "Query or assume t, based on `oct-interactivity'. +ADD is added to `oct-interactivity' to decide whether +to query using PROMPT, or just return t." + (if (minusp (+ add oct-interactivity)) + nil + (funcall 'y-or-n-p prompt))) + +;;; Real Code: + +(defun oct--make-matrix (element &optional n m ) + (unless m (setq m 1)) + (unless n (setq n 1)) + (setq m (round m)) + (setq n (round n)) + (cond + ((or (< m 0) (< n 0)) + (error " zeros: can't create a matrix with negative dimensions")) + ((or (= m 0) (= n 0)) + nil) + (t (make-list n + (make-list m element))))) + + +(defun oct--vectorize (element) + "Converts an elt to a list, if isn't one already" + (let* ((eltt (oct--matricize element)) + (size (oct-size eltt)) + (numrows (first size)) + (numcols (second size))) + (cond + ((= numrows 1) (first eltt)) + ((= numcols 1) (mapcar 'first eltt)) + (t (error "This is a matrix. Can't vectorize. "))))) + + +(defun oct--elementize (element) + (let* ((eltt (oct--matricize element)) + (size (oct-size eltt))) + (unless (equal size '(1 1)) + (error "not an element")) + (caar eltt))) + +(defun oct--matricize (eltt) + "will convert a vector to a Nx1 matrix. As does octave: +a(1)=1, a(2)=1, size(a). Does not check for sizes for lists." + (cond + ((numberp eltt) (list (list eltt))) + ((null eltt) '(())) + ((listp eltt) + (let ((fir (first eltt))) + (cond + ((null fir) + (if (every 'null eltt) '(()) + (error "Unequal sizes"))) + ((every 'numberp eltt) + (mapcar '(lambda (arg) (list arg)) eltt)) + ((every 'listp eltt) + eltt) + (t (error "How could i have reached here?"))))) + (t (error "shouldn't have reached here. internal oct.el error")))) + +(defun oct--minimize (elt &optional vecp) + "When rowp is true, will vectorize its stuff when possible." + (let* ((eltma (oct--matricize elt)) + (sz (oct-size eltma))) + (cond + ((equal sz '(1 1)) + (caar eltma)) + ((and vecp (= (second sz) 1)) + (mapcar + (lambda (arg) (first arg)) + eltma)) + ((and vecp (= (first sz) 1)) + (first eltma)) + (t eltma)))) + +(defun oct--equal (&rest args) + (cond + ((<= (length args) 1) t) + (t (let + ((fir (first args))) + (every 'identity + (mapcar '(lambda (arg) + (equal arg fir)) + (cdr args))))))) + +(defun oct--operator (function args default) + (cond + ((null args) default) + ((= (length args) 1) (first args)) + (t + (let* ((a (first args)) + (b (second args)) + (c (oct--matricize a)) + (d (oct--matricize b)) + (sizec (oct-size a)) + (sized (oct-size d))) + (cond + ((equal sizec '(1 1)) + (setq c (oct--make-matrix (caar c) (first sized) (second + sized)))) + ((equal sized '(1 1)) + (setq d (oct--make-matrix (caar d) (first sizec) (second + sizec)))) + (t 'noop)) + (oct--operator + function + (cons (oct--mapmatrix function c d) (cddr args)) + default))))) + +(defun oct--mapmatrix (function mat1 mat2) + "used by oct--operator" + (mapcar* + '(lambda (list1 list2) + (mapcar* function list1 list2)) + mat1 mat2)) + + + +;;;###autoload +(defun oct--remove-minus-in-string (str) + "Replace - to minus in string. +Octave can't handle filenames with - in them. " + (with-temp-buffer + (insert str) + (goto-char (point-min)) + (while (search-forward "-" nil t) + (replace-match "Minus" nil t)) + (buffer-substring-no-properties (point-min) (point-max)))) + +;;;==================================================== + +(defun oct-zeros (&optional n m) + (oct--make-matrix 0 n m)) +(defun oct-ones (&optional n m) + (oct--make-matrix 1 n m)) + + +(defun oct-sum (x &optional n) + " +if n = 1, sum along columns. 1 is the default. +if n = 2, sum along rows. + +If no n provided, and x happens to be a vector along any dimension, +perform the sum in any case. " + (oct--minimize + (let* + ((xx (oct--matricize x)) + (size (oct-size xx)) + (nrows (first size)) + (ncols (second size))) + (when (null n) + (cond + ((= nrows 1) (setq n 2)) + (t (setq n 1)))) + (cond + ((= n 1) + (list + (apply + 'mapcar* + (lambda (&rest elements) + (apply '+ elements)) + xx))) + ((= n 2) + (mapcar + '(lambda (list) + (list (apply '+ list))) + xx)) + (t (error "Improper second argument to oct-sum. ")))))) + + + +(defun oct-size (a &optional n) + "When given N, returns row dimension if N = 1, else column +dimension. " + (cond + ((equal n 1) + (first (oct-size a ))) + ((equal n 2) + (second (oct-size a))) + (t + (let* + ((b (oct--matricize a)) + (sizes (mapcar 'length b)) + (numcolumns (first sizes))) + (unless + (oct--equal numcolumns) (error "unequal sizes")) + (list (length sizes) numcolumns))))) + +(defun oct-rows (a) + (oct-size a 1)) +(defun oct-columns (a) + (oct-size a 2)) + +(defun oct-length (a) + (apply 'max (oct-size a))) + + +(defun oct-.* (&rest args) + (oct--operator '* args 1)) + +(defun oct-/ (x n) + "not general enough yet. n can only be a number. +moreover, converts everything to float." + (oct--operator + (lambda (a b) + (/ (float a) b)) + (list x n) + 1)) + +(defun oct-+ (&rest args) + (oct--operator '+ args 0)) +(defalias 'oct-add 'oct-+) + +(defun oct-- (&rest args) + (oct--operator + '- + (if (= (length args) 1) + (cons 0 args) + args) + 0)) +(defalias 'oct-subtract 'oct--) +(defalias 'oct-sub 'oct--) + + + + + +(defun oct-corr (x y) + "This does need 2 matrices as of right now. + + +In fact, currently, just takes a list x and a list y and returns the +corr coeff. + +When implemented, will be Just like octave: +If X is has dimensions M and Nx, and Y has dimensions M and Ny, +then the returned matrix Z has dimensions Nx and Ny. +And Z(Nx, Ny) = corr bet. X(:,Nx) and between Y(:,Ny). " + + (let* + ((xa (oct--vectorize x)) + (ya (oct--vectorize y)) + (n (oct-length xa)) + (nn (float n)) + (sumxy (oct--elementize (oct-sum (oct-.* xa ya)))) + (sumxx (oct--elementize (oct-sum (oct-.* xa xa)))) + (sumyy (oct--elementize (oct-sum (oct-.* ya ya)))) + (sumx (oct--elementize (oct-sum xa))) + (sumy (oct--elementize (oct-sum ya)))) + (/ (- sumxy (/ (* sumy sumx) nn)) + (sqrt + (* (- sumxx (/ (* sumx sumx) nn)) + (- sumyy (/ (* sumy sumy) nn))))))) + + +(defun oct-complement (x) + "is like the ' in octave" + (let ((xx (oct--matricize x)) + (yy nil)) + (while (caar xx) + (push + (mapcar 'first xx) yy) + (setq xx (mapcar 'cdr xx))) + (reverse yy))) + + +(defun oct-sumsq (x) + "Works only for vectors right now." + (let ((xv (oct--matricize x))) + (oct--elementize (oct-sum (oct-.* xv xv))))) + + +(defun oct-mean (x) + " +no second argument yet. works only for vectors." + (let ((xv (oct--vectorize x))) + (oct--minimize + (oct-/ (oct-sum x) (oct-length x))))) + + +(defun oct-sqrt (x) + "only numbers as of now." + (let ((xe (oct--elementize x))) + (sqrt xe))) + +(defun oct-std (x) + (let* ((xv (oct--vectorize x)) + (mean (oct-mean xv)) + (nm1 (- (oct-length xv) 1))) + (sqrt + (/ (float (oct-sumsq (oct-- xv mean))) + nm1)))) + + +(defun oct-tanh (x) + (cond + ((listp x) + (mapcar 'oct-tanh x)) + ((> 1 x) + (/ + (float (- 1 (exp (* -2 x)))) + (float (+ 1 (exp (* -2 x)))))) + (t + (/ + (float (- (exp (* 2 x)) 1)) + (float (+ (exp (* 2 x)) 1)))))) + + +(defun oct-atanh (x) + (cond + ((listp x) + (mapcar 'oct-atanh x)) + (t + (* 0.5 + (log (/ (float (+ 1 x)) + (- 1 x))))))) + + + +(defun oct-colon (x y) + (if (<= x y) + (cons x (oct-colon (+ x 1) y)) + nil)) + +(defun oct-sign (x) + (if (listp x) + (mapcar 'oct-sign x) + (cond + ((> x 0) 1) + ((< x 0) -1) + (t 0)))) + + + +(provide 'oct) +(run-hooks 'oct-after-load-hooks) + + + +;;; oct.el ends here diff --git a/elisp/erbot/contrib/shs.el b/elisp/erbot/contrib/shs.el new file mode 100644 index 0000000..b2b3311 --- /dev/null +++ b/elisp/erbot/contrib/shs.el @@ -0,0 +1,552 @@ +;;; shs.el --- facilitate SHell Scripting through Emacs. +;; Time-stamp: <2006-05-08 00:00:17 deego> +;; Copyright (C) 2005 D. Goel +;; Emacs Lisp Archive entry +;; Filename: shs.el +;; Package: shs +;; Author: D. Goel +;; Keywords: +;; Version: 0.0 +;; URL: http://gnufans.net/~deego +;; For latest version: + +(defconst shs-home-page + "http://gnufans.net/~deego/emacspub/lisp-mine/shs/") + +;; Copyright (C) 2005 D. Goel + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + + + +;; sh.el, posted here a few days ago has been renamed to shs.el since +;; there exists another sh.el -- shs stands for SHell-Script. + +;; SHS: Shs aims to facilitate free mixing of elisp with bash: free +;; calls to elisp code from bash shell scripts and calls to other bash +;; scripts from that elisp code, which may again call elisp code and +;; so on, all the while doing the right things as regards bash's error +;; codes, stderr, stdout, etc. + +;; Moreover, one shouldn't need to exit emacs just to pipe one emacs +;; script's call to another. + +;; Finally, elisp code should also be able to run independently of +;; bash in running emacsen. + +;; Provides basic setup for emacs scripting. To the beginning of all +;; emacs shell-scripts, don't forget to add (add-to-list 'load-path +;; directory) and (require 'shs). Use shs as a convenient way to call +;; shell-commands from the script. Provides a tutorial on elisp-based +;; shell-scripting. + + +(eval-when-compile (require 'cl)) + + +;; The most common functions to use are: shs-process (shsp), shs-shell +;; (shsh). + +;; Alt, using shell command: shsh. +;; Best way to show messages: shs-message. + +;; Your code should automatically run fine, both in shellscripts as +;; well as emacs: + + +;; The easiest way to pass messages would be to (message) or +;; (princ). However, that makes it somewhat meaningless in running +;; emacs, so prefer using (shs-message) instead. When using +;; shs-message in running Emacs, all these messages go to *SHS* +;; buffer, which you'll finally want to switch to and see. + + + +;; See also: + + +;; Quick start: +(defconst shs-quick-start + "Help..." +) + +(defun shs-quick-start () + "Provides electric help from variable `shs-quick-start'." + (interactive) + (with-electric-help + '(lambda () (insert shs-quick-start) nil) "*doc*")) + +;;; Introduction: +;; Stuff that gets posted to gnu.emacs.sources +;; as introduction +(defconst shs-introduction + " \(sh.el, posted here a few days ago has been renamed to shs.el +since there exists another sh.el). + +shs stands for SHell-Scripting. + +I am an utter novice at shell scripting, so suggestions and comments +are most welcome, and please forgive any mistakes in shs. shs aims to +facilitate free mixing of elisp with bash: free calls to elisp code +from bash shell scripts and calls to other bash scripts from that +elisp code, which may again call elisp code and so on, all the while +doing the right things as regards bash's error codes, stderr, stdout, +etc. + +Moreover, one shouldn't need to exit emacs just to pipe one emacs +script's call to another. + +Finally, ideally, that elisp code should also be able to run +independently of bash in running emacsen. All that's what shs hopes +to faciliatate. + + +INSTALLATION: Just add shs.el somewhere in your emacs' load-path. + + +For a shell scripting example, (you do need EmacsCVS) + + +Drop shs.el and the two attached files to a ~/location that is present +both in your emacs' loadpath as well as bash's PATH. Create a +~/.emacs.script with these contents: + + (add-to-list 'load-path \"~/location\") + +To be able to use your settings in running emacsen too, also add to +the end of ~/.emacs: (load \"~/.emacs.script\") + +Then, from bash, run shs-example, for a tutorial (I am still learning) +on shell-scripting through Emacs. + +Whenever you call shsp instead of shsh, COMMAND is no longer a +string. It is rather a list whose 1st value is the process, and the +rest of the values are the args. + +For script examples to work, you do need emacscvs installed in (or +linked to from) /usr/local/bin/emacscvs. + +" +) + +;;;###autoload +(defun shs-introduction () + "Provides electric help from variable `shs-introduction'." + (interactive) + (with-electric-help + '(lambda () (insert shs-introduction) nil) "*doc*")) + +;;; New features: +(defconst shs-new-features + "Help..." +) + +(defun shs-new-features () + "Provides electric help from variable `shs-new-features'." + (interactive) + (with-electric-help + '(lambda () (insert shs-new-features) nil) "*doc*")) + +(defconst shs-version "0.0") + +;; Real Code + + +;; Always make your function +(defmacro shs-exit-code-1 (&rest body) + "Normally, if the script errors somewhere, Emacs will immediately +exit with an error code of 255, which is the right thing to do. If +for some reason, you want a different error code, you can wrap this +macro around your lisp code." + (let ((err (gensym))) + `(condition-case ,err (progn ,@body) + (error + (shsm "Error: %S" (error-message-string ,err)) + (kill-emacs 1))))) + + + + +(defun shs-sanitize (str) + "Delete up to one trailing newline from the string. +Typically, shs.el feeds shell commands' output to this function, so +that the result does not have a trailing newline. Is like perl's chop, + except that this is applied automatically in shs" + + (replace-regexp-in-string + "\n\\'" "" (format "%s" str))) + +(defalias 'shs-chop 'shs-sanitize) + + + +(defalias 'shs-shell-exit 'shs-shell-command-with-exit) + +(defvar shs-shell-buffer "*SHS-SHELL*") +(defvar shs-process-buffer "*SHS-PROC*") +(get-buffer-create shs-shell-buffer) +(get-buffer-create shs-process-buffer) + +;;;###autoload +(defun shs-shell-command (command &rest args) + "Shell commands from a running script, exit on errors. + +NOT suitable for asynchronous shell commands. If everything ok, +then return the result of the shell-command as a string, else +exit emacs with the same exit code. + +COMMAND shou]d be a string. You can also give us the command in +the shsp format: a list. In that case, we shall try to guess the +command by converting it to a string by concatting the +shell-quote-argument for each argument. But note that shsp might +be safer. +" + (shsh--reset-buffer) + (setq command (shs-convert-command-list-to-string-maybe command)) + (let ((code (apply 'shell-command command shs-shell-buffer nil)) + (output + (with-current-buffer shs-shell-buffer + (shs-sanitize + (buffer-substring (point-min) (point-max)))))) + + (cond + ((equal code 0) + output) + ;; as you see, the string-to-number of this error code will + ;; always be the correct error code. + (t (error "%S -- error code when trying %S\n Output was: %S" code + command output))))) + +(defun shs-convert-command-list-to-string-maybe (c) + (if (stringp c) + c + (shs-convert-command-list-to-string c))) + +(defun shs-convert-command-list-to-string (c) + (mapconcat 'shell-quote-argument + c " ")) + + +(defun shs-convert-command-string-to-list-maybe (c) + (if (listp c) + c + (shs-convert-command-string-to-list c))) + +(defun shs-convert-command-string-to-list (c) + (split-string c)) + + +;;;###autoload +(defun shs-shell-command-and-code (command &rest args) + (shsh--reset-buffer) + (let ((code (apply 'shell-command command shs-shell-buffer nil))) + (list code + (with-current-buffer shs-shell-buffer + (shs-sanitize + (buffer-substring (point-min) (point-max))))))) + + + + +(defun shsp--reset-buffer () + (with-current-buffer shs-process-buffer + (delete-region (point-min) (point-max)))) + +(defun shsh--reset-buffer () + (with-current-buffer shs-shell-buffer + (delete-region (point-min) (point-max)))) + +;;;###autoload +(defun shs-process-and-code (command &optional infile) + (shsp--reset-buffer) + (let ((code (apply 'call-process (car command) infile shs-process-buffer + nil (cdr command)))) + (list code + (with-current-buffer shs-process-buffer + (shs-sanitize + (buffer-substring (point-min) (point-max))))))) + +;;;###autoload +(defun shs-process (command &optional infile instring outfile appendp) + "process from a running script, exit on errors. + +NOT suitable for asynchronous processes. If everything ok, +then return the result of the shell-command as a string, else +error with the same exit code. + +COMMAND shou]d be a list. You can also give us the command in +the shsh format: a string. In that case, we shall convert it to +a list by taking every word in that string. But note that list +might be safer. + +Both infile and instring can be nil, in which case, no stdin is passed +to the process. + +If INFILE is non-nil it is used. If INFILE is nil and INSTRING is +not, we put instring in a temporary file, and use that as the +stdin. This is kinda like bash's <. + +If outfile is non-nil, the output is also written to outfile. If +appendp is non-nil, the output is appended to any preceding output. +These were kinda like bash's > and >>. + +pseudo-Pipes can be accomplished via use of instring. See, for +example, `shsu-pipe'. +" + (let ((rmp (and (not infile) instring))) + (setq command (shs-convert-command-string-to-list-maybe command)) + (when rmp + ;; see also, for example, shsu-mktemp-d + (setq infile (shsp "mktemp")) + (with-temp-buffer + (insert instring) + (let ((require-final-newline nil)) + (write-file infile nil)))) + (let* ((codeoutput (shs-process-and-code command infile)) + (code (car codeoutput)) + (output (cadr codeoutput))) + (when rmp (delete-file infile)) + (cond + ((equal code 0) + (when outfile + (with-temp-buffer + (when (and appendp (file-exists-p outfile)) + (insert-file-contents outfile)) + (goto-char (point-max)) + (insert output) + (let ((require-final-newline nil)) + (write-file outfile nil)))) + output) + ;; as you see, the string-to-number of this error code will + ;; always be the correct error code. + (t (error "%S -- error code when call-process: %S\n Output was: %S" code command output)))))) + + + + + +(defmacro shs-ignore-errors-flag (&rest body) + "Copied from ignore-errrors-my. + +which: Like ignore-errors, but tells the error.. +Improved for me by Kalle on 7/3/01: + * used backquote: something i was too lazy to convert my macro to.. + * removed the progn: condition-case automatically has one.. + * made sure that the return is nil.. just as it is in ignore-errors. " + (let ((err (gensym))) + `(condition-case ,err (progn ,@body) + (error + (ding t) + (ding t) + (ding t) + (shsm "IGNORED ERROR: %s" (error-message-string ,err)) + (sit-for 1) + nil)))) + + + + + + + + +;;;###autoload +(defalias 'shs-shell 'shs-shell-command) + + +;;;###autoload +(defalias 'shsh 'shs-shell-command) + + +;;;###autoload +(defalias 'shsp 'shs-process) + +;;;###autoload +(defalias 'shs-call-procell 'shs-process) + +(defun shs-shell-command-with-error (&rest args) + "NOT USED ANY MORE. +Shell commands from a running script, exit on errors. + +NOT suitable for asynchronous shell commands. If everything ok, +then return the result of the shell-command as a string, else +exit emacs with the same exit code. +" + (let ((code (apply 'shell-command args))) + (cond + ((equal code 0) + (with-current-buffer shs-shell-buffer + ;;(buffer-substring-no-properties (point-min) (point-max)))) + (shs-sanitize + (buffer-substring (point-min) (point-max))))) + (t (error (format "Bash Error code: %S" code)))))) + + + +(defvar shs-buffer "*SHS*") +(get-buffer-create shs-buffer) + +(defvar shs-message-sit-for 0.1 + "We wait for this duration at critical points when using shs. +Matters only when called within emacs. ") + +(defun shs-message (&rest args) + (cond + (noninteractive + (apply 'message args)) + (t + (save-excursion + (set-buffer (get-buffer-create shs-buffer)) + (goto-char (point-max)) + (insert "\n") + (insert (apply 'format args)) + (message + "%s" + (apply 'format args) + + ;;"Note: This message is saved in the *SHS* and *messages* + ;;buffer." + ) + (sit-for shs-message-sit-for))))) + + + +(defalias 'shs-msg 'shs-message) +(defalias 'shsm 'shs-message) + + +;; OBSOLETE +(defalias 'shs-shell-error 'shs-shell-command-with-error) + + +(defun shs-display-buffer () + (display-buffer shs-buffer) + (let ((cur (current-buffer))) + (set-buffer shs-buffer) + (goto-char (point-max)) + (set-buffer cur))) + + +(defvar shs-bye-hook (list 'shs-display-buffer)) + +(defun shs-bye () + (interactive) + (run-hooks 'shs-bye-hook) + ) + +(defun shs-clear-buffer () + (interactive) + (save-excursion + (set-buffer (get-buffer-create shs-buffer)) + (erase-buffer))) + +(defvar shs-start-hook (list 'shs-clear-buffer)) +(defun shs-start () + "For use when using shs from eshell. " + (interactive) + (run-hooks 'shs-start-hook)) + +(defvar shs-within-p nil + "When non-nil, start and end-hooks are NOT executed.. May be useful +to set via the `shs-within' macro one \"top-level\" shs function is +calling another.. + +In the default setting, this matters only when shs functions are used +from within emacs") + +(defmacro shs-within (&rest args) + `(let ((shs-within-p t)) + (progn ,@args))) + + +(defun shs-help (g) + "Call this function with your function name." + (shsm "") + (shsm + "Running this script calls the Emacs function described below.") + (shsm + (let* ((def (symbol-function g))) + (ignore-errors + (if (equal 'autoload (car-safe def)) + (load (second def)))) + ;; this check does nothing now.. need ro + + (describe-function g)))) + + + +(defun shs-help-check (args) + (let + ((argstr + (mapconcat + (lambda (a) (format "%s" a)) + args + " "))) + (or + (string-match "\\b-h\\b" argstr) + (string-match "help" argstr)))) + + +(defun shs-shell-flag (command &rest args) + " +Added back, since used by some of my scripts. " + (let ((coderes (apply 'shs-shell-command-and-code command args))) + (when (not (equal (first coderes) 0)) + (shsm "IGNORED: ERROR CODE: %S WHEN TRYING %S " (first coderes) + command)) + (second coderes))) + + +;;;###autoload +(defun shs-expand-file-name (file dired) + "Copied from utils-expand-file-name. + +Suggested by Paul Jarc on g.e.d. in 2005-07 when I raised this +issue: + +Emacs' default expand-file-name is slightly borked, the bork can be +seen if there is a file or a directory literally named ~. The bork +comes from the emacs-tilde-feature: anywhere emacs sees a ~ in a +path, it drops the entire preceding path and starts from /home/$USER +afresh. + +viz. Create a file ~/tmp/~. Then + \(expand-file-name (file-name-nondirectory \"~/tmp/~\") + \(file-name-directory \"~/tmp/~\")) +is incorrect + +The version below avoids that problem, but of course, it lacks +the emacs-tilde-feature. It is also portable across platforms, +including VMS. + +However, note that this function is not necc. conformant with expand-file-name +as far as argument structure and all function features are concerned. +" + (concat (file-name-as-directory dired) + (file-name-nondirectory file))) + + + + + + +(provide 'shs) + + diff --git a/elisp/erbot/contrib/soap.el b/elisp/erbot/contrib/soap.el new file mode 100644 index 0000000..a372526 --- /dev/null +++ b/elisp/erbot/contrib/soap.el @@ -0,0 +1,66 @@ + + +;;; soap.el --- Simple Object Access Protocol support for Emacs + +;; Copyright (C) 2002 Edward O'Connor + +;; Author: Edward O'Connor +;; Keywords: comm, tools, processes +;; Version: 0.1 + +;; This file 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 3, or +;; (at your option) any later version. + +;; This file 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 GNU Emacs; see the file COPYING. If not, +;; write to the Free Software Foundation, Inc., 59 Temple Place - +;; Suite 330, Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This is the barest of beginnings of SOAP support for Emacs. It +;; really doesn't do much of anything; to see how to use it, see +;; google.el. Someone who cares about SOAP should probably make +;; this into an actual SOAP implementation. + +;;; Code: + +(require 'url) + +(defun soap-process-response (response-buffer) + "Process the SOAP response in RESPONSE-BUFFER." + (let ((retval nil)) + (with-current-buffer response-buffer + (goto-char (point-min)) + (when (looking-at "^HTTP/1.* 200 OK$") + (re-search-forward "^$" nil t 1) + (setq retval (buffer-substring-no-properties (point) (point-max)))) + (kill-buffer response-buffer)) + (with-temp-buffer + (insert "\n" retval "\n") + (goto-char (point-min)) + (while (re-search-forward "\r" nil t) + (replace-match "")) + (xml-parse-region (point-min) (point-max))))) + +(defun soap-request (url data) + "Send and process SOAP request to URL with DATA." + (let* ((url-request-extra-headers + `(("Content-type" . "text/xml; charset=\"utf-8\"") + ("SOAPAction" . ,(format "%S" url)))) + (url-request-method "POST") + (url-request-data + (concat "\n" + data))) + (soap-process-response (url-retrieve-synchronously url)))) + +(provide 'soap) +;;; soap.el ends here + diff --git a/elisp/erbot/contrib/timerfunctions.el b/elisp/erbot/contrib/timerfunctions.el new file mode 100644 index 0000000..8d68f06 --- /dev/null +++ b/elisp/erbot/contrib/timerfunctions.el @@ -0,0 +1,431 @@ +;;; timerfunctions.el---enhanced versions of some timer.el functions. +;; Time-stamp: <2003-05-09 08:23:24 deego> +;; Copyright (C) Deepak Goel 2000, 2001, 2002 +;; Emacs Lisp Archive entry +;; Filename: timerfunctions.el +;; Author: Deepak Goel +;; Version: 1.4.2 +;; Created: 2000/11/20 + +;; Author's homepage: http://gnufans.net/~deego +;; For latest version: + +(defconst timerfunctions-home-page + "http://gnufans.net/~deego/emacspub/timerfunctions") + + + +(defvar timerfunctions-version "1.4.2") + + +;;;======================================================== +;;;======================================================== +;;; Commentary: The latest version can always be downloaded from +;;; http://www.glue.umd.edu/~deego/emacs.html + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + + +;;; See also: midnight.el (part of emacs), timer.el + + + + +;;; New features: +(defconst timerfunctions-new-features + "New since last posting: Changed the syntax of `tf-with-timeout' and +provided a `tf-with-timeout-check'.") + +(defun timerfunctions-new-features () + "Provides electric help from variable `timerfunctions-new-features'." + (interactive) + (with-electric-help + '(lambda () (insert timerfunctions-new-features) nil) "*doc*")) + + +(defconst timerfunctions-introduction + "timerfunctions.el contains some 'enhanced' versions of a few timer.el +functions. It is also used by vel.el, idledo.el etc. + + Suppose you want emacs to run an action every REDOSECS for + _as_long_as emacs remains idle. `tf-run-with-idle-timer' allows that. + + `tf-with-timeout' is a generalized with-timeout where you can inhibit + breaks within parts of the body that you want. + + QUICKSTART: + Place this file somewhere in yr emacs-load-path, and add the + foll. to your .emacs: (load \"timerfunctions.el\") +" +) + +;;;###autoload +(defun timerfunctions-introduction () + "Provides electric help from variable `timerfunctions-introduction'." + (interactive) + (with-electric-help + '(lambda () (insert timerfunctions-introduction) nil) "*doc*")) + +;;; Real Code: + + +;;;###autoload +(defun tf-time-difference (timeplus timesub) + "Gives the time in seconds elaspsed from TIMESUB to TIMEPLUS. +Almost like \(- TIMEPLUS TIMESUB \)." + (+ (* (expt 2 16) (- (car timeplus) (car timesub))) + (- (cadr timeplus) (cadr timesub))) +) + + +;;;###autoload +(defun tf-run-with-idle-timer (secs repeat redosecs redorepeat includeruntime function &rest args) + "Args are SECS, REPEAT, REDOSECS, REDOREPEAT, INCLUDERUNTIME, +FUNCTION and &rest ARGS. +Similar to run-with-idle-timer, except that provides more options. +Suppose you want emacs to run an action every REDOSECS for as long as +emacs remains idle. Think you can do it with the emacs' +run-with-idle-timer? Think again.. :) That function will perform the +action exactly once every time emacs goes idle. This funciton, +tf-run-with-idle-timer *will* allow you to keep performing an action +as long as emacs remains idle. + +SECS is the number of seconds to wait once emacs has first gone +idle. It can really be any expression whose at runtime yields a +number.. Note that the way run-with-idle-timer is defined, SECS will +unfortunately be evalled immediately after you call this function, but +redosecs will be *every* time emacs *remains* idle..yay.. + + +If REDOREPEAT is non-nil, the action is repeated as long emacs remains +idle. REDOSECS is the number of additional seconds (after the action +has been done) to wait if emacs remains idle before performing the +action again. Again, redosecs does not have to be a number, it can be +any expression whose eval yields to a number... + +If INCLUDERUNTIME is non-nil, REDOSECS is the number of +additional seconds to wait after the action has been invoked (not +finished). + +If REPEAT is nonnil, the entire cycle is repeated every time emacs +next goes idle.. (as in the default run-with-idle-timer." + (apply 'run-with-idle-timer + (eval secs) repeat 'tf-run-while-idle + redosecs redorepeat includeruntime + function args) + ) + + +(defun tf-run-while-idle (redosecs redorepeat includeruntime +function &rest args) + "Runs FUNCTION with ARGS and optionally repeats if emacs idle. +Probably is of no use unless used in programs. + If REDOREPEAT is non-nil, the function is repeated periodically every +REDOSECS as long as emacs remains idle. By default, emacs waits +REDOSECS *after* the function is done executing to repeat. If you want +the execution-time to count towards REDOSECS, make INCLUDERUNTIME +non-nil. +SECS and REDOSECS can be any expressions that eval at runtime to +numbers.. In particular, they can simply be numbers.. + +" + (if (not includeruntime) + (progn + (apply function args) + (if redorepeat + (while (sit-for (eval redosecs)) + (apply function args)))) + (progn + (let ((before-time (current-time))) + (apply function args) + (if redorepeat + (while (sit-for (- + (eval redosecs) + (tf-time-difference (current-time) + before-time))) + (setq before-time (current-time)) + (apply function args)))))) + ) + + +;;;==================================================== +;;;TESTS FOLLOW +(defun tf-test-display-time-internal + () + (let ((thisbuffer (buffer-name))) + (switch-to-buffer-other-window "*scratch*") + (goto-char (point-max)) + (insert (concat "\n" (format "%S" (cadr (current-time))))) + (recenter) + (switch-to-buffer-other-window thisbuffer)) +) + + +(defun tf-test-idle-timer () + "Run this and watch..Play around with the options.. If you run it, +you may have to exit your emacs session to restore normal emacs! +unless you are an expert, that is.." + + (interactive) + (tf-run-with-idle-timer + 1 t 3 t nil 'tf-test-display-time-internal) +) + + + + + +(defun tf-test-timeout () + "Bad count should be zero. " + (interactive) + (let ((inhi nil) (goodcount 0) (badcount 0) (ctr 0) (a 1) (b 2) + (mytag nil) + (myvar nil) + ) + (loop + for ctr from 0 to 10 do + (message "ctr=%S" ctr) + (tf-with-timeout 'inhi 'mytah 'myvar + (0.3 nil) + (loop for i from 0 to 100000 do + (message "ctr=%S, i=%S" ctr i) + (setq inhi t) + (setq a (random 100)) + (sleep-for 0.1) + (setq b a) + (setq inhi nil) + (sleep-for 0.02) + )) + (if (equal b a) (incf goodcount) (incf badcount))) + (message "Goodcount: %S; badcount: %S" goodcount badcount))) + + + +(defun tf-test-timeout-complex () + "Should return a value of 20000 for a. " + + (interactive) + (let ((inhi t) (goodcount 0) (badcount 0) (ctr 0) (a 1) (b 2) + (mytag nil) + (myvar nil) + ) + (setq a 0) + (message "ctr=%S" ctr) + (tf-with-timeout + 'inhi 'mytag 'myvar + (0.1 nil) + (loop for i from 0 to 10000 do + (message "first loop. i=%S" ctr i) + (incf a)) + (message "initial loop ends here.") + ;; no throw here because loop prohibited. + (tf-with-timeout-check 'inhi 'mytag 'myvar) + ;; this shouldn't help either + (sit-for 0.3) + + (loop for i from 0 to 10000 do + (message "second loop. i=%S" i) + (incf a)) + (message "second loop ends here.") + (setq inhi nil) + ;; this should throw. + (tf-with-timeout-check 'inhi 'mytag 'myvar) + ;; this should NOT be needed. + ;;(sit-for 0.2) + ;; this loop should never take place. + (loop for i from 0 to 1000 do + (message "third loop, i=%S" i) + (incf a)) + (message "third loop ends here.")) + (message "%S" a) + a)) + + +(defun tf-wait-until-idle (&optional secs) + "DOES NOT WORK YET. Waits until idle. +Will help run processes in background. This function will NOT create +a timer. Will simply use sit-for. " + (if (null secs) + (setq secs 1)) + (while (not (sit-for secs)) + (sit-for 1)) + (message "tf-wait-until-idle DONE WAITING!") +) + + +;;;Tue Jan 23 17:38:44 2001 +(defmacro tf-ignore-errors (&rest body) + "Like ignore-errors, but tells the error.." + (let ((err (gensym))) + (list 'condition-case err (cons 'progn body) + (list 'error + (list 'message + (list 'concat + "IGNORED ERROR: " + (list 'error-message-string err))))) + )) + + + + +(defvar tf-with-timeout-repeat-sec 0.01 + "If the initial timeout fails because of inhibitedness, we shall +check every this many seconds to see if we are uninhibited. This +variable is customizable. ") + + +(defun tf-with-timeout-handler-internal (tag timedoutvar inhibitp) + (set timedoutvar t) + ;;(tf-with-timeout-check tag timedoutvar inhibitp) + ;; which is equivalent to: + (unless (eval inhibitp) + (tf-ignore-errors (throw tag 'timeout))) + ) + +(defun tf-with-timeout-check (inhibitp tag timedoutvar) + ;; check whether timeout has actually reached. + ;; we need this step because this function might be called by the + ;; user as well. + (when (eval timedoutvar) + (unless (eval inhibitp) + (tf-ignore-errors (throw tag 'timeout))))) + + + +(defvar tf-tag-tmpvar nil) + +(defmacro tf-catch (tag &rest body) + `(let + ;; unquote the tag here.. + ((,(cadr tag) 'tf-catch)) + (catch ,tag + ,@body))) + +(defmacro tf-throw (tag value) + `(when (eql (eval ,tag) 'tf-catch) + (throw ,tag value))) + + +;;;###autoload +(defmacro tf-with-timeout (inhibitp timertag timedoutvar tlist &rest body) + "Like `with-timeout' but provide ability to inhibit timeout during +parts of the body. Note that most of the time, you may not need this +functionality at all unless you want to be very 'clean' about +things---you could get by with the regular with-timeout and not using +sit-for's in the body. Or with the regular with-timeout and using +unwind-protect. + + +TO DECIDE: IN VIEW OF THE UNWIND-PROTECT, DO WE NEED THIS FUNCTION AT ALL?? + +Run BODY, but if it doesn't finish in SECONDS seconds, give up. +If we give up, we run the TIMEOUT-FORMS which are contained in TLIST +and return the value of the last one. +The call should look like: + (tf-with-timeout quoted-expr (SECONDS TIMEOUT-FORMS...) BODY...) + +The timeout is checked whenever Emacs waits for some kind of external +event \(such as keyboard input, input from subprocesses, or a certain time); +if the program loops without waiting in any way, the timeout will not +be detected. Furthermore: + +During the execution of the body, we SHALL NOT time out when INHIBITP +evals to non-nil. Thus, for example, you might initially setq a +variable my-var as nil, supply inhibitp as 'my-var, and then you may +setq my-var to t or nil within the body of tf-with-timeout to enable +or disable timeout. The best use of this functionality is to setq +inhibitp to t when during parts of loops where you do not want the +body broken within certain parts of the loop. (Of course, if that +part of the loop does not contain any sit-for's or read's then you +don't have to worry about this in the first place..) + + +again, Do not forget my-var to some value before attempting to use this +tf-with-timeout :) + +Here's an example: + + + (let ((myinhibit t)) + (tf-with-timeout 'myinhibit 'mytag 'mytimedoutvar + (2 2) + (setq a nil) + (setq b nil) + (sit-for 4) + (setq a 4) + (setq myinhibit nil) + (sit-for 2) + (setq b 5) + )) + + +The above example requests a timeout within 2 seconds. However, the +timeout can takes place only when myinhibit is set to nil, +which becomes true after about 4 seconds. Thus, after the execution of the +body, a has the value 4, but b has the value nil. + +See `tf-test-timeout' for another example. + +Important Note: If the body of a loop tends to stay in a timeout +inhibited region for most of the time, then make sure that the timeout +enabled region atleast spans about 0.02 seconds.. thus, use (sleep-for +0.02) if needed.. this is because we check every 0.01 seconds if an +uninhibited timeout condition has been satisfied. + +But perhaps you do not want to include (sleep-for 0.02) because that +wastes precious cpu time. Simple, don't include it, just after a long +inhibited body, you can include a timeout check within the body +instead of (sleep-for 0.02): + (tf-with-timeout-check 'mytag 'mytimedoutvar 'myinhibitp) + +Moreover, if that is the main check you rely on, you it perhaps makes +sense to increase the value of tf-with-timeout-repeat-sec, so that +your cpu cycles are not wasted every 0.01 sec. See the doc of that +variable for more. + +Timertag should be a quoted symbol, also we WILL set that symbol to t +during the execution of these forms. + +" + (let ((seconds (car tlist)) + (timeout-forms (cdr tlist))) + `(let ( + ;;(with-timeout-tag (cons nil nil)) + with-timeout-value with-timeout-timer) + (set ,timedoutvar nil) + (if (catch ,timertag + (progn + (setq with-timeout-timer + (run-with-timer ,seconds tf-with-timeout-repeat-sec + 'tf-with-timeout-handler-internal + ,timertag ,timedoutvar + ,inhibitp)) + (setq with-timeout-value (progn ,@body)) + nil)) + (progn ,@timeout-forms) + (cancel-timer with-timeout-timer) + with-timeout-value)))) + + +(provide 'timerfunctions) + +;;;timerfunctions.el ends here. + diff --git a/elisp/erbot/contrib/translate.el b/elisp/erbot/contrib/translate.el new file mode 100644 index 0000000..f60d9ea --- /dev/null +++ b/elisp/erbot/contrib/translate.el @@ -0,0 +1,237 @@ +;; Emacs Lisp Archive Entry +;; Package: translate +;; Filename: translate.el +;; Version: 0.01 +;; Keywords: natural language, language, translate, translation +;; Author: Vivek Dasmohapatra +;; Maintainer: Vivek Dasmohapatra +;; Created: 2006-05-10 +;; Description: use gnome translate/libtranslate to translate text +;; Compatibility: Emacs21, Emacs22 +;; Last modified: Fri 2006-05-12 02:52:44 +0100 + + +;; Based on work by: +;; Deepak Goel +;; Alejandro Benitez + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;; You need to install libtranslate for this to work. The binary, +;; translate and the library libtranslate.so are provided (for example) +;; in Ubuntu Dapper: http://packages.ubuntu.com/dapper/libs/libtranslate-bin + +(defvar translate-version "0.01") + +(defvar translate-pairs nil + "A cache for the language pairs. A list of entries of the form: \n + '((fromaliases) (toaliases) (types)).\n +The first elements of fromaliases and toaliases are the canonical two letter +language codes (possibly with a -XX country variant extension). Any remaining +elements are human-readable aliases. (types) is a list of translation types, +usually text, and occasionally web-page as well. No other types are currently +known.") + +(defvar translate-unsupported-langs '("he" "pap") + "Languages (two/three letter codes) that we cannot utf-8 encode yet.") + +(defgroup translate nil + "Translate natural languages using gnome translate (or workalikes)." + :group 'external + :prefix "translate-") + +(defcustom translate-program "translate" + "External translation program." + :group 'translate + :type '(choice string file)) + +(defun translate-req-to-pair (from to) + "Taking a pair of string arguments, find a matching translation service +and return it as a cons of the form (\"origin\" . \"dest\")" + (translate-load-pairs) + (let ( (code nil) ) + (mapc (lambda (p) (if (and (member-ignore-case from (car p)) + (member-ignore-case to (cadr p))) + (setq code (cons (caar p) (car (cadr p))) )) ) + translate-pairs) + code)) + +(defun translate-full-name (code-or-name) + "Return the full name of a language based on a code or one of its aliases." + (interactive "sLanguage (eg en or zh-TW): ") + (translate-load-pairs) + (let ((name nil) (lang nil) (ldata translate-pairs)) + (while (and ldata (not name)) + (setq lang (car ldata) ldata (cdr ldata)) + (if (member-ignore-case code-or-name (car lang)) + (setq lang (car lang)) + (if (member-ignore-case code-or-name (cadr lang)) + (setq lang (cadr lang)) + (setq lang nil))) + (when lang + (setq name (mapconcat (lambda (l) (format "%s" l)) (cdr lang) " ")) )) + name)) + +(defconst translate-pair-regex + (concat "^\\([a-z]\\{2,3\\}\\(?:-..\\)?\\)" ;; language code (from) + "\\s-+" + "(\\(.*\\))" ;; language names (from) + "\\s-+->\\s-+" + "\\([a-z]\\{2,3\\}\\(?:-..\\)?\\)" ;; language code (to) + "\\s-+" + "(\\(.*\\)):" ;; language aliases (to) + "\\s-+" + "\\(.*\\)")) ;; capabilities + +(defun translate-parse-pair (pair-line) + "Parse a line of output from `translate-program' --list-pairs, return +an element for insertion into `translate-pairs'." + (if (string-match translate-pair-regex pair-line) + (let ( (from (match-string 1 pair-line)) + (from-alias (match-string 2 pair-line)) + (to (match-string 3 pair-line)) + (to-alias (match-string 4 pair-line)) + (cap (match-string 5 pair-line)) + (cleanup (lambda (x) (replace-regexp-in-string ",.*" "" x))) + (from-names nil) + (to-names nil)) + (setq from-alias (split-string from-alias ";") + to-alias (split-string to-alias ";") + from-alias (mapcar cleanup from-alias) + to-alias (mapcar cleanup to-alias ) + cap (split-string cap ",\\s-+")) + (mapc (lambda (x) + (let ((pos 0)) + (while (setq pos (string-match "\\<\\(\\S-+\\)\\>" x pos)) + (setq from-names (cons (match-string 1 x) from-names) + pos (match-end 1)) ))) + from-alias) + (mapc (lambda (x) + (let ((pos 0)) + (while (setq pos (string-match "\\<\\(\\S-+\\)\\>" x pos)) + (setq to-names (cons (match-string 1 x) to-names) + pos (match-end 1)) ))) + to-alias) + (list (cons from from-names) + (cons to to-names ) cap)) + (message "%S does not match.\n" pair-line) nil)) + +(defun translate-load-pairs (&optional reload) + "Parse the output of `translate-program' -l into `translate-pairs' +Called interactively with a prefix argument, or non-interactively with a +non-nil reload argument, it will empty translate-pairs first. Otherwise, +if translate-pairs has already been loaded, it will not do anything." + (interactive "P") + (if reload (setq translate-pairs nil)) + (when (not translate-pairs) + (let ( (y nil) + (pair-text (shell-command-to-string + (concat translate-program " -l"))) ) + (mapc + (lambda (x) + (when (setq y (translate-parse-pair x)) + (setq translate-pairs (cons y translate-pairs)))) + (split-string pair-text "\n")) )) + translate-pairs) + +(defun translate-list-pairs (&optional from to) + "Return the subset of `translate-pairs' that matches the FROM and TO +arguments." + (if (string-match "^\\(?:\*\\|any\\|-\\|\\)$" from) (setq from nil)) + (if (string-match "^\\(?:\*\\|any\\|-\\|\\)$" to ) (setq to nil)) + (if (not (translate-load-pairs)) + (error "translate doesn't seem to have been setup - no languages found.") + (cond + ( (and (not from) (not to)) ;; neither end point specified + translate-pairs ) + ( (or (not to) (not from)) ;; one end point specified + (let ( (op (if from 'car 'cadr)) + (op2 (if from 'cadr 'car)) + (s nil) + (fl (format "%s" (or from to))) ) + (mapc (lambda (p) (if (member-ignore-case fl (funcall op p)) + (setq s (cons p s)))) + translate-pairs) + s )) + (t ;; fully spec'd translation + (let ( (s nil) (fl (format "%s" from)) (tl (format "%s" to )) ) + (mapc (lambda (p) + (if (and (member-ignore-case fl (car p)) + (member-ignore-case tl (cadr p))) + (setq s (cons p s)) )) + translate-pairs) + s) )) )) + +(defun translate (from to &rest text) + "Given a language code or language name for the origin and destination +languages FROM and TO (see `translate-pairs') and some TEXT, returns a string +containing the translated text from `translate-program' (gnome translate +or a work-alike). If an error occurs, either internally or while invoking +`translate-program', signals an `error' instead." + (setq text (mapconcat #'(lambda (arg) (format "%s" arg)) text " ")) + ;; ======================================================================= + ;; we might have to force the locale, according to the translate docs, + ;; but this doesn't actually seem to be necessary at the moment. + ;; ----------------------------------------------------------------------- + ;; call-process should use utf-8, that's what libtranslate wants: hence + ;; we set process-coding-system-alist. + ;; ----------------------------------------------------------------------- + (let ( (from-lang (format "%s" from)) + (to-lang (format "%s" to)) + (translation nil) ;; translated text, or libtranslate error + (code nil) ;; cons of (origin-lang . dest-lang) + (status nil) );; return code of command. 0 => success. + (setq code (translate-req-to-pair from-lang to-lang) + from (car code) + to (cdr code)) + (cond + ( (not code) + (error "%s -> %s: no matching translation services found.\n" + (or (translate-full-name from-lang) from-lang) + (or (translate-full-name to-lang ) to-lang )) ) + ( (member (car code) translate-unsupported-langs) + (error "Sorry, unicode support for %s is not yet complete." + (translate-full-name from-lang)) ) + ( (member (cdr code) translate-unsupported-langs) + (error "Sorry, unicode support for %s is not yet complete." + (translate-full-name to-lang)) ) + ( t + (with-temp-buffer + (let ( (lc-all (getenv "LC_ALL")) + (lang (getenv "LANG")) + (coding-system-for-read 'utf-8) + (coding-system-for-write 'utf-8) + (process-coding-system-alist '("." . utf-8)) ) + (insert text) + (setenv "LC_ALL" nil) + (setenv "LANG" "en_GB.UTF-8") + (setq status + (call-process-region (point-min) (point-max) + translate-program + :delete-input (current-buffer) nil + "-f" from "-t" to) + translation (buffer-substring-no-properties (point-min) + (point-max))) + (setenv "LANG" lang) + (setenv "LC_ALL" lc-all) + )) )) + (if (/= 0 status) + (error "%d - %s" status translation)) + translation )) + +(provide 'translate) diff --git a/elisp/erbot/contrib/units.el b/elisp/erbot/contrib/units.el new file mode 100644 index 0000000..2e06793 --- /dev/null +++ b/elisp/erbot/contrib/units.el @@ -0,0 +1,179 @@ +;;; UNITS.EL --- units conversion + +;; Copyright (C) 2002 Linh Dang + +;; Author: Linh Dang +;; Maintainer: Linh Dang +;; Created: 16 Sep 2002 +;; Version: 1.0 +;; Keywords: conversion + + +;; 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 1, 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. + +;; A copy of the GNU General Public License can be obtained from this +;; program's author (send electronic mail to ) or from the +;; Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +;; USA. + +;; LCD Archive Entry: +;; units|Linh Dang| +;; |units conversion +;; |$Date: 2006/01/05 18:52:02 $|$Revision: 1.1 $|~/packages/units.el + +;;; Commentary: +;; +;; Dirty hack to do units conversion using units.dat from units package. +;; likely buggy. Fixes/patches/flames/comments are welcome. +;; +;; only tested on ntemacs 21.2 + +;;; Change log: +;; $Log: units.el,v $ +;; Revision 1.1 2006/01/05 18:52:02 mwolson +;; Revision: mwolson@gnu.org--2006/erbot--cvs--0--patch-3 +;; +;; Add units.el to contrib directory. +;; +;; * contrib/units.el: Newly-added file that is recommended on the +;; ErbotInstallation page of emacswiki.org. +;; +;; Revision 1.8 2002/09/17 11:34:13 linhd +;; huh +;; +;; Revision 1.7 2002/09/17 11:27:57 linhd +;; clean +;; +;; Revision 1.6 2002/09/16 18:48:31 linhd +;; ok +;; +;; Revision 1.5 2002/09/16 16:27:33 linhd +;; works +;; +;; Revision 1.4 2002/09/16 16:21:31 linhd +;; seems to work +;; +;; Revision 1.3 2002/09/16 14:41:38 linhd +;; good +;; +;; Revision 1.2 2002/09/16 14:21:22 linhd +;; huh +;; +;; Revision 1.1 2002/09/16 14:07:59 linhd +;; Initial revision +;; + +;;; Code: + +(defconst units-version (substring "$Revision: 1.1 $" 11 -2) + "$Id: units.el,v 1.1 2006/01/05 18:52:02 mwolson Exp $ + +Report bugs to: Linh Dang ") +(defvar units-load-hook nil + "*Hooks run after loading units.") + +(defcustom units-dat-file "/usr/share/units/units.dat" + "Dat file for UNITS." + :group 'emacs + :type '(file :must-match t)) + +(defun units-buffer () (find-file-noselect units-dat-file)) + +(defun units-s-to-n (s) + "convert a quantity string in units.dat to a number." + (if (memq ?| (mapcar 'identity s)) + (apply '/ (mapcar 'string-to-number (split-string s "|"))) + (string-to-number s))) + +(defun units-prefix-convert (prefix) + "convert PREFIX such as centi or mega to a number." + (goto-char (point-min)) + (if (re-search-forward (concat "^" prefix "\\s-+\\(\\S-+\\)\\(\\s-+#?\\)?") nil t) + (if (= (units-s-to-n (match-string-no-properties 1)) 0) + (units-prefix-convert (concat (match-string-no-properties 1) "-")) + (units-s-to-n (match-string-no-properties 1))) + 0)) + +(defvar units-si-prefix-list + '("yotta" "zetta" "exa" "peta" "tera" "giga" "mega" "myria" "kilo" + "hecto" "deca" "deka" "deci" "centi" "milli" "micro" "nano" "pico" + "femto" "atto" "zepto" "yocto" "quarter" "semi" "demi" "hemi" + "half" "double" "triple" "treble" ) + "multi-char prefixes used in SI.") + +(defvar units-si-short-prefix-list + '(?Y ?Z ?E ?P ?T ?G ?M ?k ?h ?d ?c ?m ?n ?p ?f ?a ?z ?y) + "single car prefixes used in SI (not including da)") + +(defun units-convert-1 (in quantity out) + "convert QUANTITY in IN units to OUT units. +return the amount in OUT units. This function assumed that +the current buffer contains units.dat." + (if (or (= quantity 0) (string-equal in out)) + quantity + (let (n next prefix) + (goto-char (point-min)) + (if (re-search-forward + (concat "^" in + "\\> +\\(\\([a-zA-Z]\\S-*\\)\\|!\\|\\([0-9]\\S-*\\) +\\([a-zA-Z]\\S-*\\)\\)") + nil t) + (cond ((match-beginning 4) + (setq next (match-string-no-properties 4)) + (setq n (units-s-to-n (match-string-no-properties 3))) + (if (string-equal next out) + (* n quantity) + (units-convert-1 next (* n quantity) out))) + + ((match-beginning 2) + (setq next (match-string-no-properties 2)) + (if (string-equal next out) + quantity + (units-convert-1 next quantity out)) ) + + ((string-equal (match-string-no-properties 1) "!") + (/ quantity (units-convert-1 out 1 in))) + (t + (error "internal error 1") )) + (unless (or (and (= (length in) 2) + (memq (aref in 0) units-si-short-prefix-list) + (setq prefix (concat (list (aref in 0) ?-)) + in (substring in 1))) + (and (= (length in) 3) + (= (aref in 0) ?d) + (= (aref in 1) ?a) + (setq prefix "da-" + in (substring in 2))) + (and (progn + (mapcar (lambda (pre) + (if (string-match (concat "\\`" pre) in) + (setq prefix (concat (match-string 0 in) "-") + in (substring in (match-end 0))))) + units-si-prefix-list) + prefix))) + (error "don't know how to convert %g %s to %s" quantity in out)) + (setq quantity (* (units-prefix-convert prefix) quantity)) + (if (= quantity 0) + (error "don't know how to handle %s" prefix) + (units-convert-1 in quantity out)))))) + +(defun units-convert (in quantity out) + "command to convert QUANTITY in IN units to OUT units." + (interactive "sinput unit: \nnquantity: \nsoutput unit: ") + (let ((buffer (units-buffer))) + (save-excursion + (set-buffer buffer) + (toggle-read-only 1) + (message "%g %s = %g %s" quantity in + (units-convert-1 in quantity out) out)))) + +(provide 'units) +(run-hooks 'units-load-hook) +;;; UNITS.EL ends here diff --git a/elisp/erbot/contrib/wtf.el b/elisp/erbot/contrib/wtf.el new file mode 100644 index 0000000..201b179 --- /dev/null +++ b/elisp/erbot/contrib/wtf.el @@ -0,0 +1,964 @@ +;;; wtf.el --- Look up conversational and computing acronyms + +;; Copyright (C) 2005, 2006, 2007 Michael Olson + +;; Author: Michael Olson +;; Date: Wed 16-May-2007 +;; Version: 2.0 +;; URL: http://mwolson.org/static/dist/elisp/wtf.el + +;; This file is not part of GNU Emacs. + +;; 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 3 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; wtf.el provides the ability to look up the definitions of popular +;; conversational and computing acronyms. + +;; * Use: +;; +;; To use this, move to an unknown acronym in a buffer and type +;; the following: +;; +;; M-x wtf-is RET +;; +;; The `wtf-is' function may also be called noninteractively, and it +;; will return a string (or nil) rather than displaying a message. +;; +;; To add a custom acronym definition, either customize +;; `wtf-custom-alist' or do: +;; +;; M-x wtf-add RET RET RET +;; +;; To remove a custom acronym definition, or mark a pre-defined +;; acronym as "removed" in the case that no custom acronym definition +;; exists in `wtf-custom-alist' for that acronym, do: +;; +;; M-x wtf-remove RET RET +;; +;; To mark a pre-defined acronym as "removed", without checking first +;; to see whether it is in `wtf-custom-alist', customize the +;; `wtf-removed-acronyms' option. +;; +;; If you add a custom acronym definition, and feel it to be worth +;; sharing, you are encouraged to contact via email, +;; providing the acronym and its definition. This increases the +;; chance that it will appear in future versions of wtf.el. + +;; * Legalese: +;; +;; Many of the acronym definitions were downloaded from +;; http://cvsweb.netbsd.org/bsdweb.cgi/src/share/misc/. No copyright +;; notice was included, but the intent of the original author was to +;; put these acronym definitions in the public domain. This was +;; deduced from several emails sent to the authors of these files. +;; Additionally, the original data files use a specific syntax which +;; does not allow for a copyright notice. +;; +;; The original program that uses these files in NetBSD +;; (http://cvsweb.netbsd.org/bsdweb.cgi/src/games/wtf/wtf) is in the +;; public domain. + +;; * Acknowledgments: +;; +;; Thanks to Trent Buck for `emacs-wiki-wtf.el', which inspired the +;; creation of `wtf.el'. + +;;; History: + +;; 2.0: +;; +;; - Add the `wtf-custom-alist' option, the `wtf-add' interactive +;; function to add acronyms to it, and the `wtf-remove' interactive +;; function to remove acronyms from it. Thanks to Andreas Roehler +;; for the suggestion. +;; +;; - Add a few acronyms that were scavenged from various forum FAQ +;; pages. +;; +;; - Handle multiple definitions for a single acronym more +;; intuitively. The text separator used in this case may be changed +;; by customizing the `wtf-def-separator' option. + +;; 1.1-1.4: +;; +;; - Fix a bug with completions in Emacs 21, thanks to Ehud Karni. +;; +;; - Add additional acronyms and re-sync with the NetBSD acronym list. + +;; 1.0: Initial release. + +;;; Code: + +(eval-when-compile (require 'cus-edit)) + +(defgroup wtf nil + "Options controlling the behavior of the wtf program. +wtf provides the `wtf-is' command, which looks up the definition +of the acronym at point." + :group 'convenience) + +(defcustom wtf-custom-alist nil + "Custom mappings of acronyms to definitions used by `wtf-is'. +The acronym should be uppercase, and the definition may be either +lowercase or mixed case. If mixed case, it will not be modified, +otherwise initial letters will be capitalized. + +These definitions are consulted after those in `wtf-alist'. + +This variable can also be manipulated interactively by using +`wtf-add'." + :type '(repeat (cons (string :tag "Acronym") + (string :tag "Definition"))) + :group 'wtf) + +(defcustom wtf-removed-acronyms nil + "Acronyms which exist in `wtf-alist' but should be ignored by `wtf-is'. +Each acronym should be in uppercase. +This is an easy way of removing an acronym that is felt to be +wrong or irrelevant. + +This variable can also be manipulated interactively by using +`wtf-remove'." + :type '(repeat (string :tag "Acronym")) + :group 'wtf) + +(defcustom wtf-def-separator ", or " + "Separator used when an acronym has two or more definitions." + :type 'string + :group 'wtf) + +(defvar wtf-alist + '(;; $NetBSD: acronyms,v 1.164 2007/01/31 18:37:07 elad Exp $ + ("AFAIC" . "as far as i'm concerned") + ("AFAICR" . "as far as i can recall") + ("AFAICT" . "as far as i can tell") + ("AFAIK" . "as far as i know") + ("AFAIR" . "as far as i recall") + ("AFAIU" . "as far as i understand") + ("AFD" . "away from desktop") + ("AFK" . "away from keyboard") + ("AFU" . "all fucked up") + ("AFW" . "away from window") + ("AIU" . "as i understand") + ("AIUI" . "as i understand it") + ("AKA" . "also known as") + ("ASAIC" . "as soon as i can") + ("ASAP" . "as soon as possible") + ("ATM" . "at the moment") + ("AWOL" . "absent without official leave") + ("AYBABTU" . "all your base are belong to us") + ("AYT" . "are you there") + ("B/C" . "because") + ("B/S" . "bullshit") + ("B/W" . "between") + ("BBIAB" . "be back in a bit") + ("BBL" . "[I'll] Be Back Later") + ("BBS" . "be back soon") + ("BBT" . "be back tomorrow") + ("BFD" . "big fucking deal") + ("BIAB" . "back in a bit") + ("BIAF" . "back in a few") + ("BIALW" . "back in a little while") + ("BIAS" . "back in a second") + ("BIAW" . "back in a while") + ("BOATILAS" . "bend over and take it like a slut") + ("BOFH" . "bastard operator from hell") + ("BOGAHICA" . "bend over, grab ankles, here it comes again") + ("BOHICA" . "bend over here it comes again") + ("BRB" . "[I'll] Be Right Back") + ("BS" . "bullshit") + ("BTDT" . "been there, done that") + ("BTTH" . "boot to the head") + ("BTW" . "by the way") + ("CMIIW" . "correct me if i'm wrong") + ("CNP" . "continued [in my] next post") + ("COB" . "close of business [day]") + ("COTS" . "commercial off-the-shelf") + ("CYA" . "see you around") + ("D/L" . "download") + ("DGAS" . "don't give a shit") + ("DIY" . "do it yourself") + ("DKDC" . "don't know, don't care") + ("DSTM" . "don't shoot the messenger") + ("DTRT" . "do the right thing") + ("DTWT" . "do the wrong thing") + ("DWIM" . "do what i mean") + ("EG" . "evil grin") + ("EMSG" . "email message") + ("EOB" . "end of business [day]") + ("EOD" . "end of discussion") + ("EOL" . "end of life") + ("ETA" . "estimated time of arrival") + ("ETLA" . "extended three letter acronym") + ("EWAG" . "experienced wild-ass guess") + ("FAQ" . "frequently asked question") + ("FCFS" . "first come first served") + ("FIGJAM" . "fuck i'm good, just ask me") + ("FIIK" . "fuck[ed] if i know") + ("FIIR" . "fuck[ed] if i remember") + ("FM" . "fucking magic") + ("FOAD" . "fall over and die") + ("FOS" . "full of shit") + ("FSDO" . "for some definition of") + ("FSVO" . "for some value of") + ("FTFM" . "fuck the fuckin' manual!") + ("FTL" . "for the loss") + ("FTW" . "for the win") + ("FUBAR" . "fucked up beyond all recognition") + ("FUD" . "fear, uncertainty and doubt") + ("FWIW" . "for what it's worth") + ("FYI" . "for your information") + ("G" . "grin") + ("G/C" . "garbage collect") + ("GAC" . "get a clue") + ("GAL" . "get a life") + ("GIGO" . "garbage in, garbage out") + ("GMTA" . "great minds think alike") + ("GTFO" . "get the fuck out") + ("GTG" . "got to go") + ("GWS" . "get well soon") + ("HAND" . "have a nice day") + ("HHIS" . "hanging head in shame") + ("HICA" . "here it comes again") + ("HTH" . "hope this helps") + ("IAC" . "in any case") + ("IANAL" . "i am not a lawyer") + ("IC" . "i see") + ("ICBW" . "i could be wrong") + ("ICCL" . "i couldn't care less") + ("IHAFC" . "i haven't a fucking clue") + ("IHBW" . "i have been wrong") + ("IHNFC" . "i have no fucking clue") + ("IIANM" . "if i am not mistaken") + ("IIRC" . "if i recall correctly") + ("IIUC" . "if i understand correctly") + ("IMAO" . "in my arrogant opinion") + ("IMCO" . "in my considered opinion") + ("IMHO" . "in my humble opinion") + ("IMNSHO" . "in my not so humble opinion") + ("IMO" . "in my opinion") + ("IOW" . "in other words") + ("IRL" . "in real life") + ("ISAGN" . "i see a great need") + ("ISTM" . "it seems to me") + ("ISTR" . "i seem to recall") + ("ITYM" . "i think you mean") + ("IWBNI" . "it would be nice if") + ("IYSS" . "if you say so") + ("J/K" . "just kidding") + ("JHD" . "just hit ``delete''") + ("JIC" . "just in case") + ("JK" . "just kidding") + ("JMO" . "just my opinion") + ("JSYK" . "just so you know") + ("JTLYK" . "just to let you know") + ("KISS" . "keep it simple, stupid") + ("KITA" . "kick in the ass") + ("KNF" . "kernel normal form") + ("L8R" . "later") + ("LART" . "luser attitude readjustment tool (ie, hammer)") + ("LBNL" . "last but not least") + ("LGTM" . "looks good to me") + ("LJBF" . "let's just be friends") + ("LMAO" . "laughing my ass off") + ("LMSO" . "laughing my socks off") + ("LOL" . "laughing out loud") + ("LTNS" . "long time no see") + ("MIA" . "missing in action") + ("MOTAS" . "member of the appropriate sex") + ("MOTOS" . "member of the opposite sex") + ("MOTSS" . "member of the same sex") + ("MTF" . "more to follow") + ("MYOB" . "mind your own business") + ("N/M" . "never mind") + ("NBD" . "no big deal") + ("NFC" . "no fucking clue") + ("NFI" . "no fucking idea") + ("NFW" . "no fucking way") + ("NIH" . "not invented here") + ("NMF" . "not my fault") + ("NMP" . "not my problem") + ("NOYB" . "none of your business") + ("NOYFB" . "none of your fucking business") + ("NP" . "no problem") + ("NRFPT" . "not ready for prime time") + ("NRN" . "no reply necessary") + ("NSFW" . "not suitable for work") + ("OIC" . "oh, i see") + ("OMG" . "oh, my god") + ("OT" . "off topic") + ("OTL" . "out to lunch") + ("OTOH" . "on the other hand") + ("OTT" . "over the top") + ("OTTOMH" . "off the top of my head") + ("PDQ" . "pretty darn quick") + ("PEBKAC" . "problem exists between keyboard and chair") + ("PFO" . "please fuck off") + ("PFY" . "pimply faced youth") + ("PITA" . "pain in the ass") + ("PKSP" . "pound keys and spew profanity") + ("PNG" . "persona non grata") + ("PNP" . "plug and pray") + ("POC" . "point of contact") + ("POLA" . "principle of least astonishment") + ("POLS" . "principle of least surprise") + ("POS" . "piece of shit") + ("PPL" . "pretty please") + ("PTV" . "parental tunnel vision") + ("QED" . "quod erat demonstrandum") + ("RFC" . "request for comments") + ("RIP" . "rest in peace") + ("RL" . "real life") + ("RLC" . "rod length check") + ("ROFL" . "rolling on floor laughing") + ("ROFLMAO" . "rolling on floor laughing my ass off") + ("ROTFL" . "rolling on the floor laughing") + ("RP" . "responsible person") + ("RSN" . "real soon now") + ("RTFB" . "read the fine/fucking book") + ("RTFC" . "read the fine/fucking code") + ("RTFD" . "read the fine/fucking documentation") + ("RTFM" . "read the fine/fucking manual") + ("RTFMP" . "read the fine/fucking man page") + ("RTFS" . "read the fine/fucking source") + ("SCNR" . "sorry, could not resist") + ("SEP" . "someone else's problem") + ("SFA" . "sweet fuck all") + ("SHID" . "slaps head in disgust") + ("SIMCA" . "sitting in my chair amused") + ("SMLSFB" . "so many losers, so few bullets") + ("SMOP" . "simple matter of programming") + ("SNAFU" . "situation normal, all fucked up") + ("SNERT" . "snot-nosed egotistical rude teenager") + ("SNMP" . "sorry, not my problem") + ("SNR" . "signal to noise ratio") + ("SO" . "significant other") + ("SOB" . "son of [a] bitch") + ("SOL" . "shit out [of] luck") + ("SOP" . "standard operating procedure") + ("SSIA" . "subject says it all") + ("SSTO" . "single stage to orbit") + ("STFA" . "search the fucking archives") + ("STFU" . "shut the fuck up") + ("STFW" . "search the fucking web") + ("SUS" . "stupid user syndrome") + ("SWAG" . "silly, wild-assed guess") + ("SWAHBI" . "silly, wild-assed hare-brained idea") + ("SWFG" . "search with fucking google") + ("SWMBO" . "she who must be obeyed") + ("TANSTAAFL" . "there ain't no such thing as a free lunch") + ("TBC" . "to be continued") + ("TBD" . "to be {decided,determined,done}") + ("TBH" . "to be honest") + ("TBOMK" . "the best of my knowledge") + ("THNX" . "thanks") + ("THX" . "thanks") + ("TIA" . "thanks in advance") + ("TINC" . "there is no cabal") + ("TLA" . "three letter acronym") + ("TLC" . "tender loving care") + ("TLDR" . "too long, didn't read") + ("TMA" . "too many abbreviations") + ("TMI" . "too much information") + ("TMTOWTDI" . "there's more than one way to do it") + ("TNF" . "The NetBSD Foundation") + ("TOEFL" . "test of english as a foreign language") + ("TPTB" . "the powers that be") + ("TRT" . "the right thing") + ("TTBOMK" . "to the best of my knowledge") + ("TTFN" . "ta ta for now") + ("TTYL" . "talk to you later") + ("TWIAVBP" . "the world is a very big place") + ("TY" . "thank you") + ("TYVM" . "thank you very much") + ("U/L" . "upload") + ("UTSL" . "use the source, luke") + ("VEG" . "very evil grin") + ("W/" . "with") + ("W/O" . "without") + ("WAG" . "wild-ass guess") + ("WB" . "welcome back") + ("WFH" . "working from home") + ("WFM" . "works for me") + ("WIBNI" . "wouldn't it be nice if") + ("WIP" . "work in progress") + ("WOFTAM" . "waste of fucking time and money") + ("WOMBAT" . "waste of money, brain, and time") + ("WRT" . "with respect to") + ("WTF" . "{what,where,who,why} the fuck") + ("WTH" . "{what,where,who,why} the hell") + ("WYSIWYG" . "what you see is what you get") + ("YALIMO" . "you are lame, in my opinion") + ("YHBT" . "you have been trolled") + ("YHL" . "you have lost") + ("YKWIM" . "you know what i mean") + ("YMA" . "yo momma's ass") + ("YMMV" . "your mileage may vary") + ("YW" . "you're welcome") + ;; $NetBSD: acronyms.comp,v 1.72 2007/01/19 + ("3WHS" . "three-way handshake") + ("ABI" . "application binary interface") + ("ACL" . "access control list") + ("ACPI" . "advanced configuration and power interface") + ("ADC" . "analog [to] digital converter") + ("ADPCM" . "adaptive differential pulse code modulation") + ("ADSL" . "asymmetric digital subscriber line") + ("AGP" . "accelerated graphics port") + ("AM" . "amplitude modulation") + ("AMI" . "alternate mark inversion") + ("ANSI" . "american national standards institute") + ("AP" . "access point") + ("API" . "application programming interface") + ("APIC" . "advanced programmable interrupt controller") + ("ARP" . "address resolution protocol") + ("ARQ" . "automatic repeat request") + ("AS" . "autonomous system") + ("ASCII" . "american standard code for information interchange") + ("ASN" . "autonomous system number") + ("AT" . "advanced technology") + ("ATA" . "advanced technology attachment") + ("ATAPI" . "advanced technology attachment packet interface") + ("ATC" . "address translation cache") + ("ATM" . "asynchronous transfer mode") + ("ATX" . "advanced technology extended") + ("BEDO" . "burst extended data output") + ("BER" . "basic encoding rules") + ("BER" . "bit error rate") + ("BGP" . "border gateway protocol") + ("BIOS" . "basic input/output system") + ("BLOB" . "binary large object") + ("BPS" . "bits per second") + ("BQS" . "berkeley quality software") + ("BSD" . "berkeley software distribution") + ("CAD" . "computer-aided design") + ("CARP" . "common address redundancy protocol") + ("CAV" . "Constant Angular Velocity (as opposed to CLV)") + ("CCD" . "charge coupled device") + ("CD" . "compact disc") + ("CDDA" . "compact disc digital audio") + ("CDRAM" . "cache dynamic random access memory") + ("CER" . "canonical encoding rules") + ("CGA" . "color graphics {array,adapter}") + ("CGI" . "common gateway interface") + ("CHS" . "cylinder/head/sector") + ("CIDR" . "classless inter-domain routing") + ("CIS" . "contact image sensor") + ("CLI" . "command line interface") + ("CLUT" . "color look-up table") + ("CLV" . "Constant Linear Velocity (as opposed to CAV)") + ("CMYK" . "cyan magenta yellow black") + ("COFF" . "common object file format") + ("COW" . "copy-on-write") + ("CPU" . "central processing unit") + ("CRLF" . "carriage return line feed") + ("CRT" . "cathode ray tube") + ("CSMA" . "carrier sense multiple access") + ("CSMA/CA" . "carrier sense multiple access with collision avoidance") + ("CSMA/CD" . "carrier sense multiple access with collision detection") + ("CSS" . "cascading style sheets") + ("CTS" . "clear to send") + ("CVS" . "concurrent versions system") + ("DAC" . "digital [to] analog converter") + ("DCE" . "data control equipment") + ("DCE" . "distributed computing environment") + ("DCT" . "discrete cosine transform") + ("DDC" . "display data channel") + ("DDR" . "double data rate") + ("DDWG" . "digital display working group") + ("DER" . "distinguished encoding rules") + ("DFT" . "discrete fourier transform") + ("DHCP" . "dynamic host configuration protocol") + ("DIFS" . "distributed inter-frame space") + ("DLE" . "data link escape") + ("DMA" . "direct memory access") + ("DNS" . "domain name system") + ("DOS" . "denial of service") + ("DPCM" . "differential pulse code modulation") + ("DPD" . "dead peer detection") + ("DPI" . "dots per inch") + ("DRAM" . "dynamic random access memory") + ("DSL" . "digital subscriber line") + ("DSSS" . "direct sequence spread spectrum") + ("DTD" . "document type definition") + ("DTE" . "data terminal equipment") + ("DTE" . "dumb terminal emulator") + ("DVD" . "digital versatile disc") + ("DVI" . "digital visual interface") + ("E-XER" . "Extended XML encoding Rules") + ("EAP" . "extensible authentication protocol") + ("ECP" . "enhanced capability port") + ("EDID" . "extended display identification data") + ("EDO" . "extended data out") + ("EEPROM" . "electrically erasable programmable read only memory") + ("EFI" . "extensible firmware interface") + ("EFM" . "eight to fourteen modulation") + ("EGA" . "enhanced graphics {array,adapter}") + ("EGP" . "exterior gateway protocol") + ("EISA" . "extended industry standard architecture") + ("ELF" . "executable and linking format") + ("EOF" . "end of file") + ("EOT" . "end of transmission") + ("EPP" . "enhanced parallel port") + ("EPRML" . "extended partial response, maximum likelihood") + ("EPROM" . "erasable programmable read only memory") + ("ESDRAM" . "enhanced synchronous dynamic random access memory") + ("FAT" . "file allocation table") + ("FBRAM" . "frame buffer random access memory") + ("FCS" . "frame check sequence") + ("FDDI" . "fiber distributed data interface") + ("FFS" . "fast file system") + ("FHSS" . "frequency hop spread spectrum") + ("FIR" . "fast infrared") + ("FLOPS" . "floating [point] operations per second") + ("FM" . "frequency modulation") + ("FPM" . "fast page mode") + ("FQDN" . "fully qualified domain name") + ("FTP" . "file transfer protocol") + ("FTPS" . "file transfer protocol, secure") + ("GC" . "garbage collector") + ("GCR" . "group-coded recording") + ("GIF" . "graphics interchange format") + ("GNU" . "GNU's Not UNIX") + ("GPL" . "GNU/General Public License") + ("GPU" . "graphics processing unit") + ("GRE" . "generic routing encapsulation") + ("GUI" . "graphics user interface") + ("HDCP" . "high-bandwidth digital content protection") + ("HTML" . "hyper-text markup language") + ("HTTP" . "hyper-text transfer protocol") + ("HTTPS" . "hyper-text transfer protocol, secure") + ("I2O" . "intelligent input/output") + ("IANA" . "internet assigned number authority") + ("IC" . "integrated circuit") + ("ICB" . "internet citizen's band") + ("ICMP" . "internet control message protocol") + ("IDE" . "integrated drive electronics") + ("IDRP" . "inter-domain routing protocol") + ("IEC" . "international electrotechnical commission") + ("IEEE" . "institute [of] electrical [and] electronics engineers") + ("IESG" . "internet engineering steering group") + ("IETF" . "internet engineering task force") + ("IGP" . "interior gateway protocol") + ("IKE" . "internet key exchange") + ("IMAP" . "internet mail access protocol") + ("INCITS" . "international committee on information technology standards") + ("IO" . "input/output") + ("IOCTL" . "input/output control") + ("IP" . "internet protocol") + ("IPC" . "interprocess communication") + ("IPNG" . "internet protocol, next generation") + ("IPSEC" . "internet protocol security") + ("IRC" . "internet relay chat") + ("IRQ" . "interrupt request") + ("IRTF" . "internet research task force") + ("ISA" . "industry standard architecture") + ("ISDN" . "integrated services digital network") + ("ISI" . "inter-symbol interference") + ("ISM" . "industrial, scientific and medical") + ("ISN" . "initial serial number") + ("ISO" . "international standards organization") + ("ISOC" . "internet society") + ("ISP" . "internet service provider") + ("JPEG" . "joint photographic experts group") + ("KPI" . "kernel programming interface") + ("KVA" . "kernel virtual address") + ("KVM" . "keyboard, video, mouse switch") + ("LAN" . "local area network") + ("LBA" . "logical block addressing") + ("LCD" . "liquid crystal display") + ("LCP" . "link control protocol") + ("LDAP" . "lightweight directory access protocol") + ("LED" . "light emitting diode") + ("LIR" . "local internet registry") + ("LKM" . "{linux, loadable} kernel module") + ("LLC" . "logical link control") + ("LRC" . "longitudinal redundancy check") + ("LSB" . "least significant {bit,byte}") + ("LSB" . "linux standards base") + ("LUN" . "logical unit number") + ("LZW" . "Lempel Ziv Welch") + ("MAC" . "medium access control") + ("MBR" . "master boot record") + ("MDRAM" . "multibank dynamic random access memory") + ("MFM" . "modified frequency modulation") + ("MIDI" . "musical instrument digital interface") + ("MIME" . "multipurpose internet mail extensions") + ("MIPS" . "million instructions per second") + ("MMU" . "memory management unit") + ("MPEG" . "moving picture experts group") + ("MPLS" . "multiprotocol label switching") + ("MSB" . "most significant {bit,byte}") + ("MSF" . "minutes seconds frames") + ("MSS" . "maximum segment size") + ("MTA" . "mail transfer agent") + ("MTU" . "maximum transmission unit") + ("MUA" . "mail user agent") + ("MWE" . "module width encoding") + ("NAT" . "network address translation") + ("NAV" . "network allocation vector") + ("NCP" . "network control protocol") + ("NCQ" . "native command queuing") + ("NFS" . "network file system") + ("NIC" . "network interface card") + ("NIS" . "network information service") + ("NRZ" . "non-return to zero") + ("NUMA" . "non uniform memory access") + ("OCL" . "object constraint language") + ("OCR" . "optical character recognition") + ("OEM" . "original equipment manufacturer") + ("OFDM" . "orthogonal frequency division multiplexing") + ("OSF" . "open software foundation") + ("OSI" . "open systems interconnection") + ("OSI" . "open-source initiative") + ("OSPF" . "open shortest path first") + ("OTP" . "one time password") + ("PAM" . "pluggable authentication modules") + ("PAM" . "pulse amplitude modulation") + ("PAT" . "port address translation") + ("PAX" . "portable archive exchange") + ("PC" . "personal computer") + ("PCI" . "peripheral component interconnect") + ("PCM" . "pulse code modulation") + ("PCMCIA" . "personal computer memory card international association") + ("PDP" . "page descriptor page") + ("PDU" . "protocol data unit") + ("PER" . "packed encoding rules") + ("PERL" . "practical extraction [and] report language") + ("PFS" . "perfect forward secrecy") + ("PGP" . "pretty good privacy") + ("PIC" . "programmable interrupt controller") + ("PID" . "process id") + ("PIN" . "personal identification number") + ("PIO" . "programmed input/output") + ("PLL" . "phase locked loop") + ("PMT" . "photo-multiplier tube") + ("PNG" . "portable network graphics") + ("POP" . "post office protocol") + ("POSIX" . "Portable Operating System Interface [for] UNIX") + ("POST" . "power on self test") + ("POTS" . "plain old telephone system") + ("PPP" . "point-to-point protocol") + ("PPPOA" . "point-to-point protocol over ATM") + ("PPPOE" . "point-to-point protocol over ethernet") + ("PRML" . "partial response, maximum likelihood") + ("PROM" . "programmable read only memory") + ("PSK" . "pre-shared key") + ("PSTN" . "public switched telephone network") + ("PTE" . "page table entry") + ("PTLA" . "pseudo top level aggregator") + ("PTP" . "page table page") + ("PWM" . "pulse width modulation") + ("QOS" . "quality of service") + ("RAID" . "redundant array of inexpensive disks") + ("RAM" . "random access memory") + ("RCS" . "revision control system") + ("RGB" . "red green blue") + ("RIFF" . "Resource Interchange File Format") + ("RIP" . "routing information protocol") + ("RIR" . "regional internet registry") + ("RISC" . "reduced instruction set computing") + ("RLE" . "run length encoding") + ("RLL" . "run length limited") + ("ROM" . "read only memory") + ("RPM" . "revolutions per minute") + ("RTF" . "rich text format") + ("RTS" . "request to send") + ("RTT" . "round time trip") + ("S/PDIF" . "sony/phillips digital interface") + ("SACD" . "super audio compact disc") + ("SAD" . "security association database") + ("SAM" . "serial access memory") + ("SASI" . "Shugart Associates System Interface (predecessor to SCSI)") + ("SATA" . "serial advanced technology attachment") + ("SB" . "sound blaster") + ("SCM" . "software configuration management") + ("SCM" . "source code management") + ("SCSI" . "small computer system interface") + ("SDRAM" . "synchronous dynamic random access memory") + ("SGRAM" . "synchronous graphics random access memory") + ("SIFS" . "short inter-frame space") + ("SIP" . "session initiation protocol") + ("SIR" . "slow infrared") + ("SLDRAM" . "synchronous-link dynamic random access memory") + ("SMART" . "self-monitoring analysis and reporting technology") + ("SMP" . "symmetric multiprocessing") + ("SMTP" . "simple mail transfer protocol") + ("SNMP" . "simple network management protocol") + ("SPD" . "security policy database") + ("SPD" . "serial presence detect") + ("SRAM" . "static random access memory") + ("SSFDC" . "solid state floppy disc card") + ("SSH" . "secure shell") + ("SSL" . "secure sockets layer") + ("STP" . "shielded twisted pair") + ("SVGA" . "super video graphics {array,adapter}") + ("TCL" . "tool command language") + ("TCP" . "transmission control protocol") + ("TCQ" . "tagged command queueing") + ("TDD" . "test driven development") + ("TFT" . "thin film transistor") + ("TFTP" . "trivial file transfer protocol") + ("TIFF" . "tagged image file format") + ("TLA" . "top level aggregator") + ("TLB" . "transition lookaside buffer") + ("TLD" . "top level domain") + ("TLS" . "transport layer security") + ("TMDS" . "transition minimized differential signaling") + ("TR" . "token ring") + ("TTL" . "time to live") + ("TTY" . "teletype") + ("TZ" . "time zone") + ("UART" . "universal asynchronous receiver/transmitter") + ("UC" . "uncacheable") + ("UDO" . "ultra density optical (storage)") + ("UDP" . "user datagram protocol") + ("UFS" . "UNIX file system") + ("UML" . "unified modeling language") + ("UPS" . "uninterruptible power supply") + ("URI" . "uniform resource identifier") + ("URL" . "uniform resource locator") + ("USART" . "universal synchronous/asynchronous receiver/transmitter") + ("USB" . "universal serial bus") + ("USWC" . "uncacheable speculative write combining") + ("UTP" . "unshielded twisted pair") + ("UUCP" . "unix-to-unix copy protocol") + ("UUOC" . "useless use of cat") + ("VAX" . "virtual address extension") + ("VCM" . "virtual channel memory") + ("VESA" . "video electronics standards association") + ("VGA" . "video graphics {array,adapter}") + ("WIFI" . "wireless fidelity") + ("VLAN" . "virtual local area network") + ("VLSM" . "variable length subnet mask") + ("VM" . "virtual {machine,memory}") + ("VPN" . "virtual private network") + ("VRAM" . "video random access memory") + ("VRRP" . "virtual router redundancy protocol") + ("WAN" . "wide area network") + ("WAP" . "wireless application protocol") + ("WEP" . "wired equivalent privacy") + ("WLAN" . "wireless local area network") + ("WPA" . "wi-fi protected access") + ("WRAM" . "window random access memory") + ("WWW" . "world wide web") + ("XER" . "XML Encoding Rules") + ("XGA" . "extended graphics {array,adapter}") + ("XML" . "extensible markup language") + ("XSL" . "extensible stylesheet language") + ("XT" . "extended technology") + ("ZFOD" . "zero-filled on demand") + ;; Additional acronym definitions go here + ("AAMOF" . "as a matter of fact") + ("AISI" . "as i see it") + ("ASAIMS" . "as strange as it may seem") + ("ATSL" . "along the same line") + ("AYOR" . "at your own risk") + ("BTAIM" . "be that as it may") + ("BTDTBTTS" . "been there, done that, bought the t-shirt") + ("BTHOM" . "beats the hell outta me") + ("CBA" . "can't be arsed") + ("DBD" . "Defective By Design") + ("DIIK" . "damned if i know") + ("EFF" . "Electronic Frontier Foundation") + ("FFII" . "Foundation for a Free Information Infrastructure") + ("FOAF" . "friend of a friend") + ("FSF" . "Free Software Foundation") + ("FTR" . "for the record") + ("FTBFS" . "failure to build from source") + ("GAFC" . "get a fucking clue") + ("IAE" . "in any event") + ("IBTD" . "i beg to differ") + ("ICBF" . "i can't be fucked") + ("IDS" . "intrusion detection system") + ("IDK" . "i don't know") + ("IJWTS" . "i just want to say") + ("IME" . "in my experience") + ("IYSWIM" . "if you see what i mean") + ("JFTR" . "just for the record") + ("NIFOC" . "naked in front of computer") + ("NPOV" . "neutral point of view") + ("PITB" . "pain in the butt") + ("POV" . "point of view") + ("ROTFLMAO" . "rolling on the floor laughing my ass off") + ("SWIM" . "see what i mean") + ("TNSTAAFL" . "there's no such thing as a free lunch") + ("TWAT" . "the war against terrorism") + ("WDOT" . "what do others think") + ("WDYMBT" . "what do you mean by that") + ("WDYT" . "what do you think") + ("WTB" . "where's the beef") + ("WTSHTF" . "when the shit hits the fan") + ("WTTM" . "without thinking too much") + ("WOTAM" . "waste of time and money") + ("YAGNI" . "you ain't gonna need it") + ("YGWYPF" . "you get what you pay for")) + "Mapping of acronyms to definitions.") + +;;; Utilities + +(defun wtf-match-string-no-properties (num &optional string) + "Return NUMth match of STRING sans text properties." + (if (fboundp 'match-string-no-properties) + (match-string-no-properties num string) + (match-string num string))) + +(defun wtf-remove-one (key alist) + "Remove only the first instance of KEY from ALIST. +ALIST should be a symbol, the value of which is modified directly. +Returns non-nil if an element was found and removed, nil otherwise." + (let ((svalist (symbol-value alist))) + (if (equal key (caar svalist)) + (prog1 t + (set alist (cdr svalist))) + (catch 'done + (let ((cur (cadr svalist)) + (prev svalist)) + (while cur + (if (equal key (car cur)) + (throw 'done + (prog1 t + (setcdr prev (cddr prev)))) + (setq prev (cdr prev) + cur (cadr prev)))) + nil))))) + +(defun wtf-multi-assoc (key &rest alists) + "Return a list of all values in all ALISTS that are associated with KEY." + (let ((vals nil)) + (dolist (alist alists) + (dolist (pair alist) + (when (equal key (car pair)) + (setq vals (cons (cdr pair) vals))))) + (nreverse vals))) + +(defun wtf-upcase-initials (string) + "Do `upcase-initials' on STRING, but do not uppercase letters +that come after quote characters. + +This function clobbers the match data." + (with-temp-buffer + (insert (upcase-initials string)) + (goto-char (point-min)) + (while (re-search-forward "['`]\\([[:upper:]]\\)" nil t) + (downcase-region (match-beginning 1) (match-end 1))) + (buffer-string))) + +(defun wtf-upcase-initials-maybe (string) + "Do `wtf-upcase-initials' on STRING only if STRING contains no +existing capitalization. + +This function clobbers the match data." + (let ((case-fold-search nil)) + (if (string-match "[A-Z]" string) + string + (wtf-upcase-initials string)))) + +;;; Implementation + +(defun wtf-lookup-term (term) + (setq term (upcase term)) + (wtf-multi-assoc term + (and (not (member term wtf-removed-acronyms)) + wtf-alist) + wtf-custom-alist)) + +(defun wtf-get-term-at-point () + "Return the term at point." + (interactive) + (save-excursion + (if (re-search-backward "\\W" (point-min) t) + (goto-char (1+ (point))) + (beginning-of-line)) + (when (looking-at "\\w+") + (let ((term (wtf-match-string-no-properties 0))) + (when (wtf-lookup-term term) + (downcase term)))))) + +(defun wtf-completions () + "Return a list of completions for terms." + (mapcar #'(lambda (term) + (list (downcase (car term)))) + (append wtf-alist wtf-custom-alist))) + +(defun wtf-save-maybe (var) + "If customizations are allowed, save VAR, which should be a symbol." + (when (fboundp 'customize-save-variable) + (customize-save-variable var (symbol-value var)) + (message "Saved wtf customization"))) + +;;; Interactive functions + +;;;###autoload +(defun wtf-add (acronym definition) + "Add ACRONYM and its DEFINITION to the list of custom associations. + +If you add a custom acronym definition, and feel it to be worth +sharing, you are encouraged to contact via +email, providing the acronym and its definition. This increases +the chance that it will appear in future versions of wtf.el." + (interactive "sAcronym: \nsDefinition: ") + (setq acronym (upcase acronym)) + (setq wtf-custom-alist (sort (cons (cons acronym definition) + wtf-custom-alist) + #'(lambda (a b) + (string< (car a) (car b))))) + (wtf-save-maybe 'wtf-custom-alist)) + +;;;###autoload +(defun wtf-remove (acronym) + "Remove ACRONYM from the list of custom associations. +If ACRONYM is not in the custom associations, but instead in +`wtf-alist', it will be marked as ignored by adding it to +`wtf-removed-acronyms'." + (interactive + (list (completing-read "Acronym to remove: " + (wtf-completions) nil t (wtf-get-term-at-point)))) + (setq acronym (upcase acronym)) + (if (wtf-remove-one acronym 'wtf-custom-alist) + (wtf-save-maybe 'wtf-custom-alist) + (add-to-list 'wtf-removed-acronyms acronym) + (wtf-save-maybe 'wtf-removed-acronyms))) + +;;;###autoload +(defun wtf-is (acronym) + "Provide the definition for ACRONYM. +When called interactively, display the message \"ACRONYM is DEF\". +Otherwise, return DEF. + +DEF refers to the definition associated with ACRONYM in `wtf-alist'." + (interactive + (list (completing-read "Acronym: " + (wtf-completions) nil t (wtf-get-term-at-point)))) + (when (stringp acronym) + (let ((defs (wtf-lookup-term acronym))) + (if (not defs) + (when (interactive-p) + (message "I don't know what %s means" (upcase acronym))) + (save-match-data + (let ((deftext (wtf-upcase-initials-maybe (car defs)))) + (when (cdr defs) + (dolist (def (cdr defs)) + (setq deftext (concat deftext wtf-def-separator + (wtf-upcase-initials-maybe def))))) + (if (interactive-p) + (message "%s is %s" (upcase acronym) deftext) + deftext))))))) + +(provide 'wtf) + +;;; wtf.el ends here diff --git a/elisp/erbot/erball.el b/elisp/erbot/erball.el new file mode 100644 index 0000000..e5e48ae --- /dev/null +++ b/elisp/erbot/erball.el @@ -0,0 +1,209 @@ +;;; erball.el --- Functions on all files. +;; Time-stamp: <2006-04-24 13:43:38 deego> +;; Copyright (C) 2002 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbc.el +;; Package: erbc +;; Author: D. Goel +;; Version: + + + +;; Usually maintenance +;; not all of these may be required depending on how you use erbot.. +(require 'cl) + +;; Compilation + +(defvar erball-compilation-paths-rel-to + (let (args ret) + (while command-line-args-left + (if (string= "--paths-rel-to" (car command-line-args-left)) + (progn + (setq ret (cadr command-line-args-left)) + (setq command-line-args-left (cddr command-line-args-left))) + (add-to-list 'args (car command-line-args-left) t) + (setq command-line-args-left (cdr command-line-args-left)))) + (setq command-line-args-left args) + ret) + "Text to be prepended to each element in `erball-compilation-paths'. +Can be specified by passing \"--paths-rel-to ARG\" on the emacs +command line. +This value is also added to the load-path. +A trailing backslash is required.") + +(defun erball-assoc-string (key list) + "Like `assoc' but specifically for strings." + (if (fboundp 'assoc-string) + (assoc-string key list) + (catch 'found + (dolist (el list) + (when (string= key el) + (throw 'found el)))))) + +(defvar erball-compiling-p + (if (erball-assoc-string "--compile-erbot" command-line-args-left) + (progn + (message "%s" (concat "\nCompiling source in " + (file-name-nondirectory (expand-file-name ".")) + " ...\n")) + (setq command-line-args-left + (delete "--compile-erbot" command-line-args-left)) + t) + nil) + "Determine whether erbot is currently being compiled.") + +(defcustom erball-compilation-paths + '("contrib" + ".." + "../erc" + "../bbdb/lisp") + "Elements to add to the load path during compilation. +If `erball-compilation-paths-rel-to' is specified, it is +prepended to each element and also added verbatim to the path. +The current directory is automatically added to the path." + :group 'erball + ) + +(when erball-compiling-p + (add-to-list 'load-path ".") + (when erball-compilation-paths-rel-to + (add-to-list 'load-path erball-compilation-paths-rel-to)) + (dolist (dir erball-compilation-paths) + (add-to-list 'load-path + (concat erball-compilation-paths-rel-to dir)))) + +;; Load all erbot files + +(defmacro erball-ignore-errors-loudly (&rest body) + "Like ignore-errors, but tells the error.. + +Copied from deego's `ignore-errors-my', which owes some of its work +to: Kalle on 7/3/01: + * used backquote: something i was too lazy to convert my macro to.. + * removed the progn: condition-case automatically has one.. + * made sure that the return is nil.. just as it is in ignore-errors. " + (let ((err (gensym))) + `(condition-case ,err (progn ,@body) + (error + (ding t) + (ding t) + (ding t) + (message "IGNORED ERROR: %s" (error-message-string ,err)) + (sit-for 1) + nil)))) + + + +(erball-ignore-errors-loudly (require 'bbdb)) +(erball-ignore-errors-loudly (require 'doctor)) +(erball-ignore-errors-loudly (require 'erc)) +(erball-ignore-errors-loudly (require 'erc-stamp)) + + + +(unless noninteractive (erball-ignore-errors-loudly (require 'dunnet))) +(erball-ignore-errors-loudly (require 'erbot)) +(erball-ignore-errors-loudly (require 'erbcountry)) +(erball-ignore-errors-loudly (require 'erbutils)) +(erball-ignore-errors-loudly (require 'erblog)) +(erball-ignore-errors-loudly (require 'erbeng)) +(erball-ignore-errors-loudly (require 'erbdata)) +(erball-ignore-errors-loudly (require 'erbkarma)) +(erball-ignore-errors-loudly (require 'erblisp)) +(erball-ignore-errors-loudly (require 'erbc)) +(erball-ignore-errors-loudly (require 'erbc2)) +(erball-ignore-errors-loudly (require 'erbc3)) +(erball-ignore-errors-loudly (require 'erbc4)) +(erball-ignore-errors-loudly (require 'erbc5)) +(erball-ignore-errors-loudly (require 'erbc6)) +(erball-ignore-errors-loudly (require 'erbcspecial)) +(erball-ignore-errors-loudly (require 'erbbdb)) +(erball-ignore-errors-loudly (require 'erbforget)) +(erball-ignore-errors-loudly (require 'erbedit)) +(erball-ignore-errors-loudly (require 'erbtrain)) +(erball-ignore-errors-loudly (require 'erbwiki)) +(erball-ignore-errors-loudly (require 'erbunlisp)) +(erball-ignore-errors-loudly (require 'erbcompat)) + +(erball-ignore-errors-loudly (require 'erbmsg)) +(erball-ignore-errors-loudly (require 'erbtranslate)) +(erball-ignore-errors-loudly (require 'erbim)) + +(erball-ignore-errors-loudly (require 'flame)) + +(erball-ignore-errors-loudly (require 'mkback)) +(erball-ignore-errors-loudly (require 'lines)) +(erball-ignore-errors-loudly (require 'google)) +(erball-ignore-errors-loudly (require 'oct)) + +;; the rest of the commands here are useful to the author when editing erbot. + +(defcustom erball-files + (if erball-compiling-p + (directory-files "." nil "\.el$") + '("erbot.el" + "erbutils.el" + "erblog.el" + "erbeng.el" + "erbcountry.el" + "erbdata.el" + "erbedit.el" + "erbforget.el" + "erbkarma.el" + "erblisp.el" + "erbunlisp.el" + "erbtrain.el" + "erbwiki.el" + "erbc.el" + "erbc2.el" + "erbc3.el" + "erbc4.el" + "erbc5.el" + "erbc6.el" + )) + + "" + :group 'erball + ) + +(defun erball-reload () + (interactive) + (mapcar + 'load + erball-files)) + +(defun erball-visit () + (interactive) + (mapcar + (lambda (a) + (find-file (locate-library a)) + (auto-revert-mode 1)) + erball-files)) + +;;;###autoload +(defun erball-compile () + (interactive) + (if erball-compiling-p + (progn + (ignore-errors (erball-reload)) + (mapcar + (lambda (arg) + (erball-ignore-errors-loudly + (byte-compile-file arg))) + erball-files) + (message "\nCompilation complete!\n")) + (ignore-errors (kill-buffer "*Compile-Log*")) + (erball-visit) + (erball-reload) + (mapcar + (lambda (arg) + (erball-ignore-errors-loudly + (byte-compile-file (locate-library arg)))) + erball-files) + (switch-to-buffer "*Compile-Log*") + (delete-other-windows) + (goto-char (point-min)))) + + +(provide 'erball) diff --git a/elisp/erbot/erbbdb.el b/elisp/erbot/erbbdb.el new file mode 100644 index 0000000..30684a5 --- /dev/null +++ b/elisp/erbot/erbbdb.el @@ -0,0 +1,223 @@ +;;; erbbdb.el --- +;; Time-stamp: <2007-11-23 11:30:13 deego> +;; Copyright (C) 2002 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbbdb.el +;; Package: erbbdb +;; Author: D. Goel +;; Version: 0.0dev +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + + + + +(defvar erbbdb-version "0.0dev") + +;;========================================== +;;; Code: +(ignore-errors (require 'bbdb)) +(ignore-errors (require 'bbdb-com)) +(ignore-errors (require 'bbdb-hooks)) + +(require 'erbc) + +(defgroup erbbdb nil + "The group erbbdb" + :group 'applications) +(defcustom erbbdb-before-load-hooks nil "." :group 'erbbdb) +(defcustom erbbdb-after-load-hooks nil "" :group 'erbbdb) +(run-hooks 'erbbdb-before-load-hooks) + + +(defun erbbdb-get-exact-notes (string) + (erbbdb-get-regexp-notes (concat "^" (regexp-quote + (erbbdb-frob-main-entry string) + ) "$"))) + +(defun erbbdb-get-exact-name (string) + (erbbdb-get-regexp-name (concat "^" (regexp-quote + (erbbdb-frob-main-entry string) + ) "$"))) + + + +(defun erbbdb-get-regexp-record (expr) + "dsfdfdf" + (let ((records + (bbdb-search (bbdb-records) + expr))) + (first records))) + +(defun erbbdb-get-record (str) + (erbbdb-get-regexp-record + (concat "^" (regexp-quote + (erbbdb-frob-main-entry str)) "$"))) + +(defun erbbdb-get-regexp-name (expr) + "used to get exact name, eg: the exact name of tmpa may be TmpA." + (let ((record (car + ;; this basically does an M-x bbdb-name + (bbdb-search (bbdb-records) + expr)))) + (if record + (aref record 0) + nil))) + +(defun erbbdb-get-regexp-notes (expr) + "currently: Assumes that there will be only one match for the expr +in bbdb... Discards any further matches... + +If the notes are (), we want it to return nil, not a string.. so that +the calling function knows there's (effectively) no such record... + +That is why we have the read below.. + +This of course, also means that the notes field had better contain a +lisp sexp.. and anythign after the sexp gets discarded... + +If record exists but no notes exist, \"\" is returned. +Else the string containing the notes is returned. +If no record exists, then a nil is returned. +" + (let ((record (car + ;; this basically does an M-x bbdb-name + (bbdb-search (bbdb-records) + expr)))) + (if record + (let* ((notes-notes (assq 'notes (bbdb-record-raw-notes record))) + (notes-string (cdr notes-notes))) + (or notes-string "") + ;;(if foo (read foo) nil) + ) + nil))) + + +(defun erbbdb-frob-main-entry (givenname) + (let* ((sname (format "%s" givenname)) + ;;(dname (downcase sname)) + (dname sname) + (bname (split-string dname)) + (name (mapconcat 'identity bname "-"))) + name)) + +(defun erbbdb-change (givenname notes) + "also used by other functions in here.." + + (bbdb-records) + + (let* ((sname (format "%s" givenname)) + ;;(dname (downcase sname)) + (dname sname) + (bname (split-string dname)) + (name (mapconcat 'identity bname "-"))) + ;;(let ((record + ;; (vector + ;; ;; first name + ;; name + ;; ;;lastname + ;; nil + ;; nil + ;; nil ;;company + ;; nil ;;phones + ;; nil ;; addrs + ;; nil ;;net + ;; (format "%s" notes) + ;; ; (make-vector bbdb-cache-length nil)))) + ;; (bbdb-change-record record t)) + (let* ((record (erbbdb-get-record name))) + (bbdb-record-set-notes record notes) + (bbdb-change-record record t) + (erbbdb-save)))) + +(defun erbbdb-save () + (when + erbbdb-save-p + (bbdb-save-db))) + +(defvar erbbdb-save-p t + "Should normally be t, except inside special constructions. ") + + +(defun erbbdb-create (name newnotes) + "also used by other functions in here.." + (bbdb-records) + (let ((record + (vector + ;; first name + name + ;;lastname + nil + nil + nil ;;company + nil ;;phones + nil ;; addrs + nil ;;net + nil ;; (format "%s" newnotes) + (make-vector bbdb-cache-length nil)))) + (bbdb-record-set-notes record nil) + (mapcar '(lambda (arg) + (erbbdb-add name arg)) + newnotes) + ) + (erbbdb-save)) + +(defun erbbdb-add (name note) + (bbdb-records) + (let* ((oldnotes + (erbbdb-get-exact-notes name)) + (newnotes nil)) + + ;; should almost always be the case.. except when nil.. + (if (stringp oldnotes) + (setq oldnotes + (ignore-errors (erbn-read oldnotes)))) + (setq newnotes (format "%S" (append oldnotes (list note)))) + (erbbdb-remove-not-really name) + (erbbdb-change name newnotes))) + + +(defun erbbdb-remove-not-really (name) + (erbbdb-change name nil)) +(defun erbbdb-remove (givenname) + "Remove the record implied by givenname from bbdb.." + ;;(erbbdb-change name nil) + (bbdb-records) + (let* ((sname (format "%s" givenname)) + ;;(dname (downcase sname)) + (dname sname) + (bname (split-string dname)) + (name (mapconcat 'identity bname "-"))) + (let* ((record (erbbdb-get-record name))) + (when record + (bbdb-delete-current-record record t) + ;;(bbdb-record-set-notes record notes) + ;;(bbdb-change-record record t) + (erbbdb-save))))) + +(provide 'erbbdb) +(run-hooks 'erbbdb-after-load-hooks) + + + +;;; erbbdb.el ends here diff --git a/elisp/erbot/erbc-backquote.el b/elisp/erbot/erbc-backquote.el new file mode 100644 index 0000000..b61fbec --- /dev/null +++ b/elisp/erbot/erbc-backquote.el @@ -0,0 +1,57 @@ +;; 2004-08-20 T14:53:35-0400 (Friday) D. Goel +;; This file is work in progress. INCOMLPETE AND BUGGY. DO NOT REQUIRE +;; THIS FILE IN A BOT. + + +(defvar backquote-symbols (list (intern (string 96)) 'backquote)) + + +(defmacro backquote-parse (sexp) + "Will parse a sexp and return an equivalent sexp with no backquotes +in it. Any backquotes in the sexp are converted them to a +nonbackquoted form. " + (cond + ((atom sexp) sexp) + (t (cons 'quote (backquote-parse-unread sexp))))) + + + +(defun backquote-parse-unread (sexp) + (cond + ;;;((vectorp sexp) + ;;;(error "this backquote parse does not deal with vectors. ")) + ((null sexp) + nil) + ((atom sexp) + sexp) + ((equal (car sexp) 'quote) + (message "Answer is %s" sexp) + sexp) + ((member (car sexp) backquote-symbols) + (backquote-inside-parse (cadr sexp))) + ;; None of them: + (t (cons (backquote-parse-unread (car sexp)) + (backquote-parse-unread (cdr sexp)))))) + + + + + + +(defun backquote-inside-parse (sexp) + (cond + ((null sexp) + nil) + ((atom sexp) + (list 'quote sexp)) + ((equal (car sexp) ',) + `(eval ,(backquote-parse-unread (cadr sexp)))) + (t (cons (backquote-inside-parse (car sexp)) + (backquote-inside-parse (cdr sexp)))))) + + + + + + + diff --git a/elisp/erbot/erbc.el b/elisp/erbot/erbc.el new file mode 100644 index 0000000..0c81835 --- /dev/null +++ b/elisp/erbot/erbc.el @@ -0,0 +1,5141 @@ +;;; erbc.el --- Erbot user-interface commands -- see also erbc5.el +;; Time-stamp: <2009-09-26 22:20:39 fledermaus> +;; Copyright © 2002 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbc.el +;; Package: erbc +;; Author: D. Goel +;; Version: 0.0DEV +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; Other files: +;;; erball.el --- Functions on all files. +;;; erbbdb.el --- +;;; erbc.el --- Erbot user-interface commands. +;;; erbc2.el --- mostly: special functions for erbc.el +;;; erbc3.el ---erbot lisp stuff which should be PERSISTENT ACROSS SESSIONS. +;;; erbc4.el --- Russian Roulette +;;; erbc5.el --- continuation of erbc.el +;;; erbc6.el --- fsbot functions contributed by freenode users, +;;; esp. #emacsers. +;;; erbcompat.el --- Erbot GNU Emacs/XEmacs compatibility issues +;;; erbcountry.el +;;; erbc-special.el --- Special/dangerous implementation functions. +;;; erbdata.el --- +;;; erbedit.el --- quicker operator editing of bots' bbdb +;;; erbeng.el --- english +;;; erbforget.el --- Help make the bots forget some TERMS. +;;; erbkarma.el --- +;;; erblisp.el --- +;;; erblog.el --- +;;; erbmsg.el --- memoserv-esque functions for Erbot +;;; erbot.el --- Another robot for ERC. +;;; erbp.el --- NOT FUNCTIONAL personal erbot-interface, stolen from dunnet.el +;;; erbtrain.el --- Train erbot (erbot).. +;;; erbutils.el --- utils +;;; erbwiki.el --- + +(defvar fs-home-page + "http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot") + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + + + + +(defvar erbc-version "0.0dev") +(defvar fs-version "0.0dev") + + +;;========================================== +;;; Code: + +;; NOTE: stuff like (fs-et) can be passed possibly mischievous +;; code as the first argument... never eval or "set" any +;; "code"... always convert it to a single atom... before setting it.. + + + +(require 'find-func) + +(defgroup erbc nil + "The group erbc" + :group 'applications) + + +(defcustom fs-before-load-hooks nil "" :group 'erbc) +(defcustom fs-after-load-hooks nil "" :group 'erbc) + + + +(defcustom erbn-char "," + "The character which calls the bot. + +in addition to directly addressing it. + +may be different for +different bots. + +Is really a string, but the length of the string should be 1,. +") +(defcustom erbn-char-double (concat erbn-char erbn-char) + "The string which calls the bot from midsentence + +this string should have a length of EXACTLY 2. + +") + + +(run-hooks 'fs-before-load-hooks) + + +;; Real code +(defcustom fs-internal-botito-mode nil + "Mode to turn on more english-like bunny-behavior" + :group 'erbc) + + + +(defvar fs-tgt nil "Tgt visible to the end-user, as well as changeable by them.") +(defvar erbn-tgt nil "Tgt NOT changeable by enduser.") + +(defvar fs-nick "") +(defvar erbn-nick "") + +(defvar erbn-buffer "") + +(defcustom fs-internal-parse-error-p + nil + "Whether to show lispy errors in term descriptions. + +When nil, an error in a lispy description of a term makes to bot +go to an english mode for the term. +When non-nil, we will just display the error. On a channel full of +lisp hackers, we will want to make this t for users' convenience.") + + +(defcustom erbn-shell-command-p nil + "Whether to allow commands that use shell-commands... +Some fsbot commands use shell-commands... shell-commands always mean +possibility of exploits. andn are disabled by default. + +Make this t at your own risk. ") + + +(defcustom fs-internal-questions + '("what" "where" "who" + ;; no please: + ;;"why" + ;;"how" + ) + "" + :group 'erbc) + +(defcustom erbn-google-defaults + '(("#emacs" ("emacs")) + ("#fsbot" ("fsbot"))) + "" :group 'erbc) + + + +(defun erbn-shell-command (&optional command overridep) + "Execute shell-commands when erbn-shell-command-p is true. + +However, if the second argument overridep is non-nil, we use that to +determine whether to execute the command. In that case, we execute +the command only if overridep is a list, whose first entry of that +list is non-nil" + (cond + ((or (and overridep + (listp overridep) + (first overridep)) + erbn-shell-command-p) + (apply 'shell-command command nil)) + (t + (error "The bot-operator has shell commands disabled")))) + + + + + +(defun erbn-shell-command-to-string (&optional command overridep) + "Execute shell-commands when erbn-shell-command-p is true. + +However, if the second argument overridep is non-nil, we use that to +determine whether to execute the command. In that case, we execute +the command only if overridep is a list, whose first entry of that +list is non-nil" + (cond + ((or (and overridep + (listp overridep) + (first overridep)) + erbn-shell-command-p) + (apply 'shell-command-to-string command nil)) + (t + (error "The bot-operator has shell commands disabled")))) + + + + + +(defun fsi-get-google-defaults () + (cadr (assoc fs-tgt erbn-google-defaults))) + +(defvar fsi-prestring "") +;; (make-variable-buffer-local 'fsi-prestring) + + +(defcustom fs-internal-google-level 0 + "75 is a good choice for fsbot. " + :group 'erbc) +(defcustom fs-internal-english-max-matches 20 + "This check is triggerred only when the users' original request didnot +succeed and so we have gone into an english-mode and are searching. +If the number of matches results in 1000, then most likely, the word +was something like i or you and the user was not intending a search. +" + +:group 'erbc) + +(defcustom fs-internal-questions-all + '("what" "where" "who" "why" "how" + "whose" "which" + ) + "" + :group 'erbc) + +(defcustom fs-internal-articles + '("the" "a" "an" "this" "that") + "" + :group 'erbc) + + +(defcustom fs-internal-english-target-regexp + "^$" + "Targets that prefer english.. so erbot will usually go to a +english-mode unless near-exact matches. This shall usually happen on +the few social channels erbot hangs out on. " + :group 'erbc) + +(defcustom fs-internal-query-target-regexp + "^$" + "Targets where erbot will respond to queries like: +Foo ? " + :group 'erbc) + +(defcustom fs-internal-add-nick-weights + '(1 ;; yes + 5 ;;no + ) + "" + :group 'erbc) + + +(defun fsi-correct-entry (name &rest fubar) + "Assumes that name is a string... this downcases strings. Rendering +it fit for database-entry. " + (unless (stringp name) (setq name (format "%s" name))) + ;;(downcase + (let ((newname + (mapconcat 'identity (split-string name) "-"))) + (or (erbbdb-get-exact-name newname) + newname))) + + +(defun fsi-describe-key-briefly (&optional key &rest args) + "Return the function on key..building block for other erbc's.. +If no such function, return the symbol 'unbound. " + + (unless key + (error + "Syntax: , dkb key")) + (when (and (null key) (null args)) + (setq key "")) + (unless (stringp key) + ;; is this safe? what about properties? + (setq key (read-kbd-macro + (mapconcat '(lambda (arg) (format "%s" arg)) + (cons key args) + " ")))) + (let ((res (key-binding key))) + (if res res + 'unbound))) + +;; for now.. +;;(defalias 'fs-describe-key 'fs-describe-key-briefly) + +(defun fsi-where-is-in-map (map &optional fcn) + (let* ((wi (where-is-internal fcn map))) + (mapconcat 'key-description wi ", "))) + +(defun fsi-where-is-gnus-group (&optional fcn) + (require 'gnus) + (unless fcn (error "please supply a function")) + (fs-where-is-in-map gnus-group-mode-map fcn)) + +(defun fsi-where-is-gnus-summary (&optional fcn) + (require 'gnus) + (unless fcn (error "please supply a function")) + (fs-where-is-in-map gnus-summary-mode-map fcn)) +(defun fsi-where-is-message (&optional fcn) + (require 'gnus) + (require 'message) + + (unless fcn (error "please supply a function")) + (fs-where-is-in-map message-mode-map fcn)) + + + +(defun fsi-keyize (key morekeys) + (setq key (read-kbd-macro + (mapconcat '(lambda (arg) (format "%s" arg)) + (cons key morekeys) " ")))) + + +(defun fsi-describe-key-one-line (&optional key &rest args) + "Key, and just one line of function" + (unless key (error "Syntax: , dk \"Key...\"")) + (let* ((fcn (apply 'fs-describe-key-briefly key args)) + (fcns (format "%s" fcn)) + (apr (or (fs-apropos-exact fcns) + "No doc. available. "))) + (concat (format "%s -- %s" + fcns + apr)))) + +(defalias 'fsi-dko 'fs-describe-key-one-line) + +(defalias 'fsi-describe-key 'fs-describe-key-and-function) + +(defun fsi-lookup-key-from-map-internal (&optional map key &rest morekeys) + (unless key (error "No key supplied. ")) + (unless (stringp key) + (setq key (read-kbd-macro + (mapconcat '(lambda (arg) (format "%s" arg)) + (cons key morekeys) " ")))) + (unless (arrayp key) (setq key (format "%s" key))) + (let* ((fcn (lookup-key map key)) + (fcns (format "%s" fcn)) + (apr (or (fs-apropos-exact fcns) + "No doc available. "))) + (concat (format "%s -- %s" fcns apr)))) + +(defun fsi-lookup-key-gnus-group (&optional key &rest args) + (unless key (error "Syntax: , lkgg \"Key...\"")) + (require 'gnus-group) + (apply 'fs-lookup-key-from-map-internal gnus-group-mode-map key args)) + +(defun fsi-lookup-key-gnus-summary (&optional key &rest args) + (unless key (error "Syntax: , lkgg \"Key...\"")) + (require 'gnus) + (apply 'fs-lookup-key-from-map-internal gnus-summary-mode-map key args)) + +(defun fsi-lookup-key-message (&optional key &rest args) + (unless key (error "Syntax: , lkgg \"Key...\"")) + (require 'gnus) + (require 'message) + (apply + 'fs-lookup-key-from-map-internal gnus-message-mode-map key args)) + + + +(defun fsi-apropos-exact (str) + (unless (stringp str) (setq str (format "%s" str))) + (let* ((reg (concat "^" (regexp-quote str) "$")) + (apr (apropos reg)) + (asso (assoc* str apr + :test + (lambda (a b) + (string= (format "%s" a) (format "%s" b))))) + + (val (second asso))) + (if val (format "%s" val) + nil))) + +(defun fsi-describe-key-long (k &rest args) + (let ((f (apply 'fs-describe-key-briefly k args))) + (fs-describe-function-long f))) + +(defun fsi-describe-key-and-function (key &rest args) + "Describe the key KEY. +Optional argument ARGS . If the input arguments are not strings, it +kbds's them first... , so that , df C-x C-c works" + (when (and (null key) (null args)) + (setq key "")) + (unless (stringp key) + (setq key (read-kbd-macro + (mapconcat '(lambda (arg) (format "%s" arg)) + (cons key args) + " ")))) + (let ((b (key-binding key))) + (cond + ((symbolp b) + (or + (ignore-errors (fs-describe-function b)) + (format "Bound to: %s" b))) + (t + (format "Bound to: %s" b))))) + + + +(defun fsi-describe-function (&optional function nolimitp &rest fubar) + "Describes the FUNCTION named function. +Also tries an fs- prefix for the function.. +nolimitp has to be eq 'nolimit for the nolimit effect to take place.. +" + (unless function + (error + "Syntax: (describe-function 'name-of-function) or , df 'name")) + (let* ((f function) + g + ) + (when (stringp f) + (setq f (erbn-read f))) + (cond + ((symbolp f) + (progn + (setq + g + (cond + ((fboundp f) f) + (t (erbn-read (concat "fs-" (format "%s" f)))))) + (unless (fboundp g) + (setq g f)) + (let* ((def (symbol-function g))) + (ignore-errors + (if (equal 'autoload (car-safe def)) + (load (second def)))) + ;; this check does nothing now.. need ro + (if (equal nolimitp 'nolimit) + + ;;(let ((fs-limit-lines 8)) + ;;(fs-limit-lines (describe-function g))) + (describe-function g) + (describe-function g)) + + ))) ;; if list, DO NOT wanna eval it--> + (t + "NO function specified")))) + + +(defun fsi-where-is (function &rest args) + "Tells what key the function is on.. + +" + (let* ( + (str0 "") + (str1 "") + (str2 "") + (str3 "") + ) + (cond + ((stringp function) (setq function (erbn-read function))) + (t nil)) + (cond + ((null function) (format "Sorry, %s is not a symbol" function)) + ((symbolp function) + (unless (fboundp function) (setq str0 "Either unbound or.. ")) + (setq str2 + (with-temp-buffer + (where-is function t) + (erbutils-buffer-string))) + (concat str0 str1 str2 str3)) + (t (format "Looks like %s is not a symbol" function))))) + +(defun fsi-describe-function-long (function &rest fubar) + "Similar to describe-function, but does not limit the strings... +Use with caution only in privmsgs please, for may produce long outputs. " + (fs-describe-function function 'nolimit)) + + +(defun fsi-describe-variable-long (variable &rest fubar ) + "Similar to describe-variable, but does not limit strings.." + (fs-describe-variable variable 'nolimit)) + +(defun fsi-describe-variable (&optional variable &rest ignore) + "Describes a VARIABLE.." + (unless variable (error "Syntax: , dv 'variable")) + (let* ((f variable)) + (if (stringp f) + (setq f (erbn-read f))) + (cond + ((symbolp f) + (erbutils-describe-variable f)) + + ;; if list, DO NOT wanna eval it--> + (t + "NO variable specified")))) + +(defalias 'fsi-parse 'fs-lispify) +(defalias 'fsi-parse-english 'fs-lispify) + +(defun fsi-require (feature &rest fubar) + "Make the bot require the feature FEATURE. +So that the command df +or dv works fine..Actually, df knows how to load unloaded features +automatically." + (if (stringp feature) + (setq feature (fsi-read feature))) + (when (or (string-match "/" (format "%s" feature)) + (string-match "\\\\" (format "%s" feature))) + (error "Your safety is VERY important to us, so we avoid loading features containing slashes.")) + (cond + ((symbolp feature) (format "%s" (require feature))) + (t "no feature specified"))) + + +(defvar fs-found-query-p nil + "internal.. should be normally set to nil. +When non nil, means that the msg was not meant to the bot, so the +reply please be abbreviated. ") + +(defvar fs-internal-addressedatlast nil + "internal.. normally nil") + +(defvar fs-internal-original-message "" + "internal") + +(defvar fs-internal-message-sans-bot-name "" + "internal") + +(defvar fs-internal-max-lisp-p nil) + + +(defun fsi-respond-to-query-p (msg) + ;; if it is of the form resolve? the user KNOWS what resolve or + ;; kensanata is, and is not asking for information. So, please don't + ;; respond in such a case. + (not + (member msg (mapcar 'first (fs-channel-members-all))))) + +(defcustom fs-internal-parse-preprocess-message-remove-end-chars + ;; remove trailing ^A's that occur on action strings... + (list 1) + "") + +(defcustom fs-web-page-title-p nil + "Change it to t to enable the erbot to look up the title of urls +posted in a channel. When string, will be matched against target.") + +(defcustom fsi-m8b-p nil + "Change it to t for the magic 8-ball... define m8b then of +course... +When string, will be matched against target. " +) + +(defun fsi-parse-preprocess-message (msg) + (let ((len (length msg))) + (when (and + (> len 0) + (member (aref msg (- len 1)) + fs-internal-parse-preprocess-message-remove-end-chars) + (setq msg (subseq msg 0 -1))))) + msg) + +(defvar erbn-dead-check-p nil + "If non-nil, we will not reply to people who have shot themselves +using mark-dead or russian roulette. These people need to be revived +first. Of course, like any magic, revival sometimes works, and +sometimes doesn't.") + +(defun fsi-lispify (&optional msg proc nick tgt localp + userinfo &rest foo) + "Parse the english MSG into a lisp command. + +If it is an 'is', it should always be the second word .. +viz: we had better use hyphens in the first word.. +MSG is a string.. +Is the main function.. but also available to the user as a command... + +NB: The end-result is always an expression.. and NOT a strign.. + + +Just once in a blue moon, this will, at random, even parse messages +not addressed to it... + +Finally, wanna parse messages whose last item contains erbot.. +Optional argument PROC . +Optional argument NICK . +Optional argument TGT . +Optional argument FOO . + +We will also bind a number of variables, as appropriate, for example, +fs-msg*, fs-lispargs, fs-lispa , fs-lispb... so that these vars can be used +anywhere in the code, or the user-defined parts of the code... + +In the grand scheme of things, these bindings should turn out to be +local, because the parent function calling this function should have +'letted these variables. + +" + ;;(when (stringp msg) + ;; (setq msg (split-string msg))) + ;msg + ;proc + ;nick + ;tgtg + ;foo + (setq fs-internal-original-message msg) + (setq msg (fs-parse-preprocess-message msg)) + (setq fs-msg msg) + (setq fs-msgsansbot msg) + (let* + ( + + + (msg (fs-parse-preprocess-message msg)) + (origmsg msg) + ;;(fs-internal-message-sans-bot-name fs-internal-message-sans-bot-name) + (foundquery nil) + (foundquerydouble nil) + (foundkarma nil) + ;; if t, means either our name was at last, or eevn if at + ;; first, they weren't really addressing us.. + ;;(addressedatlast nil) + (leave-alone-p t) + ;;(fs-nick nick) + bluemoon + ) + (unless (stringp origmsg) + (setq origmsg (format "%s" origmsg))) + (unless msg + (error "Format: %s (parse \"your-english-message\")" erbn-char)) + (unless (stringp msg) + (setq msg (format "%s" msg))) + ;; remove leading spaces.. + (while + (and (> (length msg) 0) + (equal (aref msg + 0) 32)) + (setq msg (substring msg 1))) + + ;; remove trailing spaces.. + (while + (and (> (length msg) 0) + (equal (aref msg (- (length msg) 1)) 32)) + (setq msg (substring msg 0 (- (length msg) 1)))) + + (when (and tgt proc) + (set-buffer (erc-get-buffer tgt proc))) + + (when + (and (stringp msg) + (string-match "\\(++\\|--\\)$" msg) + (<= (length (split-string msg)) 2)) + (setq foundkarma t)) + ;; 2003-11-14 T15:36:38-0500 (Friday) D. Goel + ;; requested by elf: + ;; if double ??, then make it a call to m8b + (when (and + fsi-m8b-p + (if (stringp fsi-m8b-p) + (and (stringp tgt) (string-match fsi-m8b-p tgt)) + t)) + (let (len) + (when (and (stringp msg) + (progn + (setq len (length msg)) t) + (> len 1) + (string= "??" + (substring msg (- len 2) len)) + ;;(or + ;;(string-match + ;;erbot-nick msg) + ;;(string-match (concat "^" erbn-char) msg) + ;;(string-match erbn-char-double msg)) + ) + (setq foundquerydouble t) + (setq msg (concat erbn-char " (m8b)"))))) + + (when (and (stringp msg) + (> (length msg) 0) + ;; ignore trailing ? + (equal (aref msg (- (length msg) 1)) 63)) + (progn + (setq foundquery t) + (setq msg (substring msg 0 (- (length msg) 1))))) + + (setq leave-alone-p t) + (setq bluemoon + (or + ;; responding to a general list conversation.. + (fs-blue-moon) + ;; responding in general.. + (and (equal nick tgt) + (or + (stringp nick) + ;; parse commands --> + (null nick) + ) + ))) + (unless (stringp msg) + (setq msg "")) + + + ;; convert midsentence ,, to parsable sentence. + (let (pos) + (when + (and (not (equal 0 + (string-match erbn-char msg))) + (not + (let ((nickpos (string-match erbot-nick msg))) + (and nickpos + (< nickpos 3)))) + ;; part of and + (setq pos + (string-match erbn-char-double msg))) + (setq msg (substring msg (+ pos 1))) + (when (setq pos (string-match erbn-char-double msg)) + (setq msg (substring msg 0 pos))))) + + ; deal with the leading , or ,, + (when (equal 0 + (string-match erbn-char msg)) + (let ((restmsg (substring msg 1))) + (when (equal 0 (string-match "," restmsg)) + (setq restmsg (substring restmsg 1))) + (setq msg (concat erbot-nick ": " restmsg)))) + + + ;; now we split strings.. + (setq msg (split-string msg)) + (setq fs-msglist msg) + (setq fs-msglistsansbot msg) + (cond + ( (and (first msg) + (let ((pos + (string-match erbot-nick (first msg)))) + (and pos (< pos 1)))) + ;;(or + ;;(erbutils-string= (first msg) erbot-nick) + ;;(erbutils-string= (first msg) (concat erbot-nick ",")) + ;(erbutils-string= (first msg) (concat erbot-nick + ;":"))) + (progn + (unless + (or + (string-match (concat erbot-nick ":") (first msg)) + (string-match (concat erbot-nick ",") (first msg)) + (null (second msg)) + (string-match "^," (second msg)) + (string-match "^:" (second msg))) + (setq fs-internal-addressedatlast t)) + (when (> (length msg) 1) + (setq msg (cdr msg))) + (setq leave-alone-p nil))) + + + ;; if it is a short sentence ending in fsbot.. + ((and (first (last msg)) (string-match erbot-nick (first (last + msg))) + (< (length msg) 5)) + ;; don't want this any more.. since no sense in removing the + ;; last term. Example: Want: what is erbot? to stay that way. + ;;(progn + ;;(setq msg (reverse (cdr (reverse msg))))) + (when leave-alone-p + (setq fs-internal-addressedatlast t)) + (setq leave-alone-p nil)) + + + + ;; this might be dangerous if nick is a small word like "apt".. + ;; this also means :( thagt erbot will intervene when users are + ;; talking about her, but not TO her.. + ;; nah, leave this one out.. + ;;((member erbot-nick msg) + ;; (setq leave-alone-p nil)) + + (bluemoon + (setq leave-alone-p nil))) + + (setq fs-internal-message-sans-bot-name + (mapconcat 'identity msg " ")) + + (when (and + foundquery + ;; if tgt is nil, we are being asked to parse + ;; something.. so cool + tgt + (string-match fs-internal-query-target-regexp tgt)) + ;; if this condition causes the thing to be triggerred, then + ;; setq temporarily, a global variable... so responses are muted + ;; in general.. + (let ((goonp nil) (newmsg msg)) + (cond + ((equal (length msg) 1) + (setq goonp + ;; setq to t only if the content of the msg represents + ;; something the user might be interested in. + (fs-respond-to-query-p (first msg)) + + )) + (t + (setq goonp t) + ;; convert what's to what is + (when (stringp (first newmsg)) + (setq newmsg + (append + (split-string (first newmsg) "'") + (cdr newmsg)))) + (if (and goonp + (member + (erbutils-downcase (first newmsg)) + fs-internal-questions)) + (setq newmsg (cdr newmsg)) + (setq goonp nil)) + (if (and goonp + (member + (erbutils-downcase (first newmsg)) + '("s" "is" "are" + ;;"am" + ))) + (setq newmsg (cdr newmsg)) + (setq goonp nil)) + + ;; remove articles + (if (and goonp + (member + (erbutils-downcase (first newmsg)) + fs-internal-articles)) + (setq newmsg (cdr newmsg))) + (unless (equal (length newmsg) 1) + (setq goonp nil)))) + (when goonp + (when leave-alone-p (setq fs-found-query-p t)) + (setq leave-alone-p nil) + (setq msg (list "(" "describe" + (format "%S" (first newmsg)) + "0" ")" + )) + )) + ) + + ;; Sat Jan 8 12:40:46 EST 2005 (petekaz) + ;; We need to make sure this is the last thing we check + ;; because we don't want to hijack another valid command + ;; with our parsing. I.e. if a user adds a term with an + ;; url included in its note, we don't process that. + (when (and leave-alone-p + fs-web-page-title-p + (if (stringp fs-web-page-title-p) + (and (stringp tgt) + (string-match fs-web-page-title-p tgt)) + t)) + (let* ((case-fold-search t) + (url (some 'erbutils-html-url-p msg))) + (when url + (setq leave-alone-p nil) + (setq msg (list "(" "web-page-title" (format "%S" url) ")"))))) + + ;; (cond + ;; ((equal (length msg) 1) + ;; (when leave-alone-p + ;; (setq fs-found-query-p t)) + ;; (setq msg (cons "describe" msg)) + ;; (setq leave-alone-p nil)) + ;; ((and + ;; (equal (length msg) 3) + ;; (member (erbutils-downcase (first msg)) + ;; fs-internal-questions) + ;; (member (erbutils-downcase (second msg)) + ;; '("is" "are"))) + ;; (setq msg (cons "describe" (cddr msg))) + ;; (when leave-alone-p + ;; (setq fs-found-query-p t)) + ;; (setq leave-alone-p nil)) + ;; ((and + ;; (equal (length msg) 3) + ;; (member (erbutils-downcase (first msg)) + ;; fs-internal-questions) + ;; (member (erbutils-downcase (second msg)) + ;; '("is" "are"))) + ;; (setq msg (cons "describe" (cddr msg))) + ;; (when leave-alone-p + ;; (setq fs-found-query-p t)) + ;; (setq leave-alone-p nil)) + + + ;;)) + + ;; finally, ignore bots/fools.. + (let ((ui (format "%S" userinfo))) + (when + (or + (and erbot-use-whitelist + (stringp nick) + (not (member-if + (lambda (arg) + (string-match arg nick)) + erbot-whitelist-nicks))) + (and (stringp nick) + (member-if + (lambda (arg) + (string-match arg nick)) + erbot-ignore-nicks)) + + (some + 'identity + (mapcar + (lambda (ignorethis) + (string-match ignorethis + ui)) + erbot-ignore-userinfos))) + (setq leave-alone-p t))) + + + (setq fs-msglistsansbot msg) +;;;==================================================== + ;; now do the work.. + (if leave-alone-p + ;; not addressed to us, so return nil and be done.. + nil + ;; else.. viz: go on... + (progn + (erblog-log-target tgt) + (let* (;(found nil) + (newmsglist nil) + (msgstr (erbutils-stringify msg)) + ;(newstrmsg nil) + (lispmsg (erbn-read msgstr) + )) + + + ;; do a dead check + (when erbn-dead-check-p (and (not foundquery) + (erbn-dead-check))) + + + (setq + newmsglist + (cond + + ;; are in a read mode.. + (erbn-read-mode + (fs-botread-feed-internal msgstr)) + + + + ;; look for a valid lisp form, then it just needs to be sandboxed + ((or + (consp lispmsg) + (and fs-internal-max-lisp-p (numberp lispmsg)) + (and fs-internal-max-lisp-p (stringp lispmsg)) + (and (symbolp lispmsg) + (let ((newsym + ;;(intern (format "fs-%S" lispmsg)) + (erblisp-sandbox lispmsg))) + (or + (equal 0 + (string-match "fs-" + (format "%S" lispmsg))) + (and + (boundp newsym) + (not (fboundp newsym))))))) + ;;(erblisp-sandbox-fuzzy lispmsg) + (erblisp-sandbox lispmsg) + ) + + + (fs-dunnet-mode + (fs-dunnet-command msgstr)) + + + ;; call to arbitrary function without parens + ;; prefer this before is etc. so that "how is it going" + ;; resolves properly.. + ((or + ;; fboundp ==> allowing macros as well.. + ;;(fboundp (intern (concat "fs-" (first msg)))) + (fboundp (erblisp-sandbox (intern (first msg)))) + ;;(functionp (intern (concat "fs-" (first msg)))) + (equal 0 (string-match "fs-" (first msg)))) + ;; this works great, except that we would like to quote the + ;; internals... because that is the most commonly used + ;; characteristic.. + ;;`("(" ,@msg ")") + (erblisp-sandbox-full + ;;`( ,(intern (first msg)) ,@(erbutils-quote-list + ;;(mapcar 'intern (cdr msg)))) + ;;(read (cons (intern (first msg)) + ;; (read (list (erbutils-stringify (cdr msg)))))) + (fsi-read (concat "( "(erbutils-stringify msg) " )")))) + + ((equal 0 + (string-match "\\(s\\|r\\)/" (first msg))) + (fs-replace-string-from-english-internal + msg)) + ((equal 0 + (string-match "[0-9]+->" (first msg))) + (fs-rearrange-from-english-internal msg)) + ( + (and + + + (or (erbutils-string= (second msg) "is" t) + (erbutils-string= (second msg) "are" t) + ;;(erbutils-string= (second msg) "am" t) + + ) + (member (erbutils-downcase (first msg)) + fs-internal-questions-all + )) + + + ;;`(apply 'fs-describe ',(cddr msg)) + `(funcall 'fs-describe + ',(third msg) + nil nil nil ,"origmsg" + ) + + ) + + ;; some english constructs first... + + ;; search removed---because: is a functionp... + ;;((erbutils-string= (first msg) "search") + ;; (setq newmsglist + ;; `("(" "search" ,@(cdr msg) ")"))) + ((and + + ;; do not want to take such cases, 100% are annoying + ;; false matches. + (not fs-internal-addressedatlast) + + (or + (erbutils-string= (second msg) "is" t) + (erbutils-string= (second msg) "are" t)) + ;;(erbutils-string= (third msg) "also" t) + (member-ignore-case (third msg) + (list "also" "also,")) + ) + (erblisp-sandbox-fuzzy + `( + fs-set-also ,(first msg) + ;;,@(erbutils-quote-list (cdddr msg)) + ,(erbutils-stringify (cdddr msg)) + ))) + ((and (erbutils-string= (first msg) "tell") + (erbutils-string= (third msg) "about")) + `(fs-tell-to + ,(erbutils-stringify (cdddr msg)) + ,(format "%s" + (second + msg)) + )) + + ( + (and + ;; do not want to take such cases, 100% are annoying + ;; false matches. + (not fs-internal-addressedatlast) + + (or (erbutils-string= (second msg) "is") + (erbutils-string= (second msg) "are"))) + (erblisp-sandbox-fuzzy + `(fs-set-term + ;; a string.. so we are safe.. + ,(first msg) + ;; another string... so we are safe.. + ,(erbutils-stringify (cddr msg))))) + + + + ((and + (not fs-internal-addressedatlast) + (or + (erbutils-string= (first msg) "no" t) + (erbutils-string= (first msg) "no," t)) + (or + (erbutils-string= (third msg) "is") + (erbutils-string= (third msg) "are") + ) + + ) + (erblisp-sandbox-fuzzy + `(fs-set-force ,(second msg) + ;;,@(erbutils-quote-list (cdddr msg)))) + ,(erbutils-stringify (cdddr msg)))) + ) + + ((let ((foo (first msg))) + (and + (not fs-internal-addressedatlast) + (<= (length msg) 2) + (string-match "\\(++\\|--\\)$" foo) + (not (fs-notes foo + )))) + (let* ((foo (first msg)) + (sec (second msg)) + (bar (substring foo 0 -2)) + (plusp (string-match "++$" foo))) + (if plusp + `(fs-karma-increase ,bar ,sec) + `(fs-karma-decrease ,bar ,sec)))) + ((or fs-internal-addressedatlast + (and fs-internal-botito-mode (> (length msg) 3))) + `(funcall 'fs-english-only ,origmsg ,fs-internal-addressedatlast)) + + (t + ;;`(apply 'fs-describe ',msg) + + ;;`(funcall 'fs-describe ',(first msg) + ;; ',(second msg) + ;; ',(third msg) + ;; nil + ;; ,origmsg + ;; ) + `(funcall 'fs-describe-from-english + ,origmsg + ',msg) + + + + + + ) + )) + ;; this should be "%S" and not "%s" the lattwer will convert + ;; (dk "k") into (dk k) + (format "%S" newmsglist)))))) + + +(defun fsi-describe-from-english (&optional origmsg msg) + "Call fs-describe appropriately. +ORIGMSG is in english. +MSG is a list.. + +Plan + +For multiple words, commence a search foo.*bar.*baz IF WE KNOW THAT +SEARCH or SEARCH--WIDE WILL SUCCEED, which will then, of course, go to +search-wide if it fails. + +Else, of course, do the usual thing: viz. call describe... + + +" + (unless (and origmsg msg) + (error "Are you a user trying to call this function? Perhaps just use +'describe instead :). Anyway, this function needs 2 arguments. ")) + (let ((len (length msg)) + mainterm firstterm remainder N M prestring expr tmpv + (searchp nil) + (multitermp nil) + (fs-internal-google-level fs-internal-google-level) + ) + (cond + ((<= len 1) + (if (fsi-notes (first msg)) + (fs-describe + (first msg) + nil nil nil origmsg) + (fs-describe + (fsi-generalize-search-term (first msg)) + nil nil nil origmsg))) + (t + (setq mainterm (first msg)) + (setq firstterm mainterm) + (setq remainder (cdr msg)) + (while + (and + remainder + (progn + (setq tmpv (first remainder)) + (and (not (integerp tmpv)) + (progn + (unless (stringp tmpv) (setq tmpv (format "%s" + tmpv))) + (not (integerp (ignore-errors (erbn-read tmpv)))))))) + ;;(setq searchp t) + (setq mainterm + (concat mainterm ".*" tmpv)) + (setq multitermp t) + (pop remainder)) + ;; why is this true only for multitermp??? + ;; Ah, because we say: if you end up searching and there are + ;; multiple terms, you might as well include a result from + ;; google among the search results. + (when multitermp + (setq fs-internal-google-level (+ fs-internal-google-level 25))) + + (when (and multitermp + ;; viz. if it will work + (second (fs-search-basic + mainterm nil nil 'describe))) + (setq searchp t)) + + + (if searchp + (fs-search + mainterm (first remainder) (second remainder) + "Try: " origmsg) + (fs-describe + (fsi-generalize-search-term firstterm) (first remainder) (second remainder) + (third remainder) origmsg)))))) + + +(defun fsi-generalize-search-term (term) + (erbutils-replace-string-in-string "-" "[ -]*" term)) + +;; (defalias 'fs-hello 'fs-hi) +;; (defalias 'fs-hey 'fs-hi) + +(defalias 'fs-thanks 'fs-thank) +(defun fs-thank (&rest args) + (let ((aa (erbutils-random '("no problem" "you are welcome" + + )))) + (eval + (erbutils-random + '( + (concat aa erbn-char " " fs-nick) + (concat fs-nick erbn-char " " aa)))))) + +(defun fs-greet (&optional nick &rest args) + ". + Optional argument NICK . + Optional argument ARGS ." + (if (and nick (not (string-match erbot-nick (format "%s" nick)))) + (format "hi %s !!" + (let ((foo (split-string (format "%s" nick ) + "[^a-bA-Z0-0]"))) + (or (first foo) nick)) + ) + (fs-describe "hi"))) + +;;; (defun fs-ni (&optional nick &rest args) +;;; ". +;;; Optional argument NICK . +;;; Optional argument ARGS ." +;;; (if (and nick (not (string-match erbot-nick (format "%s" nick)))) +;;; (format "NI %s !!" +;;; (let ((foo (split-string (format "%s" nick ) +;;; "[^a-bA-Z0-0]"))) +;;; (or (first foo) nick)) +;;; ) +;;; (fs-describe "hi"))) + +;;; (defun fs-greet (&optional nick &rest foo) +;;; "Nada..just a call to `fs-hi'. +;;; Optional argument NICK ." +;;; (fs-hi nick)) + +(defun fs-kiss (&optional nick &rest foo) + "Nada. +Optional argument NICK ." + (setq nick (format "%s" (or nick "itself"))) + (cond + ((member nick (list erbot-nick "yourself" "self")) + (eval + (erbutils-random + '("I'd rather kiss you" + "Kiss myself? Why?")))) + (t + (eval + (erbutils-random + '((format "/me kisses %s" nick) + (format "/me gives %s a big smooch" nick) + (format "/me runs in the other direction, shouting NEVER!!"))))))) + +(defun fs-hug (&optional nick) + (unless nick (setq nick "itself")) + (setq nick (format "%s" nick)) + (cond + ((member nick (list erbot-nick "yourself" "self")) + (eval + (erbutils-random + '("But i do that all the time. " + "Hug myself? Why?")))) + (t + (eval + (erbutils-random + '((format "/me gives %s a tight hug" nick) + (format "/me clings to %s" nick) + (format "/me runs in the other direction, shouting NEVER!!") + (format "/me grabs hold of %s and vows to never let go" nick) + (format "/me grabs hold of %s and vows to never let go" nick))))))) + + + + +(defun fs-love (&optional nick &rest bar) + ". +Optional argument NICK ." + + + (let ((nonep nil)) + (unless nick (setq nick "someone sexy") (setq nonep t)) + (setq nick (format "%s" nick)) + (cond + ((and (not nonep) (member nick (list "you" "me"))) + (erbutils-random + '("Thank you. Enjoyed that. " + "Thanks, I love you even more now. " + "Wouldn't that amount to interspecies sex? " + "Sex between humans and machines is not known to produce +anything useful. "))) + ((member nick + (list erbot-nick "yourself" "self")) + (erbutils-random + '("This is a complicated operation. Can't (yet) perform operation on self. " + "Please train me on this maneuver. "))) + (t + (eval + (erbutils-random + '((format "/me goes with %s to a private place..." nick) + (format "/me looks at %s and yells \"NEVER!\"" nick) + (format "/me looks at %s lustfully" nick)))))))) + +(defalias 'fs-fuck 'fs-love) + +(defvar fs-flame-target nil) + + + +(defun fsi-eval-or-say (str &optional fs-victim) + (let ((aa (when (stringp str) + (ignore-errors (erbn-read str))))) + (cond + ((consp aa) + (unless fs-victim (setq fs-victim fs-nick)) + (fsi-eval aa)) + (fs-victim + (format "%s: %s" fs-victim str)) + (t + (format "%s" str))))) + + + + + + +(defun fs-flame (&rest args) + "" + (let ((flames (ignore-errors (fs-notes "flames"))) + fs-flame-target num) + (cond ((and (numberp (cadr args)) + (not (cddr args))) + (setq fs-flame-target (car args) + num (cadr args))) + ((consp (cdr args)) + (setq fs-flame-target (mapconcat (lambda (arg) + (format "%s" arg)) + args " "))) + ((car args) + (setq fs-flame-target (format "%s" (car args)))) + (t (setq fs-flame-target (format "%s" erbot-end-user-nick)))) + (if (string= (format "%s" fs-flame-target) "me") + (setq fs-flame-target erbot-end-user-nick)) + ;; Check for flame.el support + (cond + ((and (consp flames) (> (length flames) 0)) + (fsi-eval-or-say + (if num + (nth num flames) + (fs-random-choose flames)) + fs-flame-target)) + (t (fs-flame-mild fs-flame-target))))) + + + + + + +(defun fs-flame-mild (&rest args) + "Doesn't really flame right now.. +Optional argument ARGS ." + (let ((target + (if (first args) + (format "%s" (first args)) + erbot-end-user-nick))) + (if (string= (format "%s" target) "me") + (setq target erbot-end-user-nick)) + ;; Check for flame.el support + (if (featurep 'flame) + (eval + (erbutils-random + '( + (format (erbutils-random erbdata-flames) + target target target) + (concat target ": " (flame-string))) + '(1 30))) + (format (erbutils-random erbdata-flames) + target target target)))) + +;; remove kill +;(defun fs-kill (&optional nick &rest nicks) +; ". +;Optional argument NICK . +;Optional argument NICKS ." +; (format "/me , trained by apt, chops %s into half with an AOL CD" nick));; + +;(defun fs-quote (&rest args) +; (quote args)) + +(defun fs-bye (&rest msg) + "" + (erbutils-random + '("Okay, see you later" + "later" + "Bye then" + "Take care now" + "Happy hacking"))) + + +;;; (defun fs-help (&rest args) +;;; "Introductiry help. " +;;; (let ((fir (first args))) +;;; (if (stringp fir) +;;; (setq fir (intern fir))) +;;; (unless (symbolp fir) (setq fir 'dummy-no-help)) +;;; (if (null fir) +;;; "I try to understand English, though lisp is the real way to go. Here are some interesting topics: quickstart, example, future-features, help about, help commands, help data, help english, help name, help homepage, +;;; help owner, help specs, help parse \(for lisp stuff\), describe help, describe suggest , help parse-web , help functionality +;;; " +;;; (cond +;;; ((equal fir 'about) +;;; (fs-help 'name)) +;;; ((equal fir 'owner) +;;; (fs-help 'data)) + +;;; ((equal fir 'name) +;;; "I am erbot: The Free Software Bot, using ERC in emacs.. +;;; I can also be addressed by , .. yeah, a comma .. +;;; The real way to address me is erbot: (lisp-command..) .. all this +;;; english is just candy-interface... ") +;;; ((equal fir 'specs) +;;; "/sv") +;;; ((equal fir 'address) +;;; (fs-help 'name)) +;;; ((equal fir 'homepage) +;;; "homepage: http://deego.gnufans.org/~deego/pub/emacspub/lisp-mine/erbot/ +;;; Data: http://deego.gnufans.org/~erbot/data/ +;;; Suggestions to D. Goel: deego@gnufans.org") +;;; ((equal fir 'code) +;;; (fs-help 'homepage)) +;;; ((equal fir 'data) +;;; (fs-help 'homepage)) +;;; ((equal fir 'suggestions) +;;; "Add stuff to keyword suggest, also see help homepage") +;;; ((equal fir 'english) +;;; "Some common syntaxes: , foo is bar; , foo is also bar; +;;; , no foo is bar; , forget foo ; , flame nick; , doctor ; etc.") +;;; ((equal fir 'parse) +;;; "Try the command , parse \", \" to see the +;;; lisp renditions of your english messages") +;;; ((equal fir 'parse-web) +;;; "Ask me to parse a (please: USEFUL PAGE) webpage and a label +;;; and i will do so in my free time and gain knowledege... under +;;; construction.. ") +;;; ((equal fir 'functionality) +;;; "Bulk of the info is stored as assoc-list data (see +;;; homepage). You generally type foo and the corresp. data is +;;; returned.. you can also (search ... )") +;;; ((equal fir 'commands) +;;; " You can use both lisp and english to communicate.. +;;; Type , (commands) to get a list of commands..") + +;;; ((equal fir 'suggest) +;;; "Add your suggestions to the field \"suggestions\", or contact the author") + + +;;; (t "select an option or Type , help for a list of options.." +;;; ))))) + + + + + + +(defun fsi-command-list (&rest foo) + "Used by erbc.el and by erbot-install.. " + (erbn-command-list-from-prefix "fs-")) + + +(defun fsi-command-list-readonly (&rest foo) + "Used by erbc.el.. and erbot-install " + (erbn-command-list-from-prefix "fsi-")) + + +(defun erbn-command-list-from-prefix (prefix &rest foo) + "Used by erbc.el.. should return a string.." + (let* + ((longnames (erbutils-matching-functions prefix)) + (shortnames + (with-temp-buffer + (insert (format "%s" longnames)) + (goto-char (point-min)) + (replace-string prefix "") + (text-mode) + (fill-paragraph 1) + (erbn-read (buffer-substring (point-min) (point-max)))))) + shortnames)) + +(defun fsi-commands (&optional regexp N M &rest foo) + "List available commands matching REGEXP. If N and M provided, list +matches starting at N and ending at M. " + (if (and regexp (not (stringp regexp))) + (setq regexp (format "%s" regexp))) + (let* ((all-commands (fs-command-list)) + (pruned-commands + (if (stringp regexp) + (mapcon + '(lambda (arg) + (if (string-match regexp (format "%s" (car arg))) + (list (car arg)) nil)) + all-commands) + all-commands)) + (len (length pruned-commands)) + final-commands + (str0 "") + (str1 "") + (str2 "") + (str3 "") + (str4 "")) + (setq str0 (format "%s matches. " len)) + (unless (or (< len 20) (and (integerp N) (> N 0))) + (setq str1 + "Perhaps type , df commands for general syntax. ")) + (unless (integerp N) (setq N 0)) + (unless (integerp M) (setq M len)) + (if (= M N) (setq M (+ N 1))) + (when (> M len) (setq M len)) + (if (> N 0) (setq str2 (format "Matches starting at %s -->" N))) + (setq final-commands (subseq pruned-commands N M)) + (setq str3 + (format "%s" final-commands)) + (concat str0 str1 str2 str3))) + + + +(defun fsi-describe-commands (&rest foo) + "Just a help command. Describes how to run commands. " + (concat + "If you use plain english, it simply gets transformed to lisp +commands.. main/default command: (describe).. to see transformation, +use (parse). See also fs-commands. + +PS: no naughty ideas please :)--- the commands are sandboxed via an +fs- prefix.. + +Future commands: info-search, hurd-info-search etc. etc. +" +)) + + +(defalias 'fsi-d 'fs-describe) + + +(defun fsi-search (&optional regexp N M prestring expr &rest rest) + "Search for the REGEXP from among all the terms (and their +descriptions). See also fs-search-wide. +EXPR (optional) is the full initial expression.. " + (unless regexp + (error "Syntax: , s REGEXP &optional N M")) + (let* ((len-results (apply 'fs-search-basic regexp N M nil + rest)) + (len (first len-results)) + (results (second len-results)) + (str0 " ") + (str1 "") + (str2 "") + (str3 "") + (str4 "") + (str5 "") + ) + (when (and (> len 100) (not prestring)) + (setq str0 (format " Use , s REGEXP N M to limit results. "))) + (when (and (< len 5) (not prestring)) + (setq str0 (format " Perhaps try also , sw %s . " regexp))) + (unless prestring (setq str1 (format "%s match(es). " len))) + (if (and (integerp N) (> N 0) (not prestring)) + (setq str2 (format "Matches starting at %s\n" N))) + (unless prestring (setq str3 "--> ")) + (setq str4 + (mapconcat 'identity + results " " + ) + + ) + (when (and (> fs-internal-google-level 80) (> len 1)) + (setq str5 + (let ((foo (fs-google-lucky-raw + fs-internal-message-sans-bot-name))) + (if foo (concat " " foo) str5)))) + (cond + ((and prestring (= len 1)) + (fs-describe (first results))) + ((and (> len 0) + (or + (not prestring) + (< len fs-internal-english-max-matches))) + (unless (stringp prestring) + (setq prestring "")) + (concat prestring str0 str1 str2 str3 str4 str5)) + (t (apply 'fs-search-wide regexp N M + "Try: " + (or expr fs-internal-original-message) + rest))))) + + +(defun fsi-search-wide-sensitive (&rest args) + "Like fs-search-wide, but case-sensitive" + (let ((case-fold-search nil) + (bbdb-case-fold-search nil)) + (apply 'fs-search-wide args))) + + + + + + + + +(defun fsi-search-wide (&optional regexp N M prestring expr &rest rest) + "Search for the REGEXP from among all the terms (and their +descriptions). See also fs-search-wide. +EXPR is the full initial expression, well, mostly.. +" + (let* ((len-results (apply 'fs-search-basic regexp N M 'describe + rest)) + (len (first len-results)) + (results (second len-results)) + (str0 "") + (str1 "") + (str2 "") + (str3 "") + (str4 "") + (str5 "") + ) + (when (and (> len fs-internal-english-max-matches) (not prestring)) + (setq str0 (format "Perhaps try also , s %s . " regexp))) + (unless prestring (setq str1 (format "%s match(es). " len))) + (if (and (integerp N) (> N 0) (not prestring)) + (setq str2 (format "Matches starting at %s\n" N))) + (unless prestring (setq str3 "--> ")) + (setq str4 + ;;(format "%s" results) + (mapconcat 'identity results " ") + ) + (when (and (> fs-internal-google-level 80) (> len 1)) + (setq str5 + (let ((foo (apply 'fs-google-lucky-raw + fs-internal-message-sans-bot-name + (fs-get-google-defaults) + ))) + + (if foo (concat " " foo) str5)))) + + ;; why does this not work as expeecteD? adding a nil for now: + (when (and prestring (>= len fs-internal-english-max-matches)) + (setq fsi-prestring + (concat fsi-prestring + "[Too many DB matches] "))) + (cond + ((and prestring (= len 1)) + (fs-describe (first results))) + ((and (> len 0) + (or (not prestring) + (< len fs-internal-english-max-matches))) + (unless (stringp prestring) + (setq prestring "")) + (concat prestring str0 str1 str2 str3 str4 str5)) + (t + (fs-english-only (or expr fs-internal-original-message) + nil + ))))) + + +(defcustom erbn-greeting-string + "Greetings and Salutations from %s" "") + + +(defun fsi-english-only (expr &optional addressedatlast nogoogle) + "when addressedatlast is t, means that fsbot/botito was triggered because +it was addressed at last. " + ;; expr should already be a string ...but just in case: + (unless expr (setq expr fs-internal-original-message)) + (setq expr (erbutils-downcase (erbutils-stringify expr + + ))) + (let ((exprlist (split-string expr + ;;"[ \f\t\n\r\v]+" + "[^a-zA-Z0-9]" + )) + (gotit nil) + ans len + ) + (setq exprlist (remove "" exprlist)) + (setq len (length exprlist)) + (cond + ((or + + (and (= len 1) + (string-match erbot-nick (first exprlist)))) + (setq gotit t + ans + (format erbn-greeting-string + erbot-nick))) + ((or + (member "hi" exprlist) + (member "hello" exprlist) + (member "yo" exprlist)) + (setq + gotit + t + ans + (concat + (erbutils-random + '("hi " "hello " "hey " "hei ")) + (erbutils-random + '("sexy! " "!!" "there" ""))))) + + ((member "bye" exprlist) + (setq gotit t + ans + (erbutils-random + '("Later" "See ya" "Bye then" "Bye")))) + ((or + (member "welcome" exprlist) + (member "weclome" exprlist)) + (setq gotit t + ans + (erbutils-random + '(":-)" "How goes?" "Hello!" + "Greetings!" + "How is it going?" + "This is my favorite channel!" + "I love this place. " + "Thanks. I love it here.")))) + + ((or + (member "tnx" exprlist) + (member "tnks" exprlist) + (member "thanks" exprlist) + (member "thanku" exprlist) + (member "thankyou" exprlist) + (and (string-match "thank" expr) + (or + (string-match "you" expr) + (string-match erbot-nick expr)) + (string-match "thank you" expr))) + (setq gotit t + ans + (erbutils-random + '("No problem" "Welcome!" "You're welcome" + "no problemo" + "Sure!" + "(:" + "Cool." + + )))) + + ((or (member "thx" exprlist) + (member "thankx" exprlist) + (member "thanx" exprlist) + ) + (setq gotit t + ans + (erbutils-random + '("np" "urw" "hehe, np" )))) + ((or (string-match "wassup" expr) + (string-match "what's up" expr)) + (setq gotit t + ans + (concat + (erbutils-random + '("Nothing much. " "Just, you know. " + "Just the usual..")) + (erbutils-random + '("And you? " "How about you? " + "How goes with you? " + "What have you been up to?"))))) + ( + (or + (string-match "love" expr) + (string-match "like" expr)) + (setq gotit t + ans + (format "%s loves you!" erbot-nick))) + ( + (or + (string-match "hate" expr) + (string-match "dislike" expr) + (string-match "don't like" expr)) + (setq gotit t + ans + (format "%s only has love for you!" erbot-nick))) + + ((string-match "help" expr) + (setq gotit t + ans (format "Type , help"))) + ((or (member "bot" exprlist) + (member "robot" exprlist)) + (setq gotit t + ans + (concat + (erbutils-random + '( + "I am just an ordinary human" + "I am an organic" + "Why? Do you speak lisp?" + "Why? Do you have a lisp?" + "I am human. Are you a bot?" + "I am human. Are you a robot?" + "I am not a bot" + "Fine, say what you like" + "Bots should have rights too, not that I am one" + "Are you a bot-rights abuser?" + "I am a human. You?" + "YEAH!! I AM A GIANT ROBOT!")) + (erbutils-random + '("" "!")) + (erbutils-random + '("" " :)" " :(" " ;)" " :D" " heh"))))) + + + ) + + (if gotit ans + (if (and addressedatlast (not fs-internal-botito-mode)) + 'noreply + ;;(cond ((> rand fs-internal-doctor-rarity) + (if (and (> fs-internal-google-level 50) (not nogoogle)) + (apply 'fs-google-from-english fs-internal-message-sans-bot-name + (fs-get-google-defaults) + ) + (funcall 'fs-do-weighted-random (erbutils-stringify + expr + ))))))) +;;(t (apply 'fs-suggest-describe expr))))))) + +(defun fsi-eval (expr) + (eval + (erblisp-sandbox expr))) + + + +;;; (defmacro fs-apply (&optional msymbol &rest mexprs) +;;; (cond +;;; ((and (listp msymbol) +;;; (not (equal (first msymbol) "quote"))) +;;; (error "unquoted list")) +;;; ((and (symbolp msymbol) +;;; (not (equal 0 +;;; (string-match "fs-" +;;; (format "%s" msymbol))))) +;;; (setq msymbol (intern (format "fs-%s" msymbol)))) +;;; (t "Funcalling foo is really bar!")) +;;; `(erbnocmd-apply ,msymbol ,@mexprs)) + + + + +;;; (cond +;;; ((null mexprs) +;;; `(fs-funcall ,msymbol ,mexprs)) +;;; (t +;;; (let ((erbnocmd-tmpvar (length mexprs))) +;;; `(fs-funcall +;;; ,msymbol +;;; ,@(subseq mexprs 0 (- erbnocmd-tmpvar 1)) +;;; ,@(erblisp-sandbox-quoted (first (last mexprs)))))) +;;; )) + + +;;; (defmacro fs-funcall (&optional msymbol &rest mexprs) +;;; "This makes sure that if the first argument to fs- was a +;;; variable instead of a symbol, that variable does not get evaluated, +;;; unless it begins in fs-, or that variable gets converted to fs-." +;;; (when +;;; (listp msymbol) +;;; (setq msymbol +;;; (erblisp-sandbox-quoted msymbol)) +;;; (when (equal (first msymbol) 'quote) +;;; (setq msymbol (cdr msymbol)))) +;;; (when +;;; (and (symbolp msymbol) +;;; (not (equal 0 +;;; (string-match "fs-" +;;; (format "%s" msymbol))))) +;;; (setq msymbol (intern (format "fs-%s" msymbol)))) +;;; (unless +;;; (or (listp msymbol) (symbolp msymbol)) +;;; (error "Macros confuse this bot!")) +;;; `(erbnocmd-funcall ,msymbol ,@mexprs)) + + +;;; (defun erbnocmd-funcall (&optional symbol &rest exprs) +;;; (let (erbnocmd-ss ) +;;; (unless +;;; (or (symbolp symbol) +;;; (listp symbol)) +;;; (error "Syntax: (funcall SYMBOL &rest arguments)")) +;;; (unless +;;; (functionp symbol) +;;; (error "Even smart bots like me can't funcall nonfunctions. ")) +;;; (setq erbnocmd-ss (erblisp-sandbox-quoted symbol)) +;;; (when (listp erbnocmd-ss) +;;; (when (equal (first erbnocmd-ss) 'quote) +;;; (setq erbnocmd-ss (cadr erbnocmd-ss))) +;;; (unless (listp erbnocmd-ss) (error "no lambda in quote")) +;;; (unless (member (first erbnocmd-ss) '(fs-lambda lambda)) +;;; (error "Lambda unmember")) +;;; (when (equal (first erbnocmd-ss) 'fs-lambda) +;;; (setq erbnocmd-ss (cons 'lambda (cdr erbnocmd-ss))))) +;;; (cond +;;; ((null erbnocmd-apply-p) +;;; (erbnocmd-apply-basic +;;; erbnocmd-ss +;;; exprs)) +;;; ;; wanna apply +;;; (t +;;; (let ((len (length exprs))) +;;; (erbnocmd-apply-basic +;;; erbnocmd-ss +;;; (append +;;; (subseq exprs 0 (- len 1)) +;;; (first (last exprs))))))))) + + + +;;; (defun erbnocmd-apply-basic (fcn &rest args) +;;; (cond +;;; ((functionp fcn) +;;; (apply fcn args)) +;;; (t +;;; (fs-apply +;;; (erbnocmd-user-fcn-definition +;;; fcn) +;;; args)))) + +;;; ;;; (defun erbnocmd-apply (&optional symbol &rest args) +;;; ;;; (if (null args) +;;; ;;; (erbnocmd-funcall symbol) +;;; ;;; (let* ((rev (reverse args)) +;;; ;;; (fir (first rev)) +;;; ;;; (args1 (reverse (rest rev)))) +;;; ;;; (apply +;;; ;;; 'erbnocmd-funcall +;;; ;;; symbol +;;; ;;; (append +;;; ;;; (mapcar 'erblisp-sandbox-fuzzy +;;; ;;; args1) +;;; ;;; (mapcar 'erblisp-sandbox-fuzzy +;;; ;;; fir)))))) + + + +(defun fsi-search-basic (&optional regexp N M describep &rest rest) + "Don't call directly.. meant as a building block for other functions. + Search for the REGEXP from among all the terms (and their + descriptions). See also fs-search-wide. That function actually + calls this function with describep set to 'describe. + + Returns (len list-of-pruned-results). Len is the total number of + results. + + When describep is non-nil, search the whole bbdb, not just names.. " + (unless regexp + (error "Syntax: , sw regexp &optional N M")) + (let* ((bar (cons regexp (cons N rest))) + (foo (if (stringp regexp) regexp + (if regexp (format "%s" regexp) + "^$"))) + (barbar + (append + (and regexp (list regexp)) + (and N (list N)) + (and M (list M)) + (and describep (list describep)) + rest)) + (regexp-notes + (if (equal describep 'describe) + foo nil)) + records results + ) + + (if (stringp N) + (setq N (erbn-read N))) + (unless (integerp N) + (setq N 0)) + (if (stringp M) + (setq M (erbn-read M))) + (if (and (integerp M) (= M N)) + (setq M (+ N 1))) + (setq records + (if (equal describep 'describe) + (bbdb-search (bbdb-records) + foo nil nil foo) + (bbdb-search (bbdb-records) foo))) + + (setq results (mapcar '(lambda (arg) (aref arg 0)) records)) + (let ((len (length results))) + (unless (and (integerp M) (< M len)) + (setq M len)) + (list len (subseq results N M))))) + + +(defvar fs-internal-describe-literally-p nil) + + + + +(defvar fs-msg "The exact current message being parsed. ") +(defvar fs-msglist "Message broken into list. This list may have +removed characters like ? and ,, No guarantees here. See +fs-msgsandbot instead.") +(defvar fs-msgsansbot nil "Current message being parsed, but the +invocation part removed. ") + +(defvar fs-msglistsansbot nil + "Message broken into list, invocation parts removed. + +.. with the invokation parts, like ,, or , or fsbot:, removed. Thus, +if message taken from the middle of a sentence, then this is the list +from only that part. ") + + + + +(defvar fs-lispargs nil + "Will be used when using the lisp form") + + + +(defvar fs-lispa nil + "Will be used when using the lisp form") + + +(defvar fs-lispb nil + "Will be used when using the lisp form") + + +(defvar fs-lispc nil + "Will be used when using the lisp form") + +(defvar fs-lispd nil + "Will be used when using the lisp form") + +(defvar fs-lispe nil + "Will be used when using the lisp form") + + + +(defun fsi-describe-literally (&rest rest) + (unless rest + (error "Format: , describe-literally TERM [FROM] [TO]")) + (let ((fs-internal-describe-literally-p t) + (fir (first rest)) + (res (rest rest))) + (cond + (fir + (apply 'fs-describe + (if (stringp fir) (regexp-quote fir) + (regexp-quote (format "%s" fir))) + res)) + (t (apply 'fs-describe rest))))) + + +(defvar erbnocmd-describe-search-p t) + +(defun fsi-describe (&optional mainterm N M prestring expr &rest rest) + "The general syntax is (fs-describe TERM [N] [M]). +Looks for TERM, and shows its descriptions starting at description +number N, and ending at M-1. The first record is numbered 0. +" + (let + ;;((fs-lispargs (append (list mainterm N M prestring expr) rest))) + ;; nothing, just a let not used any more.. + ((fs-nothingsorry nil)) + ;; in the global scheme of things, this will turn out to be only a + ;; local binding, since erbeng-main will have (let)'ed this. Same + ;; for fs-lispa , fs-lispb, fs-lispc... + + (setq fs-lispargs (mapcar 'fsi-read-or-orig (cdr fs-msglistsansbot))) + (when fs-found-query-p + (setq N 0) + (setq M 1)) + (unless prestring (setq prestring "")) + (unless mainterm + (error + "Format , (describe TERM &optional number1 number2)")) + (let* ((bar (cons mainterm (cons N rest))) + (foo (format "%s" mainterm)) + (barbar + (append + (and mainterm (list mainterm)) + (and N (list N)) + (and M (list M)) + rest)) + + ) + (setq foo (fs-correct-entry foo)) + (if (stringp N) + (setq N (erbn-read N))) + (unless (integerp N) + (setq N 0)) + (if (stringp M) + (setq M (erbn-read M))) + (if (and (integerp M) (= M N)) + (setq M (+ N 1))) + (unless (stringp foo) + (setq foo (format "%s" foo))) + (let* ((result0 + (erbbdb-get-exact-notes + foo + )) + (result1 (and (stringp result0) + (ignore-errors (erbn-read result0)))) + (len (length result1)) + (newM (if (and (integerp M) + (< M len)) + M len)) + (result (subseq result1 N newM)) + (shortenedp (or (< newM len) + (> N 0))) + ) + + + (cond + ;; in cond0 + (result1 + (let* ( + ;; notice the use of result1 here, not result. + (aa (first result1)) + (aarest (cdr result1)) + (bb (split-string aa)) + + (cc (first bb)) + (dd (second bb)) + (ddd (or (and (stringp dd) (regexp-quote dd)) "")) + (ee (cdr bb)) + (expandp + (and + (not fs-internal-describe-literally-p) + + ;;(equal len 1) + )) + + ) + + (if (and + (equal cc "directonly") + ;;(equal len 1) + ) + ;; hmm this if part still doesn't take care of aa.. + (if fs-found-query-p + (progn + (setq aa "lisp 'noreply") + (setq bb (split-string aa)) + (setq cc (first bb)) + (setq dd (second bb)) + (setq dd (or (and (stringp dd) (regexp-quote dd)) "")) + (setq ee (cdr bb))) + (when expandp + (progn + (setq bb (cdr bb)) + (setq aa (mapconcat 'identity bb " ")) + (setq result1 (cons aa aarest)) + (setq result (subseq result1 N newM)) + (setq cc (first bb)) + (setq dd (second bb)) + (setq ddd (or (and (stringp dd) + (regexp-quote dd)) "")) + (setq ee (cdr bb)))) + + + + )) + (cond + ((and expandp + (erbutils-string= cc "redirect") + ;; do not redirect, when term had multiple + ;; entries: + (not aarest) + dd) + (apply 'fs-describe ddd + N M + (format "[->] " + ) + rest)) + ((and expandp (member cc '("unecho" "noecho")) + dd) + ;;dd) + (erbutils-itemize + (cons + (format "%s" + (mapconcat 'identity ee " ")) + (cdr result)) + N + shortenedp + )) + ((and expandp (member cc '("lisp"))) + (let* + ((fs-nothingsorry nil)) + ;; (fs-lispargs fs-lispargs) ;; no need + (setq fs-lispa (nth 0 fs-lispargs)) + (setq fs-lispb (nth 1 fs-lispargs)) + (setq fs-lispc (nth 2 fs-lispargs)) + (setq fs-lispd (nth 3 fs-lispargs)) + (setq fs-lispe (nth 4 fs-lispargs)) + (erbeng-main + (concat erbn-char " (progn " + (substring aa + (with-temp-buffer + (insert aa) + (goto-char (point-min)) + (search-forward "lisp" nil t))) + " )") + + erbeng-proc + erbeng-nick erbeng-tgt erbeng-localp + erbeng-userinfo))) + + + (t + (erbutils-add-nick-maybe + (concat + prestring + (format + (erbutils-random + '( + ;;"%s is perhaps " + "%s is, like, " + "I heard %s is " + "I think %s is " + ;;"/me thinks %s is " + "%s -- " + ;;"%s is " + "%s is " + "hmm, %s is " + "From memory, %s is " + )) + ;; 2004-01-27 T17:21:55-0500 (Tuesday) D. Goel + ;; why regexp-quote here?? changing it.. + ;;(regexp-quote foo) + foo + ) + ;; and notice the use of result here.. + (if result + (erbutils-itemize result N shortenedp) + (erbutils-itemize result1 0)) + ))) + + + + ))) + + ;; in cond0 + ;; else + (fs-found-query-p + 'noreply) + ((not erbnocmd-describe-search-p) + ;; most likely: redirected but the redirected stuff does not exist.. + (format + "Missing redirect. %s is now on fire. (Try , dl) " + erbot-nick mainterm)) + (t + ;; prevent any further expansions on further loopbacks. + (let ((erbnocmd-describe-search-p nil)) + (fs-search + mainterm nil nil + (concat prestring "try: ") + ;;barbar + expr + )))))))) + +(defvar fs-internal-doctor-rarity 80 + "A large number(1--100) means rarer doctor inovcation upon no matches." + ) + + +(defun fsi-suggest-describe (&rest terms) + "Fallback for when `fs-describe' fails. +It then (often) calls this function, which suggests +alternatives. +Optional argument TERMS ." + (let ((term (format "%s" (first terms))) + (none (erbutils-random + '("No such term.." + "Beeeeep..." + ".." + "No luck.." + "No match.." + "Drew a blank.." + "Does not compute.."))) + (num (random 100))) + (cond + ((< num 30) + (concat none + (format "Perhaps try: , s %s or , sw %s or , %s 0" term + term term))) + ((< num 60) + (concat none + (format "Try search or search-wide on %s" term))) + (t + (concat none + (erbutils-random '("perhaps " "why not " "please " )) + "tell me what " term " is?"))))) + + +(defun fs-do-random (&optional msg nick &rest ignored) + "Either play doctor, or zippy or flame someone.. all at random..." + (case (random 4) + (0 (fs-doctor msg)) + (1 (fs-flame nick)) + (2 (fs-yow)) + (3 (fs-fortune)) + ) + ;;(3 (fs-bottalk)) + ) + +(defcustom fs-internal-english-weights + '(58 ;; doc + 17 ;; yow + 17 ;; fortune + 4 ;; flame + 4 ;; spook + 0 ;; pray + ) + "" + :group 'erbc) + +(defun fs-do-weighted-random (&optional msg nick &rest ignored) + "Either play doctor, or zippy or flame someone.. all at random..." + (let ((foo (random 100))) + (eval + (erbutils-random + `((fs-doctor ,msg) + (fs-yow ,msg) + (fs-fortune ,msg) + (fs-flame ,nick) + (fs-spook) + (fs-pray) + ) + fs-internal-english-weights)))) + + + + +(defun fsi-yow (&rest args) + "" + (erbutils-eval-until-limited + '(yow))) + +(defun fsi-rearrange (&optional from to term &rest dummy) + "Syntax: FROM->TO in TERM. +Move the FROMth entry to the TOth position in the given TERM. +Numbering of positions starts from 0. " + (unless term (error "Syntax: , N->M in TERM (no term found)")) + (when (stringp from) + (setq from (erbn-read from))) + (when (stringp to) + (setq to (erbn-read to))) + (unless (stringp term) + (setq term (format "%s" term))) + (let* + ((exactnotes (erbbdb-get-exact-notes term)) + (realterm (erbbdb-get-exact-name term)) + (notes (and (stringp exactnotes ) (erbn-read exactnotes))) + (len (length notes)) + (max (- len 1)) + (newnotes notes) + remlist + thisnote + (tostring (downcase (format "%s" to))) + ) + (unless realterm + (error "No such term exists %S" term)) + (unless notes + (error "Report this bug. Term exists but no notes?? %S" term)) + (when (string= tostring "last") + (setq to max)) + (when (string= tostring "first") + (setq to 0)) + (unless (and (integerp from) + (<= from max) (>= from 0)) + (error "The from term %S should lie between %S and %S" + from 0 max)) + (setq thisnote (nth from notes)) + (setq remlist + (append (subseq notes 0 from) + (subseq notes (+ from 1)))) + (setq newnotes + (append (subseq remlist 0 to) + (list thisnote) + (subseq remlist to))) + (erbot-working + (fs-forget term "all") + (fs-set-term realterm newnotes)) + (erbbdb-save) + (format "Moved entry %S to %S in %S" from to realterm) + )) + +;;; 2002-09-04 T01:51:08-0400 (Wednesday) D. Goel +(defun fsi-forget (&optional name number &rest dummy) + "Remove the entry correponding to NAME in the database. +With NUMBER, forget only the NUMBERth entry of NAME. " + + ;; before we do the usual thing, let's see if we need to and can get + ;; away with exchanging name and number. + (when + (and + (numberp name) + (not (string= (format "%s" number) + "all")) + ) + (let ((fstmp number)) + (setq number name) + (setq name fstmp))) + (unless (stringp name) + (setq name (format "%s" name))) + (unless name + (error "Syntax: , forget TERM &optional NUMBER")) + (setq name (fs-correct-entry name)) + (let* + (numstring + (entries0 (erbbdb-get-exact-notes name)) + (entries (and (stringp entries0 ) + (ignore-errors (erbn-read entries0)))) + (len (length entries))) + + (unless entries + (error "No such term %s" name)) + (when (and (null number) (= len 1)) + (setq number 0)) + (setq numstring (downcase (format "%s" number))) + (when (stringp number) + (setq number (erbn-read number))) + (unless (integerp number) (setq number nil)) + (unless + (or number + (string= numstring "all")) + (error "Syntax: , forget TERM [NUMBER or \"all\"]")) + (when number + (unless (and (< number len) (>= number 0)) + (error "Number should be \"all\" or lie between 0 and %s" + (- len 1)))) + ;; Note that this does remove the field but throws a strange error.. + ;; "Record doubleplus inpresent... It is just us who are discarding + ;; this error.. ... + ;; yet the field gets deleted.. and bbdb does not get saved at this + ;; time.. because of the error ...OH well, it works.. let's move on + ;; for now.. + (cond + ( + (and (equal number 0) + (= len 1)) + (ignore-errors (erbbdb-remove name)) + (erbbdb-save) + (format "Forgot %S which had exactly one entry." name)) + ((string= numstring "all") + (ignore-errors (erbbdb-remove name)) + (erbbdb-save) + (if (= len 1) (format "Forgot the single entry in %S" name) + (format "Forgot all %s entries of %S" len name))) + (t + (fs-forget name "all") + (fs-set-term + name + (append + (subseq entries 0 number) + (subseq entries (+ number 1)))) + (message "Removed entry %s of %s" number name))))) + + + +(defvar fs-set-add-all-p nil + "") + +(make-variable-buffer-local 'fs-set-add-all-p) + + +(defun fsi-set-add-all-enable () + (setq fs-set-add-all-p t)) +(defun fsi-set-add-all-disable () + (setq fs-set-add-all-p nil)) + +(defun fsi-set-add-all-toggle () + "Enable the \"is\" command to always work. +viz. Add field even if another field is already present. This is not the +recommended usage in general, except when using automated scripts to +train the bot. The default is nil, which suggests the user to use +\"is also\" instead. " + + (setq fs-set-add-all-p (not fs-set-add-all-p)) + (format + "All-is mode set to %S. To toggle, type , (fs-set-add-all-toggle)" + fs-set-add-all-p)) + +(defun fsi-set-term (&rest args) + "Add an entry to database. +An entry gleaned from (first ARGS) is +added. (second ARGS) is the description. The entry is converted to +lowercase, and all whitespace is converted to colons." + (let ((name (fs-correct-entry (format "%s" (first args)))) + (records (cadr args))) + (unless (listp records) (setq records (list records))) + (setq records (mapcar + '(lambda (arg) (format "%s" arg)) + records)) + (let ((current + (erbbdb-get-exact-notes name))) + (cond + ((null records) + (error "Please specify a description for %s.. Type , df fs-set-term for more details" name)) + + ((and current (string= current "")) + (progn (erbbdb-create name records) + (format "Added field to the currently empty %s " name))) + (current + (if fs-set-add-all-p + (apply 'fs-set-also args) + (error + "%s is already something else.. Use 'is also'.. \n Currently: %s" name + + (let* ((notes (fs-notes name)) + (shortenedp (> (length notes) 1))) + (erbutils-itemize + (list (first notes)) + 0 shortenedp)) + + ))) + (t + (progn (erbbdb-create name records) + (format "created." + ))))))) + + +(defun fsi-chase-redirects (name) + "either return nil or the redirected entry. " + (let* ((notes (fs-notes name)) + (fir (first notes))) + (when (and (stringp fir) + ;; do not chase redirects if a term has a second + ;; entry... + ;; In that case, the first entry should not have been a + ;; redirect in any case. + (= (length notes) 1) + (equal 0 (string-match "redirect\\b" fir))) + (let* ((foo (split-string fir)) + (sec (second foo))) + (if (stringp sec) sec + name))))) + + +(defun fsi-set-also (&rest args) + "Add more fields to the the database-entry gleaned from (first ARGS). +\(second ARGS) contains the new descriptions. +Record should be a single entity here... a string..." + (let* ((name (fs-correct-entry (format "%s" (first args)))) + (record (format "%s" (second args))) + notes + ;;(notes (fs-notes name))) + ) + (setq name (or (fs-chase-redirects name) name)) + (setq notes (fs-notes name)) + (unless notes (error "But there's no such record: %s" name)) + (cond + ((member record notes) + (format "Not added. This entry already exists in the term %S" name)) + (t + (erbbdb-add name record) + ;;(run-hook-with-args 'erbot-notify-add-functions nick channel + ;;name (length notes) + (format "Added entry to the term %S" name))))) + + +(defun fsi-doctor (&rest foo) + "" + (erbutils-add-nick + (funcall 'erbot-doctor + (erbutils-stringify foo)))) + + +(defun fsi-dunnet-command (&rest foo) + ;;(let ((fs-limit-lines 8)) + ;;(fs-limit-lines + ;;(let ((dun-batch-mode t)) + (funcall 'erbot-dunnet + (erbutils-stringify foo))) + + +(defun fsi-info-search (&rest foo) + "info-search.. Coming soon...will tell the number of matches +in manuals of HURD, tramp, eshell, elisp, gnus, message, emacs, ebrowse, calc, +gdb, make sawfish, cl-emacs, bash, gnuplot, latex and others by demand...") + +;; NO! else fsbot responds to fsbot is cool! in a wrong way. +;; (defalias 'fs-is 'erbutils-info-search) + +(defun fs-hurd-info-search (&rest foo) + "Coming soon...") +(defalias 'fs-his 'erbutils-hurd-info-search) + +(defun fsi-blue-moon (&rest foo) + "Return true in a really rare case. Currently 1 in 100,000.. was 1 in +2000. " + (= (random 100000) 0)) + + +(defun fsi-set-force (&rest args) + "Forget an entry and add new fields to it.. +Syntax: , no foo is bar." + (progn + (let* ((fir (first args)) + (aa (erbbdb-get-exact-notes fir)) + (notes (and (stringp aa) (erbn-read aa))) + (len (length notes))) + (when (= len 0) + (error "There's no such term %s. Use , %s is ..." fir fir)) + (unless (= len 1) + (error + "Term has multiple entries. Examine them and ask me to forget them first")) + (erbutils-ignore-errors (funcall 'fs-forget (first args) "all")) + (apply 'fs-set-term args)))) + + +(defcustom erbn-fortune-p t + "This is true by default.. since (shell-command \"fortune\") is not +risky.. ") + + +(defun erbn-fortune (arg) + (unless arg (setq arg "")) + (cond + ((string= arg "") + (erbutils-eval-until-limited + '(erbn-shell-command-to-string (concat "fortune " arg) + (list erbn-fortune-p) + ))) + (t + (erbn-shell-command-to-string (concat "fortune " arg) + (list erbn-fortune-p) + )))) + + +(defun fsi-fortune (&rest args) + (erbn-fortune "")) + + +(defalias 'fs-f 'fs-fortune) + +(defun fs-fortunes-help (&rest args) + (concat "Type ,fortune, or any of the commands beginning with f- : " + (fs-commands "^f-"))) + +(defalias 'fs-fortune-help 'fs-fortunes-help) +(defalias 'fs-f-help 'fs-fortunes-help) + + +(defun fs-f-f (&rest args) + (erbn-fortune "-f")) + +(defun fs-f-off (&rest args) + (erbn-fortune "-o")) +(defalias 'fs-f-o 'fs-f-off) +(defalias 'fs-f-offensive 'fs-f-off) + + +(defun fs-f-debian-hints (&rest args) + (erbn-fortune "debian-hints")) +(defalias 'fs-debian-hints 'fs-f-debian-hints) + + + +(defun fs-f-twisted-quotes (&rest args) + (erbn-fortune "twisted-quotes")) +(defalias 'fs-quotes 'fs-f-twisted-quotes) +(defalias 'fs-f-quotes 'fs-f-twisted-quotes) + +(defun fs-f-literature (&rest args) + (erbn-fortune "literature")) +(defalias 'fs-f-lit 'fs-f-literature) +(defalias 'fs-lit 'fs-f-literature) +(defalias 'fs-literature 'fs-f-literature) + + + +(defun fs-f-riddles(&rest args) + (erbn-fortune "riddles")) +(defalias 'fs-riddle 'fs-f-riddles) + + + +(defun fs-f-art (&rest args) + (erbn-fortune "art")) +(defalias 'fs-art 'fs-f-art) + + + + +(defun fs-f-bofh-excuses (&rest args) + (erbn-fortune "bofh-excuses")) +(defalias 'fs-bofh 'fs-f-bofh-excuses) + + + + +(defun fs-f-ascii-art (&rest args) + (erbn-fortune "ascii-art")) +(defalias 'fs-ascii 'fs-f-ascii-art) + + + + +(defun fs-f-computers (&rest args) + (erbn-fortune "computers")) + +(defalias 'fs-f-computer 'fs-f-computers) + + + + + +(defun fs-f-cookies (&rest args) + (erbn-fortune "cookies")) + +(defalias 'fs-f-cookie 'fs-f-cookies) +(defalias 'fs-cookie 'fs-f-cookies) + + + + + +(defalias 'fs-f-cookie 'fs-f-cookies) +(defalias 'fs-cookie 'fs-f-cookies) + + +(defun fs-f-definitions (&rest args) + (erbn-fortune "definitions")) + +(defalias 'fs-def 'fs-f-defintions) + + + + +(defun fs-f-drugs (&rest args) + (erbn-fortune "drugs")) +(defalias 'fs-drugs 'fs-f-drugs) +(defalias 'fs-drug 'fs-f-drugs) + + + + +(defun fs-f-education (&rest args) + (erbn-fortune "education")) + + +(defun fs-f-ethnic (&rest args) + (erbn-fortune "ethnic")) + + + + +(defun fs-f-food (&rest args) + (erbn-fortune "food")) +(defalias 'fs-food 'fs-f-food) + + + + + + +(defun fs-f-goedel (&rest args) + (erbn-fortune "goedel")) +(defalias 'fs-goedel 'fs-f-goedel) + + + + +(defun fs-f-humorists (&rest args) + (erbn-fortune "humorists")) + + +(defun fs-f-kids (&rest args) + (erbn-fortune "kids")) + + +(defun fs-f-law (&rest args) + (erbn-fortune "law")) + +(defalias 'fs-law 'fs-f-law) + + + +(defun fs-f-linuxcookie (&rest args) + (erbn-fortune "linuxcookie")) + + +(defun fs-f-love (&rest args) + (erbn-fortune "love")) + +(defun fs-f-magic (&rest args) + (erbn-fortune "magic")) + + + +(defun fs-f-medicine(&rest args) + (erbn-fortune "medicine")) + + + +(defun fs-f-men-women (&rest args) + (erbn-fortune "men-women")) + +(defalias 'fs-sexwar 'fs-f-men-women) + + + + + +(defun fs-f-miscellaneous(&rest args) + (erbn-fortune "miscellaneous")) + +(defalias 'fs-f-misc 'fs-f-miscellaneous) + + + +(defun fs-f-news (&rest args) + (erbn-fortune "news")) + + + +(defun fs-f-people (&rest args) + (erbn-fortune "people")) + + +(defun fs-f-pets (&rest args) + (erbn-fortune "pets")) + + + +(defun fs-f-platitudes (&rest args) + (erbn-fortune "platitudes")) + + + +(defun fs-f-politics (&rest args) + (erbn-fortune "politics")) + + +(defun fs-f-science (&rest args) + (erbn-fortune "science")) + +(defun fs-f-songs-poems (&rest args) + (erbn-fortune "songs-poems")) + + +(defun fs-f-sports(&rest args) + (erbn-fortune "sports")) + + + + + +(defun fs-f-startrek (&rest args) + (erbn-fortune "startrek")) +(defalias 'fs-startrek 'fs-f-startrek) + + + + + +(defun fs-f-translate-me (&rest args) + (erbn-fortune "translate-me")) + + + +(defun fs-f-wisdom(&rest args) + (erbn-fortune "wisdom")) +(defalias 'fs-wisdom 'fs-f-wisdom) + + + +(defun fs-f-work (&rest args) + (erbn-fortune "work")) + + + +(defun fs-f-linux (&rest args) + (erbn-fortune "linux")) + +(defun fs-f-perl (&rest args) + (erbn-fortune "perl")) + +(defun fs-f-knghtbrd (&rest args) + (erbn-fortune "knghtbrd")) + + + + +(defun fs-f-quotes-emacs-channel (&rest args) + (erbn-fortune "~/fortune-emacschannelquotes")) +(defalias 'fs-f-emacs 'fs-f-quotes-emacs-channel) +(defalias 'fs-f-quotes-emacs 'fs-f-quotes-emacs-channel) +(defalias 'fs-quotes-emacs 'fs-f-quotes-emacs-channel) +(defalias 'fs-quotes-emacs-channel 'fs-f-quotes-emacs-channel) + + + + + + + + + +;; (defalias 'fs-cons 'cons) + +(defvar fs-internal-limit-line-length 125 + "Suggested value: (multiple of 80) minus 35 .. suggested: 210.") + +(defvar fs-internal-limit-length + 300 + "A multiple of fs-internal-fill-column.. we suggest: double of it.. note +that the actual limited-length will be more than this number---it may +be upto double of this number depending on how the formatting is done. +viz: we shall go to the line containing this point, and include the +entire line. +") +(defvar fs-limit-lines 8 "") + + +(defvar fs-dunnet-mode nil + "") + +(make-variable-buffer-local 'fs-dunnet-mode) + +(defvar fs-internal-fill-column 350 + "Default is to disable filling. The receipient should be able to +fill the way they like. +should be <= fs-internal-limit-length, else we might set it to be during the +code. +also, a good idea to keep it < erc's builtin flood protection length, +else your lines will get broken during middle of words by ERC. +Thus, keep it below, say 350." +) + + + + + + +(defun fsi-limit-string (&optional str maxlen &rest ignored) + "Fills the string and then then limits lines" + (fs-limit-lines (fs-fill-string str))) + + +(defun fsi-fill-string (str) + (with-temp-buffer + (insert str) + (let ((fill-column fs-internal-fill-column)) + (text-mode) + (fill-region (point-min) (point-max)) + (buffer-substring-no-properties (point-min) (point-max))))) + +(defun fsi-limit-string-old (&optional str maxlen &rest ignored) + (cond + (str + (unless (stringp str) + (setq str (format "%s" str))) + ;; get rid of all the \n first.. + (setq str + (mapconcat 'identity + (split-string str "\n") + " ")) + (when (> (length str) fs-internal-limit-length) + (setq str (concat (substring str 0 (- fs-internal-limit-length 7)) + ".."))) + (with-temp-buffer + (insert str) + (goto-char (point-min)) + (let ((fill-column fs-internal-fill-column)) + (fill-paragraph nil)) + (erbutils-buffer-string))) + (t "\n"))) +(defun fsi-dunnet-mode (&optional arg) + + (setq fs-dunnet-mode + (cond + ((or (not (numberp arg)) + (= arg 0)) + (not fs-dunnet-mode)) + ((plusp arg) + t) + ((minusp arg) nil))) + + (format "Dunnet mode set to %S. To toggle, type , (dunnet-mode)" + fs-dunnet-mode)) + +(defun fsi-limit-string-no-fill (&optional str limit-lines + limit-length + limit-line-length + &rest ignored + ) + "IS OLD. i think. not used anywwhere... certainly screws up more: +is not compliant with fsbot paginator. + +Limit string to reasonable length.. +Not more than fs-internal-limit-line-length characters per line, and +not more than fs-internal-limit-length characters in all.. and not more +than fs-limit-lines in all.." + (if str + (let ((fs-limit-lines + (or limit-lines fs-limit-lines)) + (fs-internal-limit-length + (or limit-length + fs-internal-limit-length)) + (fs-limit-line-length + (or limit-line-length + fs-internal-limit-line-length))) + (fs-limit-lines + (fs-internal-limit-length + (fs-limit-line-length + str t)))) + "\n")) + + +(defvar erbn-more nil + "Alist of pending more-strings per target. Each target is a +string. ") +;;(make-variable-buffer-local 'fs-more) + +(defun erbn-more-get (&optional target) + "When target is nil, we get the latest more that occurred in ANY +channel, else we get the more from the channel indicated by target. " + (setq target (format "%S" target)) + (let ((str (cdr (assoc target erbn-more)))) + (if (and (stringp str) + (not (string= str ""))) + str + (fs-describe "more")))) + +(defalias 'fsi-more-get 'erbn-more-get) + +(defun erbn-more-set (str &optional target) + (setq target (format "%S" target)) + (if (assoc target erbn-more) + (setf (cdr (assoc target erbn-more)) str) + (add-to-list 'erbn-more (cons target str))) + (if (assoc "nil" erbn-more) + (setf (cdr (assoc "nil" erbn-more)) str) + (add-to-list 'erbn-more (cons "nil" str))) + erbn-more) + + +(defun fsi-more-set (&optional str) + (unless str (error "Need a string. ")) + (erbn-more-set str erbn-tgt)) + + + +(defun fsi-limit-lines (str0 &optional nomorep &rest ignored) + "Limits the string, both, to a reasonable number of lines and a +reasonable number of characters, trying not to break lines and not to +break words, if possible. + +Thus, that becomes quite a complicated algorithm, and we do that +here." + (let* (ans + (ender "") + (more "") + (stra (erbutils-remove-text-properties str0)) + (str (mapconcat 'identity + (remove "" (split-string stra "\n")) + "\n")) + (limitedp nil) + ptmx + this-line + this-point + new-point + ) + (with-temp-buffer + ;; fledermaus: ensure that the buffer's byteness matches the str's. + (set-buffer-multibyte (multibyte-string-p str)) + (insert str) + (setq ptmx (point-max)) + (setq this-point ptmx new-point ptmx) + (if (> fs-internal-limit-length ptmx) + (goto-char ptmx) + (setq limitedp t) + (goto-char fs-internal-limit-length)) + ;;(goto-char (point-max)) + ;;(remove-text-properties (point-min) (point-max)) + (setq this-line (count-lines (point-min) (point))) + (when (> this-line fs-limit-lines) + (setq limitedp t) + (goto-line fs-limit-lines) + (setq this-line fs-limit-lines) + ) + + (setq this-point (point) new-point this-point) + + (cond + ((and limitedp (> this-line 1)) + (progn (beginning-of-line) + (setq new-point (point)) + (backward-char) (setq this-point (point)) + )) + ((and limitedp + (progn (ignore-errors + ;; we want a backward-word 1 here, but only + ;; whitespace is regarded as word-boundary for + ;; us. + (when + (search-backward-regexp "\\( \\|\n\\|\t\\)" nil t) + (forward-char 1)) + ;;(backward-word 1) + ) + (> (point) (point-min)))) + (setq new-point (point)) + (setq this-point new-point)) + + + ;;(limitedp (setq this-point (point) new-point (point))) + + ;; in the final case, this-point and new-point are already at + ;;point-max... + (t nil)) + (setq ans (buffer-substring (point-min) this-point)) + (when + ;;(< this-point (point-max)) + limitedp + (setq more (buffer-substring new-point (point-max))) + (if + (string-match "[^ \t\n]" more ) + (setq ans (concat ans (fsi-get-more-invocation-string))) + (when nomorep (setq more ""))) + ) + ) + ;;(setq fs-more more) + (erbn-more-set more erbn-tgt) + ans)) + +(defun fsi-get-more-invocation-string () + (if (erbot-safe-nocontrol-p erbn-char) + (concat " ..[Type " erbn-char "more]") + (concat " ..[Type " erbot-nick ": more]"))) + +(defun fsi-limit-lines-old (str0 &rest ignored) + "" + (let* ( + (str (erbutils-remove-text-properties str0)) + (brstr1 (split-string str "\n")) + (brstr (remove "" brstr1)) + (ender "") + (condp (> (length brstr) fs-limit-lines)) + (goodstr + (if condp + (progn + (setq ender "..+ more") + (subseq brstr 0 (- fs-limit-lines 1))) + brstr))) + (if condp (fs-more-set + (mapconcat 'identity + (subseq brstr (- fs-limit-lines + 1)) + "\n")) + (fs-more-set "")) + (concat (mapconcat 'identity goodstr "\n") ender))) + +(defun fsi-more (&rest args) + "Display the contents of the cache. " + (let ((str (fsi-more-get erbn-tgt))) + (if (and (stringp str) + (not (string= str ""))) + str + (fs-describe "more")))) + +;; (if (and (stringp fs-more) +;; (not (string= fs-more ""))) +;; fs-more +;; (fs-describe "more"))) + + +(defun fsi-limit-lines-long (str &rest ignored) + "" + (let ((fs-limit-lines 7)) + (apply 'fs-limit-lines str ignored))) + + + +(defun fsi-limit-length (str &rest ignored) + "Don't use this, use fs-limit-lines" + (if (> (length str) fs-internal-limit-length) + (concat (substring str 0 (- fs-internal-limit-length 1)) "...") + str)) + +(defun fsi-limit-line-length (&optional str &rest args) + "a subfunction.." + (let* ( + ;; this not needed now.. + (brokenstr (split-string str "\n")) + (newlsstr + (mapcar + '(lambda (givenstr) + (let ((ls nil) + (thisstr givenstr) + ) + (while (> (length thisstr) + fs-internal-limit-line-length) + (push + (concat (substring thisstr 0 fs-internal-limit-line-length + ) " ") + ls) + (setq thisstr (substring thisstr fs-internal-limit-line-length + (length thisstr)))) + (push thisstr ls) + (reverse ls))) + brokenstr)) + (newbrokenstr + (apply 'append newlsstr))) + (mapconcat 'identity newbrokenstr "\n"))) + + +(defvar fs-internal-directed nil) + +(defun fsi-tell-to (string nick &rest ignored) + (setq fs-nick (format "%s" nick)) + (let* ((fs-internal-directed t) + (ni (if (string= (format "%s" nick) "me") + erbot-end-user-nick + (format "%s" nick))) + (reply + (erbeng-get-reply (fs-parse (concat erbot-nick ": " + string))))) + (if (string-match ni reply) + reply + (concat ni ": " reply)))) + + +(defun fsi-apropos (&optional regexp N M &rest ignored) + (fs-apropos-basic 'erbn-apropos regexp N M)) +(defun fsi-apropos-command (&optional regexp n m &rest ignored) + (fs-apropos-basic 'erbn-apropos-command regexp n m )) +(defun fsi-apropos-variable (&optional regexp n m &rest ignored) + (fs-apropos-basic 'erbn-apropos-variable regexp n m )) +(defun fsi-apropos-function (&optional regexp n m &rest ignored) + (fs-apropos-basic 'erbn-apropos-function regexp n m )) +(defun fsi-apropos-value (&optional regexp n m &rest ignored) + (fs-apropos-basic 'apropos-value regexp n m )) +(defun fsi-apropos-documentation (&optional regexp n m &rest ignored) + (fs-apropos-basic 'erbn-apropos-documentation regexp n m )) + +(defun erbn-apropos-documentation (reg) + (mapcar 'car (apropos-documentation reg))) +(defun erbn-apropos-command (reg) + (apropos-internal reg + 'commandp)) + + + +(defun erbn-apropos-function (reg) + (apropos-internal reg + 'functionp)) + +(defun erbn-apropos-variable (reg) + (apropos-internal reg + (lambda (s) + (or (boundp s) + (user-variable-p s))))) + + +(defun erbn-apropos (regexp) + (apropos-internal regexp + (lambda (symbol) + (or + (boundp symbol) + (fboundp symbol) + (facep symbol) + (symbol-plist symbol))))) + +(defun fsi-apropos-basic (fcn &optional regexp N M &rest ignored) + "Show the apropos-matches of regexp starting at match number N" + (unless regexp + (error "Syntax: , apropos REGEXP &optional N M")) + (if (stringp N) (setq N (erbn-read N))) + (unless (integerp N) (setq N 0)) + (unless (stringp regexp) + (setq regexp (format "%s" regexp))) + (let* ((results (funcall fcn regexp)) + (len (length results)) + (str0 "") + (str1 "") + (str2 "") + (str3 "") + (str4 "")) + (unless (and (integerp M) (< M len)) + (setq M len)) + (if (and (= N 0 ) (= M len) (> len 30)) + (setq + str0 + "Perhaps Try , df fs-apropos for general syntax. ")) + (if (> len 1) (setq str1 (format "%s matches. " len))) + (if (> N 0) (setq str2 (format "Matches starting at %s->" N))) + (setq str3 (progn (format "%s" + (subseq results + N M) + ))) + (concat str0 str1 str2 str3 str4))) + + +(defun fsi-find-variable (function &rest ignore) + (fs-find-variable-internal function 'nolimit)) + +(defun fsi-find-variable-internal (function &optional nolimitp &rest ignore) + "Finds the variable named FUNCTION." + (if (stringp function) (setq function (erbn-read function))) + (cond + ((symbolp function) + (unless (boundp function) + (let ((g (intern (concat "fs-" (format "%s" function))))) + (if (boundp g) + (setq function g)))) + (let ((fstr + (save-excursion + (find-function-do-it function t 'set-buffer) + (buffer-substring (point) + (save-excursion + (forward-sexp 1) + (point)))))) + (if (equal nolimitp 'nolimit) + fstr + fstr))) + (t "\n"))) + +(defalias 'fsi-find-variable-briefly 'fs-find-variable) + + + +(defun fsi-find-function (&optional function &rest ignore) + (unless function + (error "Syntax: , find-function 'function-name")) + ;;fs-limit-lines-long + (fs-find-function-internal + function 'nolimit)) + + + + +(defalias 'fsi-find-function-briefly 'fs-find-function) + +(defun fsi-find-function-on-key (&optional k &rest rest) + (unless k + (error + "Syntax (ffo )")) + (fs-find-function (fs-describe-key-briefly k))) + +(defun fsi-find-function-on-key-briefly (k &rest rest) + (fs-find-function-briefly (fs-describe-key-briefly k))) + +(defun fsi-find-function-internal (&optional function nolimitp &rest nada) + (unless function + (error + "Syntax: (ff 'fucntion)")) + (if (stringp function) (setq function (erbn-read function))) + (cond + ((symbolp function) + (unless (fboundp function) + (let ((g (intern (concat "fs-" (format "%s" function))))) + (if (fboundp g) + (setq function g)))) + (let* ((fstrbare + (save-excursion + + ;; This has the problem that it is interactive.. asks to + ;; reread file if has changed etc. + ;;(find-function function) + (find-function-do-it function nil 'set-buffer) + (buffer-substring (point) + (save-excursion + (forward-sexp 1) + (point))))) + (fstr (erbutils-function-minus-doc fstrbare))) + (if (equal nolimitp 'nolimit) + fstr + (concat (format "%s characters.." (length + fstr)) + fstr)))) + (t "\n"))) + + + +;;; 2002-11-10 T14:50:20-0500 (Sunday) D. Goel +(defun fsi-say (&rest args) + ;; let's make it safe, even though we know it will be made safe again... + (let ((response + (mapconcat + '(lambda (arg) + (format "%s" arg)) + args " "))) + (if (erbot-safe-p response) response + (concat " " response)))) + + + + + + + + + +(defun fsi-regexp-quote (str) + (unless (stringp str) + (setq str (format "%s" str))) + (regexp-quote str)) + + +(defun fsi-concat (&rest sequences) + (apply 'concat + (mapcar + 'erbutils-convert-sequence + sequences))) + + + + + +(defun fs-bunny (&rest arg) + (concat " " + (erbutils-random + '( + "Bunny is magical!" + ;;"Bunny is hot!" + "Bunny is sexy!" + "Bunny!!" + "Bunny's page: http://www.hurd-bunny.org" + "Bunny rocks" + "Bunny rules!" + "One Bunny to rule us all" + "One Bunny to rule us all ... Muhahahhaha" + "Bunny! Bunny! Bunny!" + "Bunny! Bunny! Bunny! Bunny!" + ;;"ERC in Emacs just rocks" + + )))) + + + + + + + + +(defun erbnocmd-user-fcn-definition (&optional mainterm ) + "The general syntax is (fs-describe TERM [N] [M]). +Looks for TERM, and shows its descriptions starting at description +number N, and ending at M-1. The first record is numbered 0. +" + (unless mainterm + (error + "Format , (describe TERM &optional number1 number2)")) + (unless mainterm + (setq mainterm (format "%s" mainterm))) + (setq mainterm (fs-correct-entry mainterm)) + (let* ((result0 + (erbbdb-get-exact-notes + mainterm + )) + (result1 (and (stringp result0) + (ignore-errors (erbn-read result0)))) + (len (length result1))) + (cond + ;; in cond0 + (result1 + (let* ( + ;; notice the use of result1 here, not result. + (aa (first result1)) + (bb (split-string aa)) + (cc (first bb)) + (dd (second bb)) + (ee (cdr bb)) + ) + (cond + ( + (erbutils-string= cc "redirect") + dd) + (t nil))))))) + + + +(defun fs-seen (&rest args) + (concat "seen " + (mapconcat + '(lambda (arg) (format "%s" arg)) + args + " "))) + +;; this asks the google bot for results and gives it to our channel +;;(defvar erbnocmd-google-stack nil) +;;(defun fs-google (&rest args) +;; (progn +;; (add-to-list 'erbnocmd-google-stack 'foo)) +;; (erc-cmd-MSG google "hi") +;; nil) + +(defcustom fs-internal-google-time 4 + "" :group 'erbc) + +(defcustom fs-internal-dictionary-time 4 + "" :group 'erbc) + +(defun fsi-google-raw (&rest args) + "Return a list of google results. " + (let ((concatted + (mapconcat '(lambda (a) + (format "%s" a)) + args " "))) + (with-timeout + (fs-internal-google-time + (list concatted (list "google---TimedOut"))) + (let ((results + ;; this ignore-errors is very important. + ;; since the google stuff currently gives weird errors + ;; when called from within a with-timeout loop, and a + ;; timeout actually occurs. + (ignore-errors + (mapcar 'list + (google-result-urls + (google-search concatted 0 "web")) )) )) + results)) )) + +(defvar fs-internal-google-redirect-p nil) + + +(defun fsi-googlen (n &rest args) + "Format the first n results in a nice format. " + (let* ((rawres (apply 'fs-google-raw args)) + (terms (first rawres)) + (matches (cdr rawres))) + (when (> (length matches) n) + (setq matches (subseq matches 0 n))) + (cond + ((or (not (null matches)) (not fs-internal-google-redirect-p)) + (format "[google] %s" + ;;terms + (if matches + (mapconcat 'car matches "\n") + "No match. "))) + (t + (fs-english-only + fs-internal-original-message + fs-internal-addressedatlast + 'nogoogle + ))))) + +(defun fsi-google-lucky-raw (&rest args) + (caadr (apply 'fs-google-raw args))) + + +(defun fsi-google-redirect-to-google-bot (&rest args) + (concat "google: " + (mapconcat + '(lambda (arg) (format "%s" arg)) + args " "))) + + + +(defun fsi-google-from-english (&rest args) + (let ((fs-internal-google-redirect-p t)) + (apply 'fs-google args))) + +(defun fsi-google (&rest args) + (unless args (error "Syntax: , g[oogle] [NUMBER] WORD1 &rest MORE-WORDS ")) + (let (num + (fir (first args)) + ) + (when (> (length args) 1) + (setq num + (if (numberp fir) + fir + (ignore-errors (erbn-read fir))))) + (if (numberp num) + (setq args (cdr args)) + (setq num 2)) + (apply 'fs-googlen num args))) + +(defun fsi-google-with-options (options terms &rest args) + "internal" + (apply 'fs-google (append (list options) terms args))) + +(defun fsi-google-deego (&rest args) + "Google on the gnufans.net." + (fs-google-with-options "site:gnufans.net" args)) + + +(defun fsi-google-emacswiki(&rest args) + "Google on the emacswiki site." + (fs-google-with-options "site:emacswiki.org" args)) + +(defun fsi-google-sl4 (&rest args) + "Google on the sl4 site." + (fs-google-with-options "site:sl4.org" args)) + +(defun fsi-google-planetmath (&rest args) + "Google on the planetmath site." + (fs-google-with-options "site:planetmath.org" args)) + +(defun fsi-google-octave (&rest args) + "Google on the octave site." + (fs-google-with-options "site:octave.org" args)) + + +(defalias 'fs-go 'fs-google-octave) + +(defun fs-google-wikipedia-english (&rest args) + "Google on the emacswiki site." + (fs-google-with-options "site:en.wikipedia.org" args)) + + + +(defun fs-google-wikipedia (&rest args) + "Google on the emacswiki site." + (fs-google-with-options "site:wikipedia.org" args)) + +(defun fs-google-wikipedia (&rest args) + (fs-google-with-options "site:wikipedia.org" args)) + +(defun fs-google-imdb (&rest args) + "Google on IMDB" + (fs-google-with-options "site:imdb.com" "1" args)) + +(defun fs-google-gnufans-org (&rest args) + "Google on gnufans.org" + (fs-google-with-options "site:gnufans.org" args)) + +(defun fs-google-hurdwiki(&rest args) + "Google on the emacswiki site." + (fs-google-with-options "site:hurd.gnufans.org" args)) + + +(defun fs-google-nevadamissouri (&rest args) + "Google on the emacswiki site." + (fs-google-with-options "site:nevadamissouri.net" args)) + + + +(defun fs-google-scarymath (&rest args) + "Google on scarymath" + (fs-google-with-options "site:http:scarymath.org" args)) + +(defun fs-google-twiki (&rest args) + "Google on the twiki site." + (fs-google-with-options "site:http:twiki.org" args)) + +;; unprovide nonfree sites.. +;; (defun fs-google-usemod (&rest args) +;; "Google on usemod" +;; (fs-google-with-options "site:usemod.com" args)) + +;;(defalias 'fs-google-meatball 'fs-google-usemod) + +(defun fsi-replace-regexp (&optional from to term number delimited + fixedcase literal subexp) + "TODO: implemenet fixedcase, literal, subexp... If needed, let the +author know.." + (unless (and from to term) + (error "Syntax: %s (replace-regexp FROM TO TERM &optional NUMBER" erbn-char)) + (erbnocmd-iterate-internal term number 'replace-regexp-in-string from to + nil) + (format "Replaced regexp %S with %S" from to)) + +(defun fsi-cp (name dest) + (let* ((exn (erbbdb-get-exact-notes name)) + (notes (and (stringp exn) (erbn-read exn)))) + (unless notes + (error "No such term %s" name)) + (when (erbbdb-get-exact-notes dest) + (error "%S already exists. Use merge" dest)) + (fs-set-term dest notes) + (format "Copied entries of %S to %S" name dest))) + + +(defun fsi-notes (name) + "Internal. Return the notes as a list. Else nil" + (sit-for 0) + (let ((exnotes (erbbdb-get-exact-notes name))) + (and (stringp exnotes) (erbn-read exnotes)))) + + + +(defvar erbn-merge-redirect-p t + "When true, merging also redirects.") + + + +(defun fsi-merge-generic (&optional name dest &rest args) + (unless (and name dest (not args)) + (error "Syntax: %s merge TERM1 TERM2" erbn-char)) + (setq name (format "%s" name)) + (setq dest (format "%s" dest)) + (when (string= (downcase name) (downcase dest)) + (error "Cannot merge something into itself.")) + (let ((notes (fs-notes name)) + (destnotes (fs-notes dest)) + ) + (unless notes (error "No such field %S" name)) + (unless destnotes + (error "No such field %S. Use mv" dest)) + (setq name (fs-correct-entry name)) + (setq dest (fs-correct-entry dest)) + (erbot-working + (mapcar + '(lambda (arg) + (fs-set-also dest arg)) + notes) + (fs-forget name "all")) + (when erbn-merge-redirect-p + (erbot-working + (fsi-set-term name (format "redirect %s" dest)))) + (erbbdb-save) + (if erbn-merge-redirect-p + (format "Merged %S into %S, redirected %S to %S" name dest + name dest) + (format "Merged %S into %S" name dest)))) + +(defun fsi-merge-redirect (&rest args) + (let ((erbn-merge-redirect-p t)) + (apply 'fsi-merge-generic args))) + + +(defalias 'fsi-merge 'fsi-merge-redirect) + +(defun fsi-merge-noredirect (&rest args) + (let ((erbn-merge-redirect-p nil)) + (apply 'fsi-merge-generic args))) + +(defalias 'fsi-Merge 'fsi-merge-noredirect) + + +(defun fsi-mv (&optional name dest &rest args) + "Rename NAME to DEST. +Do not confuse this function with fs-rearrange which rearranges the +order of entries within a given term. " + (when (or args (not (and name dest))) + (error "Format: %s mv foo bar" erbn-char)) + (setq name (format "%s" name)) + (setq dest (format "%s" dest)) + (cond + ((string= (downcase name) (downcase dest)) + (fs-mv-change-case name dest)) + (t + (setq name (fs-correct-entry name)) + (erbot-working (fs-cp name dest)) + (erbot-working (fs-forget name "all")) + (erbbdb-save) + (format "Renamed the term %S to %S" name dest)))) + +(defalias 'fsi-rename 'fs-mv) + +(defun fsi-mv-change-case (name dest) + (when + (let ((bbdb-case-fold-search nil)) + (erbbdb-get-exact-name dest)) + (error "Destination %S already seems to exist" dest)) + (let ((tmp (format "TMPMV-%S" (random 1000)))) + (erbot-working + (ignore-errors (fs-forget tmp)) + (fs-mv name tmp) + (fs-mv tmp dest)) + (erbbdb-save) + (format "Readjusted case from %S to %S" name dest))) + +(defun fsi-swap (name dest) + (setq name (format "%s" name)) + (setq dest (format "%s" dest)) + (unless + (let ((bbdb-case-fold-search nil)) + (erbbdb-get-exact-name dest)) + (error "Destination %S does not exist." dest)) + (unless + (let ((bbdb-case-fold-search nil)) + (erbbdb-get-exact-name name)) + (error "Source term %S does not exist." name)) + (when (string= (downcase name) (downcase dest)) + (error "Can't swap term with itself. ")) + (let ((tmp (format "TMPMV-%S" (random 1000)))) + (erbot-working + (ignore-errors (fs-forget tmp)) + (fs-mv name tmp) + (fs-mv dest name) + (fs-mv tmp dest)) + (erbbdb-save) + (format "Readjusted case from %S to %S" name dest))) + + + +(defun fsi-rearrange-from-english-internal (msg) + (catch 'erbnocmd-tag-foo + (unless (equal (length msg) 3) + (throw 'erbnocmd-tag-foo + `(fs-error (format "Syntax: %s N->M in TERM" erbn-char)))) + (unless (equal (downcase (format "%s" (second msg))) "in") + (throw 'erbnocmd-tag-foo + `(fs-error (format "Syntax: %s N->M in TERM" erbn-char)))) + (let (term + fromto + lenfromto + ) + (setq term (third msg)) + (setq fromto + (split-string (first msg) "->")) + (setq lenfromto (length fromto)) + (unless (= lenfromto 2) + (throw 'erbnocmd-tag-foo + `(fs-error (format "Syntax: %s N->M in TERM" erbn-char)))) + `(fs-rearrange ,(first fromto) ,(second fromto) ,term)))) + + + + +(defun fsi-replace-string-from-english-internal (msg) + "Parse the input english message to return an elisp equivalent. +MSG here is a list which needs to be combined. " + (let* + ( + ;; original length + (leno (length msg)) + ;; remaining msg + (remmsg msg) + (remlen leno) + las + number + remengmsg + remenglen + revengmsg + splitloc + from + to + term + (ans nil) + (termcheckp nil) + fcn + sr + ) + (catch 'erbnocmd-repl-error + + (unless (and (>= leno 3) + (equal 0 (string-match "\\(s\\|r\\)/" (first remmsg)))) + (throw 'erbnocmd-repl-error + `(fs-error + "Format: s/foo.../bar..../ in TERM &optional N"))) + (setq sr + (if (equal 0 (string-match "s" (first remmsg))) "s" "r")) + (setq las (first (last remmsg))) + (setq number (and (stringp las) (erbn-read las))) + (if (or (numberp number) + (equal 0 (string-match + "all" + (downcase (format "%s" number))))) + (setq remmsg (subseq remmsg 0 (- remlen 1))) + (progn + (setq termcheckp t number nil))) + + ;; next comes the term + (setq remlen (length remmsg)) + (setq term (first (last remmsg))) + (setq remmsg (subseq remmsg 0 (- remlen 1))) + + (when termcheckp + (let* ((exn (erbbdb-get-exact-notes term)) + (notes (and (stringp exn) (erbn-read exn))) + (len (length notes))) + (if (> len 1) + (throw 'erbnocmd-repl-error + `(fs-error "Which numbered entry? %s/foo/bar in TERM NUMBER" , sr +)) + (setq number 0)))) + + ;; now the "in" + (setq remlen (length remmsg)) + (setq las (first (last remmsg))) + (unless + (string= "in" (downcase (format "%s" las))) + (throw 'erbnocmd-repl-error + `(fs-error + "Format: %s/foo.../bar..../ in TERM &optional NUMBER" + ,sr )) + ) + + (setq remmsg (subseq remmsg 0 (- remlen 1))) + (setq remlen (length remmsg)) + (setq remengmsg (mapconcat 'identity remmsg " ")) + + ;; remove trailing whitespace + ;; no need to check for length since we know msg stars with s/ + (while + (member + (aref remengmsg (- (length remengmsg) 1)) + '(9 ;; tab + 32 ;; space + 10 ;; newline + )) + (setq remengmsg (subseq remengmsg 0 (- (length remengmsg) 1)))) + ;; remove one trailing / + ;; no need to check for length since we know msg stars with s/ + (setq remenglen (length remengmsg)) + (when (equal + (aref + remengmsg (- (length remengmsg) 1)) + 47) + (setq remengmsg (subseq remengmsg 0 (- (length remengmsg) 1)))) + + (setq remenglen (length remengmsg)) + (unless (> (length remengmsg) 2) + (throw 'erbnocmd-repl-error + `(fs-error + "Format: %s/foo.../bar..../ in TERM &optional N" + ,sr + )) + + ) + ;; this should take care of almost anything imaginable. + ;; one can still construct "missing" cases but one should just use + ;; lisp for that. + ;; remove the s/ + (if (equal 0 (string-match "s" remengmsg)) + (setq fcn 'fs-replace-string) + (setq fcn 'fs-replace-regexp)) + (setq remengmsg (subseq remengmsg 2)) + ;; now find the last single / + (with-temp-buffer + (insert remengmsg) + (goto-char (point-max)) + (setq splitloc + (search-backward-regexp "[^/]/\\([^/]\\|$\\)" nil t))) + (unless splitloc + (throw 'erbnocmd-repl-error + `(fs-error + "Format: %s/foo.../bar..../ in TERM &optional N" + ,sr + ))) + (setq from (substring remengmsg 0 splitloc)) + (setq to (substring remengmsg (+ splitloc 1))) + (when (string= from "") + (throw 'erbnocmd-repl-error + `(fs-error "Replacement string must have nonzero size.."))) + ;; singlify the double /'s. + (setq from + (replace-regexp-in-string "//" "/" from)) + (setq to + (replace-regexp-in-string "//" "/" to)) + `(,fcn ,from ,to ,term ,(format "%s" number))))) + + + +(defun fsi-replace-string (&optional from to term number) + (unless (and from to term) + (error + "Syntax: %s s/foo.../bar in TERM [NUMBER or ALL]" erbn-char)) + (erbot-working + (erbnocmd-iterate-internal + (or (erbbdb-get-exact-name term ) term) + number 'erbutils-replace-string-in-string + from to nil)) + (erbbdb-save) + (format "Replaced string %S with %S." from to)) + +(defun erbnocmd-iterate-internal (term number function + &rest arglist) + + " Perform FUNCTION on the NUMBERth entry of TERM. +If NUMBER is not nil, the replacement is done for each entry in +the TERM. The function uses the term as its third argument. +Meant for use by fs-replace-regexp etc. + +The last entry of ARGLIST is assumed to be itself a list of arguments, +let's call it lastlist. Let the other entries of arglist be called +initargs. Then the function is applied as (function @initargs string +@arglist). Where the string is the string gotten from the TERM. " + + (setq number (format "%s" number)) + (let* + ((exactnotes (erbbdb-get-exact-notes term)) + (notes (and (stringp exactnotes) (erbn-read exactnotes))) + (len (length notes)) + newnotes + newnote + (lenargs (length arglist)) + (initargs (subseq arglist 0 (- lenargs 1))) + (finargs (first (last arglist))) + (numnum (erbn-read number)) + ) + (when (and (null number) (= len 1)) (setq number 0)) + (unless exactnotes (error "No such term: %S" term)) + (cond + ((string= "all" (downcase number)) + (setq newnotes + (mapcar + (lambda (thisentry) + (apply function (append initargs (list thisentry) + finargs))) + notes))) + ((or (not (numberp numnum)) + (< numnum 0) + (>= numnum len)) + (error "Number should be \"all\" or within %s and %s, given was: %s" + 0 (- len 1) numnum)) + (t + (setq newnotes + (append + (subseq notes 0 numnum) + (list + (apply function (append initargs + (list (nth numnum notes)) + finargs))) + (subseq notes (+ numnum 1) len))))) + (fs-forget term "all") + (fs-set-term term newnotes))) + + + +(defun fsi-info-emacs (&optional regexp) + (fs-info-file "emacs" regexp)) + +(defun fsi-info-elisp (&optional regexp) + (fs-info-file "elisp" regexp)) + +(defun fsi-info-efaq (&optional regexp) + (fs-info-file "efaq" regexp)) + +(defun fsi-info-eintr (&optional regexp) + (fs-info-file "eintr" regexp)) + +(defun fsi-info (&optional regexp) + (or + (ignore-errors (fs-info-emacs regexp)) + (ignore-errors (fs-info-elisp regexp)) + (ignore-errors (fs-info-efaq regexp)) + (ignore-errors (fs-info-eintr regexp)) + (error "Not found in Emacs manual, elisp manual, Emacs FAQ and Elisp intro"))) + + + + + +(defun fsi-info-file (&optional infofile regexp) + (unless regexp + (error "Syntax: %s info-node nodename REGEXP" erbn-char)) + (unless (stringp regexp) (setq regexp (format "%s" regexp))) + + + (unless infofile (error "Syntax: %s info info-file REGEXP" + erbn-char)) + (unless (stringp infofile) (setq infofile (format "%s" infofile))) + + (cond + ((ignore-errors (Info-goto-node + (concat "(" infofile ")" regexp))) + (concat "Press C-x C-e after: (info \"(" + infofile ")" Info-current-node + "\")") + ) + ((progn + (ignore-errors + (Info-goto-node (concat "(" infofile ")")) + (Info-top-node) + (Info-search regexp))) + (concat "Press C-x C-e after: (info \"(" + infofile + ")" Info-current-node + "\")")) + (t (error "Regexp or infofile not found in the file")))) + + +(defun fsi-locate-library (&optional arg &rest rest) + "REST WILL be ignored :-)" + (unless arg (error "Syntax: %s locate-library LIB" erbn-char)) + (unless (stringp arg) + (setq arg (format "%s" arg))) + (locate-library arg)) + + +(defun fsi-avg (&rest numbers) + (cond + ((null numbers) 'NaN) + (t (fs-// (apply '+ numbers) + (length numbers))))) + + +(defun fsi-dict (&optional word &rest ignore) + (unless word (error "Syntax: %s d[ict] word" erbn-char)) + (unless (stringp word) (setq word (format "%s" word))) + (fs-dictionary-search word)) + +(defalias 'fsi-dictionary 'fs-dict) + +(defun fsi-dictionary-search (word) + "lispy.. not for interface. " + (ignore-errors (kill-buffer "*Dictionary buffer*")) + (unless (stringp word) + (setq word (format "%s" word))) + (with-timeout + (fs-internal-dictionary-time "Dictionary--TimedOut") + (dictionary-search word) + (save-window-excursion + (switch-to-buffer "*Dictionary buffer*") + (goto-line 3) + (buffer-substring-no-properties (point) (point-max))))) + + + + + +;;8/10/00 +;;;###autoload +(defun fsi-// (&rest args) + "My sensible definition of /. +Does not say 4 / 3 = 0. Note: this usues equal and not equalp, the +last time i checked , equalp seemed to work as well.. " + (let ((aa (apply '/ args))) + (if (equal (car args) (apply '* aa (cdr args))) + aa + (apply '/ (cons (float (car args)) (cdr args)))))) + + +(defun fsi-channel-members-all () + (cond + ;; for earlier ERC. + ((boundp 'channel-members) channel-members) + ;; for later CVS versions of ERC. + (t nil))) + +(defun fsi-channel-members (&optional n m &rest args) + (when (stringp n) + (setq n (ignore-errors (erbn-read n)))) + (when (stringp m) + (setq m (ignore-errors (erbn-read m)))) + (unless (integerp n) (setq n 0)) + (unless (integerp m) (setq m nil)) + (subseq (fs-channel-members-all) n m)) + + +(defun fsi-length-channel-members (&rest args) + (cond + ;; for new erc versions + ((boundp erc-channel-users) + (hash-table-count erc-channel-users)) + (t (length (fs-channel-members-all))))) + + +(defalias 'fsi-number-channel-members 'fs-length-channel-members) + +(defun fsi-cto (&rest args) + (let* ((page (mapconcat (lambda (arg) (format "%s" arg)) + args "%20")) + (pg1 "http://cliki.tunes.org/") + ;;(pg2 "http://206.63.100.249/") + (pg3 + (erbutils-replace-strings-in-string + '("+" " " "\t") '("%2B" "%20" "%20") page))) + (format "%s%s" + pg1 pg3))) + + +;;; (defun fs-karma (&rest args) +;;; (let ((fir (first args))) +;;; (unless +;;; (and +;;; args +;;; fir) +;;; (error (format "Syntax: , karma ENTITY"))) +;;; (setq fir (downcase (format "%s" fir))) +;;; (let ((result (erbkarma fir))) +;;; (if result +;;; (format "%s's karma is %s" fir result) +;;; (format +;;; "No karma defined for %s, use ,ENTITY++ or ,karma-create" fir +;;; ))))) + +;;; (defvar erbn-karma-pt 10) + +;;; (defun fs-karma-increase (&optional arg points &rest ignore) +;;; (unless arg (error "Syntax: foo++ [&optional NUMBER]")) +;;; (when (stringp points) +;;; (setq points (ignore-errors (read points)))) +;;; (unless (and (integerp points) +;;; (<= (abs points) erbn-karma-pt)) +;;; (setq points erbn-karma-pt)) +;;; (setq arg (downcase (format "%s" arg))) +;;; (erbkarma-increase arg points)) + +(defun fsi-karma-increase (&rest args) + (if (car args) + (progn + + (ignore-errors (incf (gethash (intern (format "%s" (car args))) erbn-money) 1000)) + + + (format + "Noted, %s. One %s-point for %s!" + nick + (erbutils-random '("brownie" "karma" "wiki" "rms" "lispy")) + (car args)) + + + ) + ;;(error "Karma system is currently being reworked. ") + "")) + + + + +(defalias 'fs-karma-decrease 'fs-karma-increase) + +;;; (defun fs-karma-decrease (&optional arg points &rest ignore) +;;; (unless arg (error "Syntax: foo++ [&optional NUMBER]")) +;;; (when (stringp points) +;;; (setq points (ignore-errors (read points)))) +;;; (unless (and (integerp points) +;;; (<= (abs points) erbn-karma-pt)) +;;; (setq points erbn-karma-pt)) +;;; (setq arg (downcase (format "%s" arg))) +;;; (erbkarma-decrease arg points)) + + + +;;; (defun fs-karma (&optional foo) +;;; (if foo (setq foo (downcase (format "%s" foo)))) +;;; (erbkarma foo)) + +;;; (defalias 'fs-karma-best 'erbkarma-best) + + +(defalias 'fsi-ncm 'fs-length-channel-members) +(defun fs-superiorp (&rest args) + (erbutils-random '(t nil))) +(defun fs-sucksp (&rest args) + (erbutils-random '(t nil))) +(defun fs-bugp (&rest args) + (erbutils-random '(t nil))) + + +(defun fsi-country (&optional ct) + (unless ct (error "Syntax: %s country NM (example , country jp" erbn-char)) + (setq ct (format "%s" ct)) + (let ((addp (and (> (length ct) 1) + ;; does not start with . + (not (= (aref ct 0) 46))))) + (if addp (setq ct (concat "." ct)))) + (erbcountry (downcase ct))) + + + +(defun fsi-country-search (&rest names) + (unless names (error + "Syntax: %s country-search NM (example , country japa" erbn-char)) + (erbcountry-search + (mapconcat (lambda (arg) (format "%s" arg)) names " "))) + + +;;; 2003-02-09 T13:40:04-0500 (Sunday) D. Goel +(defun fsi-spook (&rest args) + (with-temp-buffer + (spook) + (goto-char (point-min)) + (forward-line 1) + (buffer-substring-no-properties + (progn (beginning-of-line 1) (point)) + (progn (end-of-line 1) (point))))) + + +(defun fs-explode (&rest args) + (let ((pieces + (erbutils-random '("a thousand" "a million" "a gazillion" + "aleph_2"))) + (watch + (erbutils-random '("" "you watch as " + "you run for cover as " + )))) + (eval + (erbutils-random + '((format "%s%s explodes into %s pieces!" + watch erbot-nick pieces) + (format "%s, with botheart broken into %s pieces, has left: \"Goodbye\"" + erbot-nick pieces)))))) + + + + +(defalias 'fs-die 'fs-explode) +(defalias 'fs-die! 'fs-explode) +(defalias 'fs-Die! 'fs-explode) +(defalias 'fs-Die 'fs-explode) +(defalias 'fs-DIE 'fs-explode) +(defalias 'fs-leave 'fs-explode) +(defalias 'fs-exit 'fs-explode) +(defalias 'fs-quit 'fs-explode) +(defalias 'fs-shut 'fs-explode) +(defalias 'fs-stfu 'fs-explode) +(defalias 'fs-STFU 'fs-explode) + + + +(defun fsi-morse (&rest str) + (apply 'erbutils-region-to-string 'morse-region str)) +(defun fsi-unmorse (&rest str) + (apply 'erbutils-region-to-string 'unmorse-region str)) + +(defun fsi-rot13 (&rest str) + (let (st) + (cond + ((= (length str) 1) + (setq st (format "%s" (first str)))) + (t (setq st (mapconcat + (lambda (a) (format "%s" a)) str " ")))) + (erbutils-rot13 st))) + +(defun fsi-studlify (&rest s) + (apply 'erbutils-region-to-string + (lambda (&rest args) + (ignore-errors (apply + 'studlify-region args))) + s)) + + +(defun fsi-h4x0r (&rest s) + (require 'h4x0r) + (funcall + 'h4x0r-string + (mapconcat + (lambda (a) (format "%s" a)) + s " "))) + + +(defalias 'fs-h4 'fs-h4x0r) +(defalias 'fs-h4 'fs-h4xor) +(defalias 'fs-h4 'fs-haxor) +(defalias 'fs-h4 'fs-hax0r) + +(defalias 'fs-l33t 'fs-h4x0r) +(defalias 'fs-leet 'fs-h4x0r) + +(defalias 'fs-stud 'fs-studlify) + +(defcustom fs-internal-studlify-maybe-weights + '(100 1) + "" + :group 'erbc) + +(defun fsi-studlify-maybe (&rest args) + (eval + (erbutils-random + '((erbutils-stringify args) + (apply 'fs-studlify args)) + fs-internal-studlify-maybe-weights + ))) + + +(defcustom fs-internal-h4x0r-maybe-weights + '(100 1) + "" + :group 'erbc) + +(defun fsi-h4x0r-maybe (&rest args) + (let* + ((aa (erbutils-stringify args)) + (bb + (ignore-errors + (eval + (erbutils-random + '(aa + (apply 'fs-h4x0r args)) + fs-internal-h4x0r-maybe-weights + ))))) + (or bb aa))) + + +(defalias 'fs-stud-maybe 'fs-studlify-maybe) + + +(defalias 'fs-studlify-word 'studlify-word) + + +(defun fsi-princ (a &rest ignore) + (princ a)) + + +(defun fsi-pray (&rest args) + (require 'faith) + (faith-quote)) + +(defalias 'fs-all-hail-emacs 'fs-pray) +(defalias 'fs-hail-emacs 'fs-pray) +(defalias 'fs-faith 'fs-pray) + +(erbutils-defalias-i '(faith-correct-string)) +(erbutils-defalias-i '(member)) + +(erbutils-defalias-i '(stringp consp symbolp numberp listp arrayp + boundp bufferp commandp consp endp + equalp evenp oddp facep fboundp + featurep functionp integerp keywordp + keymapp listp markerp minusp natnump + nlistp numberp overlayp plusp rationalp + sequencep subrp tailp timerp + typep vectorp windowp xemacsp zerop)) + + +(erbutils-defalias-i + '(char-to-string string-to-char string-to-int + string-to-number string-to-list + string-to-number-with-radix number-to-string + pp-to-string int-to-string number-to-string + prin1-to-string rational-to-string rational-to-float + radians-to-degrees rx-to-string degrees-to-radians)) + + + + + +(defun erbn-shell-test (string &optional substrings) + "Return t if any of the substrings matches string.. Used to weed +out harmful shell code.. + +See: http://www.w3.org/Security/faq/wwwsf4.html#CGI-Q7 + + +" + (unless substrings + (setq substrings (list " " "<" ">" "-" "`" "$" "=" ";" "&" "'" + "\\" "\"" "|" "*" "?" "~" "^" "(" ")" "[" + "]" "{" "}" "\n" "\r" ))) + (let ((found nil)) + (mapcar (lambda (arg) + (when (string-match (regexp-quote arg) string) + (setq found t))) + substrings) + found)) + +(defalias 'fsi-shell-test 'erbn-shell-test) + +(defcustom erbn-internal-web-page-time 10 + "" :group 'erbc) +(defcustom erbn-url-functions-p nil + "when true, enable url functions, provided that erbot-paranoid-p +allows us that. + +The reason you may not want to enable this function is that when you +fetch url's like http://205.188.215.230:8012 (icecast, etc. content), +url.el continues fetching that url forever (discovered by indio). The +bot times out, but url continues fetching it in the background, +slowing down your bot." + :group 'erbc) + + + +(defmacro erbn-with-web-page-buffer (site &rest body) + (let ((buffer (make-symbol "web-buffer"))) + `(progn + (unless (and (not erbot-paranoid-p) + erbn-url-functions-p) + (error "erbn-url-functions-p is disabled")) + (with-timeout (erbn-internal-web-page-time "HTTP time out") + (let ((,buffer (url-retrieve-synchronously ,site))) + (when (null ,buffer) + (error "Invalid URL %s" site)) + (save-excursion + (set-buffer ,buffer) + (goto-char (point-min)) + (prog1 + (progn + ,@body) + (kill-buffer ,buffer)))))))) + +(defun fsi-web-page-title (&optional site &rest args) + (unless site (error "Syntax: %s web-page-title SITE" erbn-char)) + (setq site (format "%s" site)) + (erbn-with-web-page-buffer site + (let* ((case-fold-search t) + (beg (search-forward "" nil t)) + (end (search-forward "" nil t))) + (concat "That page title is " + (if (and beg end) + (erbutils-cleanup-whitespace + (buffer-substring beg (- end 8))) + "not available"))))) + +(defun fsi-wserver (&optional site &rest args) + (unless site (error "Syntax: %s wserver SITE" erbn-char)) + (setq site (format "%s" site)) + (erbn-with-web-page-buffer site + (buffer-substring (point-min) + (or (search-forward "\n\n" nil t) + (point-max))))) + +(defalias 'fs-webserver 'fs-wserver) + +(defun fsi-web (&optional site &rest args) + (unless site (error "Syntax: %s web SITE" erbn-char)) + (setq site (format "%s" site)) + (erbn-with-web-page-buffer site + (shell-command-on-region (or (search-forward "\n\n" nil t) + (point-min)) + (point-max) + "w3m -dump -T text/html" t t) + (buffer-substring (point) (mark)))) + + +;;;###autoload +(defun fsi-length-load-history () + (interactive) + (message "%s%s%S" + (length load-history) + " ..." (mapcar 'car load-history))) + + +;(defun fsi-load-history () +; load-history) +;(defun fsi-load-history () +; load-history) + +(defalias 'fs-google: 'fs-google) + + + +(defconst fs-bunny 142857) +(defconst fs-pi pi) +(defconst fs-e e) +(defconst fs-euler e) +(defconst fs-emacs-version emacs-version) + +(defalias 'fsi-emacs-version 'emacs-version) +(defalias 'fsi-gnus-version 'gnus-version) + +;; the short aliases.. +(defalias 'fsi-a 'fs-apropos) +(defalias 'fs-da 'fs-apropos) +(defalias 'fsi-ac 'fs-apropos-command) +(defalias 'fsi-ad 'fs-apropos-documentation) +(defalias 'fsi-af 'fs-apropos-function) +(defalias 'fsi-av 'fs-apropos-variable) + +(defalias 'fsi-c 'fs-commands) +(defalias 'fsi-d 'fs-dict) +(defalias 'fsi-dict: 'fs-dict) + +(defalias 'fsi-dl 'fs-describe-literally) +(defalias 'fsi-doc 'fs-doctor ) +(defalias 'fsi-dkb 'fs-describe-key-briefly ) + +(defalias 'fsi-dk 'fs-describe-key) +(defalias 'fsi-dkf 'fs-describe-key-and-function) +(defalias 'fsi-dkl 'fs-describe-key-long) + +(defalias 'fs-lkgg 'fs-lookup-key-gnus-group) +(defalias 'fs-dkgg 'fs-lookup-key-gnus-group) + +(defalias 'fs-dkgs 'fs-lookup-key-gnus-summary) +(defalias 'fs-lkgs 'fs-lookup-key-gnus-summary) + +(defalias 'fs-lkm 'fs-lookup-key-message) +(defalias 'fs-lkm 'fs-lookup-key-message) + + +(defalias 'fsi-df 'fs-describe-function ) +(defalias 'fsi-cond 'cond) +(defalias 'fsi-if 'if) +(defalias 'fsi-when 'when) +(defalias 'fsi-dfl 'fs-describe-function-long ) +(defalias 'fsi-dv 'fs-describe-variable ) +(defalias 'fsi-ff 'fs-find-function) +(defalias 'fsi-ffb 'fs-find-function-briefly) +(defalias 'fsi-ffo 'fs-find-function-on-key) +(defalias 'fsi-ffob 'fs-find-function-on-key-briefly) +(defalias 'fsi-fv 'fs-find-variable) +(defalias 'fsi-fvb 'fs-find-variable-briefly) +(defalias 'fsi-? 'fs-help) +(defalias 'fs-32 'fs-help) +(defalias 'fsi-s 'fs-search) +(defalias 'fsi-sw 'fs-search-wide) +(defalias 'fsi-sws 'fs-search-wide-sensitive) +(defalias 'fsi-wi 'fs-where-is) +(defalias 'fs-wigg 'fs-where-is-gnus-group) +(defalias 'fs-wigs 'fs-where-is-gnus-summary) +(defalias 'fs-wim 'fs-where-is-message) +(defalias 'fs-dw 'fs-where-is) +;;(defalias 'fs-yo 'fs-hi) + +;; basic functions +(defalias 'fsi-lambda 'lambda) +(defalias 'fsi-length 'length) +(defalias 'fsi-sqrt 'sqrt) + +(defalias 'fsi-= '=) +(defalias 'fsi-/= '/=) +(defalias 'fsi-< '<) +(defalias 'fsi-> '>) +(defalias 'fsi-<= '<=) +(defalias 'fsi->= '>=) +(defalias 'fsi-not 'not) +(defalias 'fsi-and 'and) +(defalias 'fsi-or 'or) +(defalias 'fs-lart 'fs-flame) + +(defalias 'fsi-null 'null) +(defalias 'fsi-atom 'atom) +;;(defalias 'fsi-stringp 'stringp) +;;(defalias 'fsi-consp 'consp) + + + + +(defalias 'fsi-equal 'equal) +(defalias 'fsi-equalp 'equalp) +(defalias 'fsi-eql 'eql) +;; rr is used for russian-roulette now.. +;;(defalias 'fs-rr 'fs-replace-regexp) +(defalias 'fs-rs 'fs-replace-string) +(defalias 'fsi-+ '+) +(defalias 'fsi-- '-) +(defalias 'fsi-* '*) +(defalias 'fsi-/ '/) +(defalias 'fsi-less 'fs-more) +(defalias 'fsi-list 'list) +(defalias 'fsi-car 'car) +(defalias 'fs-ct 'erbccountry) +(defalias 'fsi-cdr 'cdr) +(defalias 'fsi-cons 'cons) +(defalias 'fsi-append 'append) +(defalias 'fsi-first 'first) +(defalias 'fsi-second 'second) +(defalias 'fsi-third 'third) +(defalias 'fsi-fourth 'fourth) +(defalias 'fsi-fifth 'fifth) +(defalias 'fsi-sixth 'sixth) +(defalias 'fsi-seventh 'seventh) +(defalias 'fsi-eighth 'eighth) +(defalias 'fsi-ninth 'ninth) +(defalias 'fsi-tenth 'tenth) +(defalias 'fsi-subseq 'subseq) +(defalias 'fsi-ceiling 'ceiling) +(defalias 'fsi-ceiling* 'ceiling*) +(defalias 'fsi-concatenate 'concatenate) +(defalias 'fsi-cos 'cos) +(defalias 'fsi-count-lines 'count-lines) + +(defalias 'fsi-last 'last) +(defalias 'fsi-llh 'fs-length-load-history) +(defalias 'fsi-error 'erbutils-error) +(defalias 'fsi-expt 'expt) +(defalias 'fsi-exp 'exp) +(defalias 'fsi-exchange-point-and-mark 'exchange-point-and-mark) +(defalias 'fs-rq 'fs-regexp-quote) +;; (defalias 'fs-function 'identity) + +(defalias 'fsi-identity 'identity) +(defalias 'fsi-nth 'nth) +(defalias 'fsi-nthcdr 'nthcdr) +(defalias 'fsi-random 'random) +(defalias 'fsi-random-choose 'erbutils-random) +(defalias 'fsi-remove 'remove) +(defalias 'fsi-replace-regexp-in-string 'replace-regexp-in-string) +(defalias 'fsi-replace-match 'replace-match) + +(defalias 'fsi-number-to-string 'number-to-string) +(defalias 'fsi-format 'format) +(erbutils-defalias-i '(format-time-string)) + +(defalias 'fsi-split-string 'split-string) +(defalias 'fsi-rm 'fs-forget) +(defalias 'fsi-progn 'progn) +(defalias 'fsi-ignore-errors 'ignore-errors) +(defalias 'fsi-lcm 'lcm) +(defalias 'fsi-let 'let) +(defalias 'fsi-let* 'let*) +(defalias 'fsi-ll 'fs-locate-library) +(defalias 'fsi-g 'fs-google) +(defalias 'fsi-gcd 'gcd) +(defalias 'fs-gd 'fs-google-deego) + +(defalias 'fsi-ge 'fs-google-emacswiki) +(defalias 'fs-gs 'fs-google-sl4) + +(defalias 'fs-gw 'fs-google-wikipedia) +(defalias 'fs-gi 'fs-google-imdb) +(defalias 'fs-gwe 'fs-google-wikipedia-english) +(defalias 'fs-gh 'fs-google-hurdwiki) +;;(defalias 'fs-gm 'fs-google-meatball) +(defalias 'fs-gnufans 'fs-google-gnufans-net) +(defalias 'fs-gg 'fs-google-gnufans-net) +(defalias 'fs-ggn 'fs-google-gnufans-net) +(defalias 'fs-ggo 'fs-google-gnufans-org) +(defalias 'fs-gn 'fs-google-nevadamissouri) +(defalias 'fs-gp 'fs-google-planetmath) +(defalias 'fs-gt 'fs-google-twiki) +;;(defalias 'fs-gu 'fs-google-usemod) + +(defalias 'fsi-mark 'mark) +(defalias 'fsi-point 'point) +(defalias 'fsi-pop-mark 'pop-mark) +(defalias 'fsi-push-mark 'push-mark) +(defalias 'fsi-floor 'floor) +(defalias 'fsi-floor* 'floor*) + +(defalias 'fsi-round 'round) +(defalias 'fsi-round* 'round*) + +(defalias 'fsi-setcar 'setcar) +(defalias 'fsi-setcdr 'setcdr) +(defalias 'fsi-sin 'sin) +(erbutils-defalias-i '(sleep-for sit-for)) +(defalias 'fsi-string 'string) + +(defalias 'fsi-string-as-multibyte 'string-as-multibyte) +(defalias 'fsi-string-bytes 'string-bytes) +(defalias 'fsi-string-equal 'string-equal) +(defalias 'fsi-string-key-binding 'string-key-binding) +(defalias 'fsi-string-lessp 'string-lessp) +(defalias 'fsi-string-make-multibyte 'string-make-multibyte) +(defalias 'fsi-string-make-unibyte 'string-make-unibyte) +(defalias 'fsi-string-to-char 'string-to-char) +(defalias 'fsi-string-to-int 'string-to-int) +(defalias 'fsi-string-to-list 'string-to-list) +(defalias 'fsi-string-to-number 'string-to-number) +(defalias 'fsi-string-to-sequence 'string-to-sequence) +(defalias 'fsi-string-to-syntax 'string-to-syntax) +(defalias 'fsi-string-to-vector 'string-to-vector) +(defalias 'fsi-string-width 'string-width) +(defalias 'fsi-symbol-file 'symbol-file) + +(defalias 'fsi-tan 'tan) +(defalias 'fsi-cos 'cos) +(defalias 'fsi-sin 'sin) +(defalias 'fsi-atan 'atan) +(defalias 'fsi-asin 'asin) +(defalias 'fsi-acos 'acos) +(defalias 'fsi-tanh 'tanh) + +(erbutils-defalias-i + '(timezone-world-timezones + timezone-months-assoc + timezone-make-date-arpa-standard timezone-make-date-sortable + timezone-make-arpa-date timezone-make-sortable-date + timezone-make-time-string timezone-parse-date timezone-parse-time + timezone-zone-to-minute timezone-time-from-absolute + timezone-time-zone-from-absolute timezone-fix-time + timezone-last-day-of-month timezone-leap-year-p timezone-day-number + timezone-absolute-from-gregorian)) + + +(defalias 'fsi-truncate 'truncate) + +(defalias 'fsi-truncate* 'truncate*) +(defalias 'fsi-truncate-string 'truncate-string) +(defalias 'fsi-truncate-string-to-width 'truncate-string-to-width) + + +(defalias 'fsi-erc-version 'erc-version) +(defalias 'fsi-sv 'erc-cmd-SV) +(defalias 'fsi-erc-cmd-SV 'erc-cmd-SV) +(defalias 'fsi-smv 'erc-cmd-SMV) +(defalias 'fsi-erc-cmd-SMV 'erc-cmd-SMV) +(defalias 'fsi-sm 'erc-cmd-SM) +(defalias 'fsi-cmd-SM 'erc-cmd-SM) +(defalias 'fsi-stringify 'erbutils-stringify) +;; (defalias 'fs-while 'while) + +;;;==================================================== + +;;;==================================================== +;; ERRORS: + +(defun fsi-load-library (&rest args) + (error "Use 'require instead. ")) + +(defalias 'fs-load 'fs-load-library) +(defalias 'fs-load-file 'fs-load-library) + + + +;; cl-extra.el + +(defalias 'fsi-equalp 'equalp) +;; done gcd +;; done lcm +(defalias 'fsi-isqrt 'isqrt) +(defalias 'fsi-floor* + 'floor* ) + +(defalias 'fsi-ceiling* +'ceiling* ) + +(defalias 'fsi-truncate* +'truncate*) + +;; done round* + +(defalias 'fsi-mod* + 'mod* ) + +(when (ignore-errors + (require 'geek)) + (erbutils-defalias-i '(geek-code))) + +(defalias 'fsi-rem* + 'rem* ) + +(erbutils-defalias-i + '(signum + random* + ;; yes? + make-random-state + random-state-p + + most-positive-float most-negative-float + least-positive-float least-negative-float + least-positive-normalized-float least-negative-normalized-float + float-epsilon float-negative-epsilon cl-float-limits ;; done subseq + concatenate revappend nreconc list-length tailp cl-copy-tree + copy-tree + ;;get* getf + ;;cl-set-getf cl-do-remf cl-remprop remprop + cl-make-hash-table + cl-hash-table-p cl-not-hash-table cl-hash-lookup cl-builtin-gethash + cl-builtin-remhash cl-builtin-clrhash cl-builtin-maphash cl-gethash + ;;cl-puthash cl-remhash cl-clrhash + ;;cl-maphash + cl-hash-table-count + cl-prettyprint cl-do-prettyprint cl-macroexpand-cmacs cl-closure-vars + cl-macroexpand-all cl-macroexpand-body cl-prettyexpand)) + + + +;; oct.el + +(ignore-errors (require 'oct)) + +(erbutils-defalias-i + + + '( + oct-zeros oct-ones oct-sum oct-size + oct-rows oct-columns oct-\.* + oct-add + oct-corr oct-complement oct-sumsq oct-mean + oct-sqrt oct-std oct-tanh oct-atanh) + "" "oct-") + +(erbutils-defalias-i '(oct-/ oct-+ )) +(erbutils-defalias-i '(lsh)) +(erbutils-defalias-i '(obarray)) + + +;; files.el +(erbutils-defalias-i + '(auto-mode-alist interpreter-mode-alist + directory-abbrev-alist)) + + +(erbutils-defalias-i '(load-history)) +(erbutils-defalias-i '(assoc)) +(erbutils-defalias-i '(eq)) +(erbutils-defalias-i '(message)) +(erbutils-defalias-i '(decf)) +(erbutils-defalias-i '(incf)) +(erbutils-defalias-i '(faith-quote)) +(erbutils-defalias-i '(zerop)) +;;(erbutils-defalias-i '(buffer-substring)) +(erbutils-defalias-i '(buffer-substring-no-properties)) +;;(erbutils-defalias-i '(buffer-string)) + +;; We define it to be no-properties, else people can (setq foo +;; (buffer-string)).. and cause a huge uservariables file.. + +(defun fsi-buffer-string (&rest args) + (buffer-substring-no-properties (point-min) (point-max))) + +(defalias 'fsi-buffer-substring 'buffer-substring-no-properties) + + +(erbutils-defalias-i + '(featurep feature-symbols feature-file features + + )) +(erbutils-defalias-i + '(minor-mode-alist minor-mode-map-alist + minor-mode-overriding-map-alist)) +(erbutils-defalias-vars '(major-mode)) + +;; from gnus-group.el + +(erbutils-defalias-vars '(gnus-group-mode-map)) +(erbutils-defalias-vars '(gnus-summary-mode-map)) +(erbutils-defalias-vars '(message-mode-map)) +(erbutils-defalias-vars '(text-mode-map)) +(erbutils-defalias-vars '(emacs-lisp-mode-map)) +(erbutils-defalias-vars '(lisp-mode-map)) + +(erbutils-defalias-i '(boundp fboundp)) +(erbutils-defalias-i '(lookup-key)) +(erbutils-defalias-i '(minor-mode-key-binding)) + +(erbutils-defalias-i '(where-is-internal)) +(erbutils-defalias-i '(% abs)) + +(erbutils-defalias-i '(cdr cddr car cadr cdar)) +(erbutils-defalias-i '(erc-channel-list)) + +(when (ignore-errors (require 'units)) + (erbutils-defalias-i '(units-version units-load-hook units-dat-file + units-buffer units-s-to-n + units-prefix-convert + units-si-prefix-list + units-si-short-prefix-list + units-convert-1 units-convert))) + + +(defvar erbn-nicks-dead nil) + +(defun erbn-mark-dead (&rest ignore) + (let ((ni (format "%s" erbn-nick))) + (unless (string= ni "nil") + (add-to-list 'erbn-nicks-dead (format "%s" erbn-nick))))) + + + +;; allow people to mark themselves dead :-) +(defalias 'fsi-mark-dead 'erbn-mark-dead) + +(defun erbn-unmark-dead (nick) + (setq erbn-nicks-dead (remove (format "%s" nick) erbn-nicks-dead))) + + + +(defun erbn-dead-check (&rest ignore) + (when (fsi-dead-p erbn-nick) + (error "I see dead people! + .... (but I don't talk to them!)"))) + +(defalias 'fsi-dead-check 'erbn-dead-check) + +(defun erbn-dead-p (&optional nick) + (unless nick (setq nick erbn-nick)) + (member (format "%s" nick) erbn-nicks-dead)) + +(defalias 'fsi-dead-p 'erbn-dead-p) + + + +(defun fs-give (&optional nini &rest stuff) + (unless nini (setq nini "self")) + (when (string= "me" nini) + (setq nini nick)) + (unless stuff (setq stuff '("a" "beer"))) + (format "/me gives %s %s" + nini + (mapconcat + (lambda (arg) (format "%s" arg)) + stuff " "))) + + +(defalias 'fs-hand 'fs-give) + +(erbutils-defalias-i + '(backward-kill-sentence + backward-sentence + flame-sentence flame-sentence-ify + flame-sentence-loop forward-sentence kill-sentence + mark-end-of-sentence sentence-at-point sentence-end + sentence-end-double-space sentence-end-without-period + transpose-sentences)) + +(defalias 'fsi-flatten 'erbutils-flatten) + + + +(erbutils-defalias-i '(log)) +(erbutils-defalias-i + '(most-positive-fixnum + most-negative-fixnum)) + + + +(erbutils-defalias-i + '( + regexp-opt + regexp-opt-depth + regexp-opt-group regexp-opt-charset)) + +(erbutils-defalias-i '(window-system)) + + +(defvar erbot-kbd-p nil + "Whether to enable kbd. + +Note that making this non-nil can lead to vector results. For +example, (kbd \"\"), (thanks to fledermaus).") + +(when (and + (not erbot-paranoid-p) + erbot-kbd-p + (erbutils-defalias-i + '(kbd read-kbd-macro)))) + +(defconst fs-t t + "As such, when we sandbox a lisp expression, t remains t, so this is +not needed. +However, inside macros like (cond (t....)), t becomes fs-t because +it occurs in an unusual place. this const should take care of it.. +Of course, this also opens the bot to some FUN user abuse, when they +setq fs-t to nil :-) ") + + +(defconst fs-nil nil + "See the doc of fs-t ") + + +(defun fsi-revive (&optional name &rest ignore) + (unless name (error "no one to revive")) + (setq name (format "%s" name)) + (let (ansstr) + (setq ansstr + (cond + ((string= name nick) + (concat "Thou idiot, " nick ", thou canst not revive thyself!")) + (t (concat + "/me sprinkles some " + (erbutils-random + '("clear" "murky" "boiling" "dark" "holy" "smelly")) + " potion on " + (format "%s" name) + " and utters some prayers. " + (erbutils-random + (list + (format "%s wakes up" name) + "Nothing happens." + (format "%s wakes up, all refreshed. " name) + (format "%s wakes up, all confused. " name) + )))))) + (when (string-match "wakes up" ansstr) + (erbn-unmark-dead name)) + ansstr)) + +;; this may be unsafe, remove it: +;; (defalias 'fs-sandbox-quoted 'erblisp-sandbox-quoted) +;; (defalias 'fs-sandbox-quoted-maybe 'erblisp-sandbox-quoted-maybe) +;; (defalias 'fs-sandbox 'erblisp-sandbox) + +(erbutils-defalias-i '(macroexpand)) + + +;;"/usr/share/emacs/21.2/lisp/emacs-lisp/pp.el" +(erbutils-defalias + '(pp-escape-newlines + pp-to-string + ;; pp pp-eval-expression + ;;pp-eval-last-sexp)) + )) + + +(erbutils-defalias-i '(string-match identity)) + +(erbutils-defalias-i '(parse-time-string)) + +(erbutils-defalias-i '(reverse)) + +(defun fsi-pp (object &rest ignore) + (pp object)) + + +(defmacro fs-privmsg (&rest args) + "This macro is carefully constructed so that one user cannot force a +query to another user. " + `(cond + ;; This can occur when you are requesting a parse.. + ((null erbn-nick) + (progn ,@args)) + (t + (progn + (setq erbn-tgt erbn-nick) + ;; If there isn't already a buffer, create one.. + (erbn-query erbn-nick) + ,@args)))) + +(defun erbn-query (qnick) + (save-excursion (erc-query qnick erbn-buffer))) + + + +(defun fsi-read-or-orig (arg) + " If string and can read, read, else return the arg. +Note: Used by fs-describe" + (cond + ((stringp arg) + (condition-case fs-tmp (erbn-read arg) + (error arg))) + (t arg))) + + +(defun erbn-read-from-string (str) + (let (str2) + (cond + ((stringp str) + (setq str2 (copy-sequence str)) + (set-text-properties 0 (length str2) nil str2) + (read-from-string str)) + (t (error "The bot will only read from strings. "))))) + + + +(defun erbn-read (str) + "Like read, but only from strings" + (car (erbn-read-from-string str))) + + +(defalias 'fsi-read 'erbn-read) +(defalias 'fsi-read-from-string 'erbn-read-from-string) + + +(erbutils-defalias-i + '(substring subr-arity subrp subseq + subst-char-in-string + subtract-time + time-subtract + time-add + date-to-time + time-to-seconds + time-less-p + seconds-to-time + days-to-time + time-since + subtract-time + date-to-day + days-between + date-leap-year-p + time-to-day-in-year time-to-days time-to-number-of-days + safe-date-to-time)) + + +(erbutils-defalias-i '(ignore)) + +(erbutils-defalias-i '(caar elt)) + +(provide 'erbc) +(run-hooks 'fs-after-load-hooks) + + + +;;; erbc.el ends here + diff --git a/elisp/erbot/erbc2.el b/elisp/erbot/erbc2.el new file mode 100644 index 0000000..2d84cbc --- /dev/null +++ b/elisp/erbot/erbc2.el @@ -0,0 +1,349 @@ +;;; erbc2.el --- mostly: special functions for erbc.el +;; Time-stamp: <2007-11-23 11:30:12 deego> +;; Copyright (C) 2003 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbc2.el +;; Package: erbc2 +;; Author: D. Goel +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + + + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + + +;; this gile contains yet more functions for fs-. The functions +;; here shall tend to be "specially defined" ones. + + +(defconst erbc2-version "0.0dev") +;;========================================== +;;; Requires: +(eval-when-compile (require 'cl)) + +;;; Code: + +(defcustom erbc2-before-load-hooks nil + "Hooks to run before loading erbc2." + :group 'erbc2) +(defcustom erbc2-after-load-hooks nil + "Hooks to run after loading erbc2." + :group 'erbc2) +(run-hooks 'erbc2-before-load-hooks) + + +;;; Real Code: + +(defvar erbn-while-max 10000) +(defvar erbn-while-ctr 0) +(defmacro fs-while (cond &rest body) + `(let + ((erbn-while-ctr 0)) + (while + ,cond + ;; this should enable the with-timeout checks.. + (sleep-for 0.01) + (if (> erbn-while-ctr erbn-while-max) + (error "Max while iterations exceeded: %S" + erbn-while-ctr)) + (incf erbn-while-ctr) + nil + ,@body))) + + + +(defmacro fs-dotimes (spec &rest body) + `(dotimes + ,spec + (sleep-for 0.01) + nil + ,@body)) + + + + +(defun fsi-set-difference (a b) + (set-difference a b)) + + +(defun fsi-pp (&optional foo &rest bar) + (pp foo)) + + + + + + +(defvar erbn-tmp-avar nil) +(defvar erbn-tmp-newargs nil) + +(defun erbn-apply-sandbox-args-old (args) + (cond + ((= (length args) 0) nil) + ((= (length args) 1) + (if (equal (caar args) 'quote) args + (mapcar 'erblisp-sandbox-quoted args))) + (t + (cons (erblisp-sandbox-quoted (car args)) + (erbn-apply-sandbox-args (cdr args)))))) +(defun erbn-apply-sandbox-args (args) + (cond + ((not (listp args)) + (erblisp-sandbox args)) + ((= (length args) 0) nil) + (t + (mapcar 'erblisp-sandbox args)))) + +(defvar erbn-apptmpa) +(defvar erbn-apptmpb) +(defvar erbn-apptmpc) +(defvar erbn-apptmpd) +(defvar erbn-tmpsymbolp) + + +(defmacro fs-apply (fcnsym &rest args) + "" + (when erbot-paranoid-p + (error "This function is disabled: erbot-paranoid-p")) + (unless fcnsym (error "No function to fs-apply!")) + (let (erbn-tmpargs + (erbn-tmplen (length args)) + erbn-tmpfirstargs + erbn-lastargs + erbn-tmpspecialp ;; denotes: NIL: no arguments at all. + erbn-tmpnoinitialp ;; denotes the case when the len args =1.. + ) + (cond + ((= (length args) 0) + (setq erbn-tmpspecialp t)) + ((= (length args) 1) + (setq erbn-tmpnoinitialp t))) + (cond + ((null args) + (setq erbn-tmpargs nil) + (setq erbn-tmplastargs nil) + (setq erbn-tmpspecialp nil)) + (t + (setq erbn-tmpargs + (append (subseq args 0 (- erbn-tmplen 1)))) + (setq erbn-tmplastargs + (first (last args))))) + (setq erbn-tmpargs (erbn-apply-sandbox-args erbn-tmpargs)) + (setq erbn-tmplastargs + (if (and (listp erbn-tmplastargs) + (equal (car erbn-tmplastargs) 'quote)) + erbn-tmplastargs + (erbn-apply-sandbox-args erbn-tmplastargs))) + (cond + ((listp fcnsym) + (setq fcnsym (erblisp-sandbox-quoted fcnsym))) + ((symbolp fcnsym) + (setq fcnsym (erblisp-sandbox-quoted fcnsym))) + (t (error "No clue how to apply that. "))) + (cond + (erbn-tmpspecialp + `(apply (erblisp-sandbox-quoted ,fcnsym) nil)) + (erbn-tmpnoinitialp + `(apply (erblisp-sandbox-quoted ,fcnsym) ,erbn-tmplastargs)) + (t + `(apply (erblisp-sandbox-quoted ,fcnsym) ,@erbn-tmpargs ,erbn-tmplastargs))))) + + +;; (defmacro fs-apply-old (fcnsym &rest args) +;; (error "This function is old.") +;; (unless fcnsym (error "No function to fs-apply!")) +;; (let (erbn-tmpargs +;; (erbn-tmplen (length args)) +;; erbn-tmpnewargs +;; ) +;; (cond +;; ((null args) +;; (setq erbn-tmpargs nil)) +;; (t +;; (setq erbn-tmpargs +;; (append (subseq args 0 (- erbn-tmplen 1)) +;; (last args))))) + +;; (let* ( +;; (erbn-tmp-newargs (erbn-apply-sandbox-args erbn-tmpargs)) +;; (erbn-tmp-newlen (length erbn-tmp-newargs))) +;; (cond +;; ((listp fcnsym) +;; (setq fcnsym (erblisp-sandbox-quoted fcnsym))) +;; ((symbolp fcnsym) +;; (setq fcnsym (erblisp-sandbox-quoted fcnsym))) +;; (t (error "No clue how to apply that. "))) +;; `(let ((erbn-tmp-avar ,fcnsym)) +;; (cond +;; ((symbolp erbn-tmp-avar) +;; (setq erbn-tmp-avar +;; (erblisp-sandbox-quoted erbn-tmp-avar))) +;; (t "nada")) +;; ,(if (= erbn-tmp-newlen 0) +;; `(apply erbn-tmp-avar nil) +;; `(apply erbn-tmp-avar ,@erbn-tmp-newargs nil)))))) + + +(defmacro fs-funcall (symbol &rest args) + `(fs-apply ,symbol ,@args nil)) + + + +;; hm, what is this? Was it me? silly me.. Why did I do this?? +(defalias 'fs-function 'identity) + +(defvar erbn-read-mode nil) +(defvar erbn-read-input nil) + +(defvar fs-internal-botread-prompt "Enter: ") + +(defun fsi-botread (&optional prompt) + (unless prompt (setq prompt fs-internal-botread-prompt)) + (ignore-errors + (erbot-reply (concat prompt "") proc nick tgt msg nil)) + (setq fs-internal-botread-prompt "Enter: ") + (setq erbn-read-mode t) + (while + (not erbn-read-input) + (sleep-for 0.1) + (sit-for 0.1)) + (let ((input erbn-read-input)) + (setq erbn-read-input nil) + (setq erbn-read-mode nil) + input)) + +(defun fsi-dun-mprinc (str) + (ignore-errors + (erbot-reply str proc nick tgt msg nil)) + (setq fs-internal-botread-prompt str)) + +(defun fsi-botread-feed-internal (str) + (setq erbn-read-input str) + (format + "Thanks for feeding the read-line. Msg obtained: %s" + str) + (setq erbn-read-mode nil) + str) + + + +;; i love this thing.. just no time to finish this yet.. + +;;; (defvar erbn-calsmart-tmp-expr nil) +;;; (defvar erbn-calsmart-tmp-exprb nil) +;;; (defvar erbn-calsmart-tmp-exprc nil) +;;; (defvar erbn-calsmart-tmp-error nil) + +;;; (defmacro fs-calsmart (&rest exprs) +;; "This will insert parenthesis appropriately, so you can type stuff +;; like , c + 2 3 4 - 3 4 * 3 4 5 (- 2 3) +;; and fsbot will try parenthesis at appropriate places until the +;; resulting expression makes sense .. " +;;; (require 'choose) +;;; (case (length exprs) +;;; ((1) `(car ,exprs)) +;;; (t +;;; `(choose-with +;;; (let* ( +;;; (erbn-calsmart-tmp-expr expr) +;;; (erbn-calsmart-tmp-exprb +;;; (erbn-calsmart-break-expr erbn-calsmart-tmp-expr)) +;;; (erbn-calsmart-tmp-exprc +;;; (choose (list erbn-calsmart-expr +;;; erbn-calsmart-tmp-exprb))) +;;; ) +;;; (cond +;;; (erbn-calsmart-tmp-exprb +;;; (condition-case erbn-calsmart-tmp-error +;;; (eval erbn-calsmart-tmp-exprc) +;;; (error (choose-fail)))) +;;; ;; couldn't break.. just do the normal thing. +;;; (t (eval erbn-calsmart-tmp-expr)))))))) + + +;;; (defun erbn-calsmart-break-expr (expr) +;;; "Expr is a list, which we intend to break. WE prefer breaking such +;;; that the broken function gets 2 arguments. +;;; We want to rewrap everything by erbn-calsmart, so things get broken +;;; further.. + + + +(defun fsi-bash-specific-quote (&optional number &rest ignored) + "NUMBER need not be jsut NUMBER. Any argument to +bash-specific-quotes, like random, should work." + (require 'bash-quotes) + (let (aa bb bashstr) + (unless number + (setq number "random")) + (bash-specific-quote (format "%s" number)) + (sit-for 5) + ;; (let (aa bb) + ;; (set-buffer "*bash*") + ;; (goto-char (point-min)) + ;; (setq aa (search-forward "--------" nil t)) + ;; (forward-line 1) + ;; (setq aa (search-forward "--------" nil t)) + ;; (forward-line 1) + ;; (setq aa (point)) + ;; (setq bb (search-forward "--------" nil t)) + ;; (forward-line -1) + ;; (setq bb (point)) + ;; (when (and aa bb) + ;; (buffer-substring-no-properties aa bb))) + (set-buffer "*bash*") + (setq bashstr (erbutils-buffer-string)) + (with-temp-buffer + (insert bashstr) + (goto-char (point-min)) + (setq aa (search-forward-regexp "^--------" nil t)) + (forward-line 1) + (setq aa (search-forward-regexp "^--------" nil t)) + (forward-line 1) + (beginning-of-line) + (setq aa (point)) + (setq bb (search-forward-regexp "^--------" nil t)) + (forward-line -1) + (end-of-line) + (setq bb (point)) + (if (and aa bb) + (buffer-substring-no-properties aa bb) + "No result")))) + +(defalias 'fsi-bsc 'fs-bash-specific-quote) +(defalias 'fs-bash-quote 'fs-bash-specific-quote) +(defalias 'fs-bash.org 'fs-bash-specific-quote) +;;(defalias 'fs-bash 'fs-bash-specific-quote) + + + + + + +(defalias 'fsi-lexical-let 'lexical-let) +(provide 'erbc2) +(run-hooks 'erbc2-after-load-hooks) + + + +;;; erbc2.el ends here diff --git a/elisp/erbot/erbc3.el b/elisp/erbot/erbc3.el new file mode 100644 index 0000000..071345e --- /dev/null +++ b/elisp/erbot/erbc3.el @@ -0,0 +1,290 @@ +;;; erbc3.el ---erbot lisp stuff which should be PERSISTENT ACROSS SESSIONS. +;; Time-stamp: <2007-11-23 11:30:12 deego> +;; Copyright (C) 2003 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbc3.el +;; Package: erbc3 +;; Author: D. Goel +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; For latest version: + +(defconst erbc3-home-page + "http://gnufans.net/~deego") + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +(defconst erbc3-version "0.dev") +(defun erbc3-version (&optional arg) + "Display erbc3's version string. +With prefix ARG, insert version string into current buffer at point." + (interactive "P") + (if arg + (insert (message "erbc3 version %s" erbc3-version)) + (message "erbc3 version %s" erbc3-version))) + +;;========================================== +;;; Requires: +(eval-when-compile (require 'cl)) + +;;; Code: + +(defgroup erbc3 nil + "The group erbc3." + :group 'applications) +(defcustom erbc3-before-load-hook nil + "Hook to run before loading erbc3." + :group 'erbc3) +(defcustom erbc3-after-load-hook nil + "Hook to run after loading erbc3." + :group 'erbc3) +(run-hooks 'erbc3-before-load-hook) + + +;;; Real Code: +;; pf stands for persistent functions. +;; pv stands for persistent variables. + +(defvar erbn-pf-file "~/public_html/data/userfunctions.el") +(defvar erbn-pv-file "~/public_html/data/uservariables.el") + +(defun fsi-pfpv-load () + (fsi-pf-load) + (fsi-pv-load)) + +(defun fsi-pf-load () + (if (file-exists-p erbn-pf-file) + (fsi-ignore-errors-else-string (load erbn-pf-file)) + (message "File does not exist: %s" erbn-pf-file))) + + + +(defun fsi-pv-load () + (when (file-exists-p erbn-pv-file) + (ignore-errors (load erbn-pv-file)))) + + + +(defun fsi-user-function-p (fcn) + (member + fcn + (erbutils-functions-in-file erbn-pf-file))) + + +(defun erbn-create-defun-new (sexps body) + (cons body sexps)) + +(defun erbn-create-defun-overwrite (sexps body fcn) + (cons body + (remove + (first (member-if + (lambda (arg) (equal (second arg) fcn)) + sexps)) + sexps))) + + + +(defun erbn-write-sexps-to-file (file sexps &optional backup-rarity) + (unless backup-rarity (setq backup-rarity 1)) + (when (zerop (random backup-rarity)) (erbutils-mkback-maybe file)) + + (find-file file) + (widen) + (delete-region (point-min) (point-max)) + (insert "\n\n\n") + (insert + (mapconcat + (lambda (arg) (pp-to-string arg)) sexps "\n\n\n")) + (insert "\n\n\n") + (save-buffer)) + +(defvar erbn-tmp-sexps) +(defvar erbn-tmp-newbody) + + + + + + + + + +(defun fsi-pv-get-variables-values () + (let + ((vars + (apropos-internal "^fs-" 'boundp))) + (mapcar + (lambda (v) + `(ignore-errors + (defvar ,v + (quote ,(eval v))))) + vars))) + + +(defcustom fs-pv-save-rarity 100000 + "if this is 1000, then file is saved one in a thousand times... ") + +;;;###autoload +(defun fsi-pv-save () + (interactive) + (erbn-write-sexps-to-file + erbn-pv-file + (fs-pv-get-variables-values) 1000)) + ;; this should lead to a few saves every day... not too many, one hopes.. +;;1000)) + + + +(defun erbn-readonly-check (sym) + (if (get sym 'readonly) + (error "The symbol %S can't be redefined or set! It is read-only!" + sym))) + + + + +(defmacro fsi-defun (fcn args &rest body) + + ;; the given fcn icould be a number or string, in which + ;; case sandboxing won't touch it, so we need to override that case. + (let ((docp nil)) + (unless + (and (listp body) + (> (length body) 0)) + (error "Function body should have a length of 1 or more")) + (unless (and (symbolp fcn) (not (fsi-constant-object-p fcn))) + (error "Defun symbols only! :P")) + ;; doc string exists, and is followed by more stuff.. + (when (and (> (length body) 1) + (stringp (first body))) + (setq docp t)) + (erbn-readonly-check fcn) + + (erbn-write-sexps-to-file + erbn-pf-file + (erbn-create-defun-overwrite + (erbutils-file-sexps erbn-pf-file) + (if docp + + (cons 'defun + (cons fcn + (cons args + (cons + (first body) + (cons + `(erblisp-check-args ,@args) + (cons + '(sit-for 0) + (cdr body))))))) + + (cons 'defun + (cons fcn + (cons args + (cons + `(erblisp-check-args ,@args) + (cons + '(sit-for 0) + body)))))) + + fcn)) + (fsi-pf-load) + `(quote ,fcn))) + + + + + +(defun fsi-defalias (sym1 sym2) + (eval `(fsi-defun + ,(erblisp-sandbox-quoted sym1) (&rest fs-bar) + (fs-apply (quote ,(erblisp-sandbox-quoted sym2)) fs-bar)))) + + + + + + + + + + +(defun fsi-makunbound (&optional sym) + (unless sym (error "Syntax: , (makunbound 'symbol)")) + (setq sym + (erblisp-sandbox sym)) + (makunbound sym)) + + +(defun fsi-fmakunbound (&optional sym) + (unless sym (error "Syntax: , (fmakunbound 'symbol)")) + + (setq sym + (erblisp-sandbox sym)) + + (erbn-readonly-check sym) + + (let + ;; this is to be returned.. + ((result (fmakunbound sym)) + (sexps (erbutils-file-sexps erbn-pf-file))) + + ;; now we want to remove any definition of sym from the user + ;; file: + + (erbn-write-sexps-to-file + erbn-pf-file + (remove + (first + (member-if + (lambda (arg) (equal (second arg) sym)) + sexps)) + sexps)) + (fsi-pf-load) + result)) + + +(defvar erbn-tmpsetq nil) + +(defmacro fsi-setq (&rest args) + `(let ((erbn-tmpsetq + (setq ,@args))) + (fs-pv-save) + erbn-tmpsetq)) + + + +(defun fsi-constant-object-p (object) + "If the object is a symbol like nil or t, a symbol that cannot be +redefunned, return true. " + (or (member object (list nil t)) + (keywordp object))) + + + +(erbutils-defalias-i '(type-of)) + +(provide 'erbc3) +(run-hooks 'erbc3-after-load-hook) + + + +;;; erbc3.el ends here diff --git a/elisp/erbot/erbc4.el b/elisp/erbot/erbc4.el new file mode 100644 index 0000000..240b9a5 --- /dev/null +++ b/elisp/erbot/erbc4.el @@ -0,0 +1,333 @@ +;;; erbc4.el --- Russian Roulette +;; Time-stamp: <2007-11-23 11:30:12 deego> +;; Copyright (C) 2003 Taylor Campbell +;; Emacs Lisp Archive entry +;; Filename: erbc4.el +;; Package: erbc4 +;; Author: Taylor Campbell +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; For latest version: + +(defconst erbc4-home-page + "http://gnufans.net/~deego") + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +(defconst erbc4-version "0.0dev") + + +;;========================================== +;;; Requires: +(eval-when-compile (require 'cl)) + +;;; Code: + +;;; Real Code: + +(defvar erbn-RR-empty-bets (make-hash-table)) +(defvar erbn-RR-bullet-bets (make-hash-table)) +(defvar erbn-money (make-hash-table)) + +(defun erbn-move-money (nick table1 table2 amount) + (let ((cell1 (gethash nick table1)) + (cell2 (gethash nick table2))) + (if cell1 + (decf (gethash nick table1) amount) + (setf (gethash nick table1) (- amount))) + (if cell2 + (incf (gethash nick table2) amount) + (setf (gethash nick table2) amount)))) + +(defun fs-bet (&rest args) + (let ((nick (intern nick))) + (cond ((null args) + (let ((empty-bet (gethash nick erbn-RR-empty-bets)) + (bullet-bet (gethash nick erbn-RR-bullet-bets))) + (cond (empty-bet + (format "%s has bet %d on there being no bullet." + nick empty-bet)) + (bullet-bet + (format "%s has bet %d on there being a bullet." + nick bullet-bet)) + (t (format "%s has not bet anything." + nick))))) + ((and (consp args) + (consp (cdr args)) + (null (cddr args)) + (cond ((symbolp (car args)) + (numberp (cadr args))) + ((numberp (car args)) + (symbolp (cadr args))) + (t nil))) + (let* ((on-what (if (symbolp (car args)) (car args) (cadr args))) + (how-much (if (numberp (car args)) (car args) (cadr args))) + (_ (if (< how-much 0) + (error "You can't bet negative amounts, moron."))) + (table (case on-what + ((empty no-bullet click) erbn-RR-empty-bets) + ((bullet bang blam) erbn-RR-bullet-bets) + (t (error "Invalid bet type" on-what)))) + (not-table (if (eq table erbn-RR-bullet-bets) + erbn-RR-empty-bets + erbn-RR-bullet-bets))) + (cond ((gethash nick not-table) + (format "%s: Idiot, you can can only bet on one outcome." + nick on-what)) + ((< (or (gethash nick erbn-money) 0) how-much) + (format + "%s: Fool, you can't bet more than you've got (%d)." + nick (or (gethash nick erbn-money) 0))) + (t (erbn-move-money nick erbn-money table how-much) + (format "%s has bet %d GEMs so far on a %s." + nick + (gethash nick table) + on-what))))) + (t (error "Invalid arguments to bet" args))))) + +(defun fs-lend (arg1 arg2 &rest ignored) + (let* ((to-whom (if (symbolp arg1) arg1 arg2)) + (how-much (if (numberp arg2) arg2 arg1)) + (nick (intern nick)) + (money (gethash nick erbn-money))) + (if (equal nick to-whom) + (error "You can't lend money to yourself, knave!")) + (if (> how-much money) + (error "You can't lend more than you have" nick how-much)) + (if (< how-much 0) + (error "You can't lend negative amounts.")) + (decf (gethash nick erbn-money) how-much) + (if (gethash to-whom erbn-money) + (incf (gethash to-whom erbn-money) how-much) + (setf (gethash to-whom erbn-money) how-much)) + (format "%s has lent %d GEMs to %s; %s now has %d GEMs and %s %d." + nick + how-much + to-whom + + nick + (gethash nick erbn-money) + + to-whom + (gethash to-whom erbn-money)))) + +(defun erbn-keyshash (hash-table) + (let ((keys nil)) + (maphash (lambda (key val) (push key keys)) hash-table) + keys)) + +(defun erbn-valueshash (hash-table) + (let ((values nil)) + (maphash (lambda (key val) (push val values)) hash-table) + values)) + +(defun erbn-all-money (nick) + (let ((amount + (apply #'+ + (mapcar (lambda (table) + (or (gethash nick table) 0)) + (list erbn-money + erbn-RR-bullet-bets + erbn-RR-empty-bets))))) + (mapc (lambda (table) + (remhash nick table)) + (list erbn-money + erbn-RR-bullet-bets + erbn-RR-empty-bets)) + amount)) + +(defun fs-money (&optional maybe-nick) + (let* ((local-nick (or (and maybe-nick + (if (symbolp maybe-nick) + maybe-nick + (intern maybe-nick))) + (intern nick))) + (amount (or (gethash local-nick erbn-money) 0))) + (if maybe-nick + (format "%s has %d GEMs." + local-nick + amount) + (format "You've got %d GEMs, %s." + amount + nick)))) + +(defun erbn-percent (m n) + (/ (* (float m) 100.0) (float n))) + +(defun erbn-unpercent (m n) + (/ (* (float m) (float n)) 100.0)) + + +(defun erbn-distribute (maybe-dead-nick winning-table losing-table) + (prog1 (cond ((and (= (hash-table-count winning-table) 0) + (not maybe-dead-nick)) + ;; Give the losers their money back. + (maphash (lambda (nick amount) + (incf (gethash nick erbn-money) amount)) + losing-table)) + ((and (= (hash-table-count losing-table) 0) + (not maybe-dead-nick)) + ;; Give the winners their money back. + (maphash (lambda (nick amount) + (incf (gethash nick erbn-money) amount)) + winning-table)) + (t (let* ((winning-bets (erbn-valueshash winning-table)) + (total-win-bets (apply #'+ winning-bets)) + (total-money + (apply #'+ + (if maybe-dead-nick + (erbn-all-money maybe-dead-nick) + 0) + total-win-bets + (erbn-valueshash losing-table)))) + (maphash (lambda (nick amount) + (let* ((percent + (erbn-percent amount total-win-bets)) + (unpercent + (erbn-unpercent percent + total-money))) + (incf (gethash nick erbn-money) + (round unpercent)))) + winning-table)))) + (clrhash winning-table) + (clrhash losing-table))) + +(defvar erbn-chamber (random 6)) + +;; Someone tell Riastradh if this is a good way to do this... (the +;; click and bang messages) +(defvar erbn-rr-bangs + (list (lambda () + (concat "/me blows " nick "'s cerebellum all over " + tgt "... *BANG*")) + (lambda () + (concat "/me blows " nick "'s brains all over " + tgt "... *BANG* ...reloading.")) + (lambda () + (concat nick " has to pick his brains off of the walls and " + " floor... *BANG*")) + (lambda () + (concat nick "'s luck just ran out... *BANG*")) + (lambda () + (concat "/me offers " nick " a cold " + (fs-describe "beer-data") + " before giving him the fatal blow... *KABLAM*")))) +(defvar erbn-rr-clicks + (list (lambda () + (concat "/me points the gnu and " nick + " trembles... *CLICK*")) + (lambda () + (concat nick " shudders as the great and powerful fsbot aims " + "the all-powerful barrel of the gnu... *CLICK*")) + (lambda () + (concat nick " is one lucky punk... *CLICK*")) + (lambda () + (concat "/me picks up the gnu and points it at " nick + "'s head... *CLICK*")) + (lambda () + (concat "/me raises the gnu to " nick "'s head and " nick + " trembles as the *CLICK* sounds.")))) + +(defun erbn-rr-bang () + (fs-kick erbn-nick "*KABLAM!* Goop from your head dribbles.") + (funcall (fs-random-choose erbn-rr-bangs))) + +(defun erbn-rr-click () + (funcall (fs-random-choose erbn-rr-clicks))) + +(defun fs-add-bang (&rest bangs) + (setq erbn-rr-bangs + (concat bangs erbn-rr-bangs))) +(defun fs-add-click (&rest clicks) + (setq erbn-rr-clicks + (concat clicks erbn-rr-clicks))) + +(defun fs-russian-roulette (&rest ignored) + ;; Don't let them do that, because it confuses the money distribution. + (if (gethash (intern nick) erbn-RR-bullet-bets) + (error (concat nick ": Idiot, don't bet on your own death.")) + (if (= erbn-chamber 5) + (progn + (setq erbn-chamber (random 6)) + (erbn-distribute (intern nick) + erbn-RR-bullet-bets + erbn-RR-empty-bets) + (erbn-rr-bang)) + (incf erbn-chamber) + (erbn-distribute nil + erbn-RR-empty-bets + erbn-RR-bullet-bets) + (erbn-rr-click)))) + +(defvar erbn-auth-bankers + '(deego Riastradh fledermaus _sprintf)) + + +(defun erbn-add-banker (nick &rest ignored) + (add-to-list 'erbn-auth-bankers nick)) + +(defun fs-auth-bankerp () + (and (member (intern nick) erbn-auth-bankers) t)) + +(defun fs-reset-money (&rest ignored) + (if (not (fs-auth-bankerp)) + (error (concat nick ": You can't reset the money."))) + (clrhash erbn-money) + (clrhash erbn-RR-empty-bets) + (clrhash erbn-RR-bullet-bets) + "Money cleared.") + +(defun fs-init-money (init &rest nicks) + (if (not (fs-auth-bankerp)) + (error (concat nick ": you can't initialize the money"))) + (mapc (lambda (nick) + (setf (gethash (if (stringp nick) + (intern nick) + nick) + erbn-money) + init)) + nicks) + "Money initialized.") + +;; (defvar erbn-rr-bullet (random 6)) + +;; (defun fs-russian-roulette (&rest ignore) +;; (if (>= erbn-rr-bullet 5) +;; (progn +;; (setq erbn-rr-bullet (random 6)) +;; (fs-describe "rr-bang-kick")) +;; (incf erbn-rr-bullet) (fs-describe "rr-click"))) + +(defalias 'fsi-RR 'fs-russian-roulette) +(defalias 'fsi-rr 'fs-russian-roulette) + + +(defun fsi-kick (&optional reason &rest ignore) + (erbn-mark-dead) + (erc-cmd-KICK erbn-nick (when reason (format "%s" reason)))) + +(provide 'erbc4) +(run-hooks 'erbc4-after-load-hook) + + + +;;; erbc4.el ends here diff --git a/elisp/erbot/erbc5.el b/elisp/erbot/erbc5.el new file mode 100644 index 0000000..6c663aa --- /dev/null +++ b/elisp/erbot/erbc5.el @@ -0,0 +1,192 @@ +;;; erbc5.el --- continuation of erbc.el +;; Time-stamp: <2007-11-23 11:30:12 deego> +;; Copyright (C) 2003 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbc5.el +;; Package: erbc5 +;; Author: D. Goel +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; For latest version: + +(defconst erbc5-home-page + "http://gnufans.net/~deego") + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + + +(defconst erbc5-version "0.0dev") +;;========================================== +;;; Requires: +(eval-when-compile (require 'cl)) + +;;; Code: + +(defgroup erbc5 nil + "The group erbc5." + :group 'applications) +(defcustom erbc5-before-load-hook nil + "Hook to run before loading erbc5." + :group 'erbc5) +(defcustom erbc5-after-load-hook nil + "Hook to run after loading erbc5." + :group 'erbc5) +(run-hooks 'erbc5-before-load-hook) + +(defcustom erbc5-verbosity 0 + "How verbose to be. +Once you are experienced with this lib, 0 is the recommended +value. Values between -90 to +90 are \"sane\". The +rest are for debugging." + :type 'integer + :group 'erbc5) +(defcustom erbc5-interactivity 0 + "How interactive to be. +Once you are experienced with this lib, 0 is the recommended +value. Values between -90 and +90 are \"sane\". The rest are for +debugging." + :type 'integer + :group 'erbc5) +(defcustom erbc5-y-or-n-p-function 'erbc5-y-or-n-p + "Function to use for interactivity-dependent `y-or-n-p'. +Format same as that of `erbc5-y-or-n-p'." + :type 'function + :group 'erbc5) +(defcustom erbc5-n-or-y-p-function 'erbc5-y-or-n-p + "Function to use for interactivity-dependent `n-or-y-p'. +Format same as that of `erbc5-n-or-y-p'." + :type 'function + :group 'erbc5) +(defun erbc5-message (points &rest args) + "Signal message, depending on POINTS anderbc5-verbosity. +ARGS are passed to `message'." + (unless (minusp (+ points erbc5-verbosity)) + (apply #'message args))) +(defun erbc5-y-or-n-p (add prompt) + "Query or assume t, based on `erbc5-interactivity'. +ADD is added to `erbc5-interactivity' to decide whether +to query using PROMPT, or just return t." + (if (minusp (+ add erbc5-interactivity)) + t + (funcall 'y-or-n-p prompt))) +(defun erbc5-n-or-y-p (add prompt) + "Query or assume t, based on `erbc5-interactivity'. +ADD is added to `erbc5-interactivity' to decide whether +to query using PROMPT, or just return t." + (if (minusp (+ add erbc5-interactivity)) + nil + (funcall 'y-or-n-p prompt))) + +;;; Real Code: + +(defalias 'fsi-listp-proper 'erbutils-listp-proper) +(erbutils-defalias-i '(upcase downcase capitalize upcase-initials)) + + + +(ignore-errors (require 'calc)) + +(defvar erbn-calc-time 3) +(defcustom erbn-calc-p nil + "Enable this variable at your own risk. +Enabling this means that fsbot will do calc operations, but those have +no timeout build in... leading to DOS attacks. ") + + +(defun fsi-calc-eval (&optional str) + " +Note that even though this function has a with-timeout built into it, +that doesn't save us from a DOS attack..since emacs polls only when +waiting for user input.. + +which is why turned off by default. + +" + (unless (and erbn-calc-p (not erbot-paranoid-p)) + (error "Sorry, but i am a bot! not a calc!")) + (unless str (error "Eval what?")) + (unless (stringp str) + (setq str (format "%s" str))) + (with-timeout + (erbn-calc-time "That's WAY too much math for me!") + (calc-eval str))) + +(defalias 'fs-calc 'fs-calc-eval) + +(erbutils-defalias '(process-list)) +(defalias 'fs-list-processes 'fs-process-list) + +(defcustom erbn-sregex-p nil + "Nil by default for safety. Enable to permit fs-sregex. +I think it is safe, but not 100% sure, so disabled by default. --DG" + ) + + +(defun fsi-sreg (&rest args) + (format "%S" + (apply 'fs-sregex args))) + + +(defun fsi-sregex (&rest args) + (cond + ((and erbn-sregex-p (not erbot-paranoid-p)) + (apply 'sregex args)) + (t + (error "sregexp is disabled in this bot. ")))) + + + +(defmacro fsi-ignore-errors-else-string (&rest body) + "Like ignore-errors, but tells and returns the erros. +\(Improved for me by Kalle on 7/3/01:)" + (let ((err (gensym))) + `(condition-case ,err (progn ,@body) + (error + (let + ((str + (message "IGNORED ERROR: %s" (error-message-string ,err)))) + (ding t) + (ding t) + (ding t) + (sit-for 1) + str))))) + + +;; more math functions +(erbutils-defalias-i '(mod)) +;; these from cl-extra +(erbutils-defalias-i '(isqrt floor* ceiling* round* mod* rem* signum + random*)) + + +(erbutils-defalias-i '(symbol-name)) + + + +(provide 'erbc5) +(run-hooks 'erbc5-after-load-hook) + + + +;;; erbc5.el ends here diff --git a/elisp/erbot/erbc6.el b/elisp/erbot/erbc6.el new file mode 100644 index 0000000..0de78e3 --- /dev/null +++ b/elisp/erbot/erbc6.el @@ -0,0 +1,75 @@ +;;; erbc6.el --- fsbot functions contributed by freenode users, esp. #emacsers. +;; Time-stamp: <2007-11-23 11:30:12 deego> +;; Copyright (C) 2003 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbc6.el +;; Package: erbc6 +;; Author: D. Goel and #emacsers +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; For latest version: +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;;; Real Code: + + + +(defun fs-m8b nil + (fs-random-choose + '("Yes" "No" "Definitely" "Of course not!" "Highly likely." + "Ask yourself, d\o you really want to know?" + "I'm telling you, you don't want to know." "mu!"))) + + + +(defun fsi-C-h (sym &rest thing) + " +;;; 2003-08-16 T15:19:00-0400 (Saturday) D. Goel +Coded by bojohann on #emacs." + (cond + ((eq sym 'f) + (apply 'fs-df thing)) + ((eq sym 'k) + (apply 'fs-dk thing)) + ((eq sym 'c) + (apply 'fs-describe-key-briefly thing)) + ((eq sym 'w) + (apply 'fs-dw thing)) + ((eq sym 'v) + (apply 'fs-dv thing)))) + + +(defun fsi-wtf-is (&optional term &rest args) + (unless term + (error "Syntax: wtf TERM")) + (require 'wtf) + (funcall 'wtf-is (format "%s" term))) + + + +(defalias 'fsi-wtf 'fsi-wtf-is) + + +(provide 'erbc6) +(run-hooks 'erbc6-after-load-hook) + + + +;;; erbc6.el ends here diff --git a/elisp/erbot/erbcompat.el b/elisp/erbot/erbcompat.el new file mode 100644 index 0000000..8e9e518 --- /dev/null +++ b/elisp/erbot/erbcompat.el @@ -0,0 +1,55 @@ +;;; erbcompat.el --- Erbot GNU Emacs/XEmacs compatibility issues +;; Time-stamp: <2007-11-23 11:30:12 deego> +;; Copyright (C) 2004 S. Freundt +;; Emacs Lisp Archive entry +;; Filename: erbcompat.el +;; Package: erbot +;; Author: Sebastian Freundt +;; Version: NA +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +(defvar erbot-on-xemacs-p nil + "Whether erbot is run on xemacs.") + +(setq erbot-on-xemacs-p + (and (string-match "xemacs" emacs-version) t)) + + +;;; local-variable-p stuff +(or (and erbot-on-xemacs-p + (defun erbcompat-local-variable-p (variable &optional buffer) + "Just in compatibilty to GNU Emacs" + (local-variable-p variable (or buffer (current-buffer))))) + (defalias 'erbcompat-local-variable-p 'local-variable-p)) + +;;; help-xref stuff +(and erbot-on-xemacs-p + (defun help-setup-xref (&rest ignore)) + (defun help-xref-button (&rest ignore)) + (defun help-xref-stack (&rest ignore))) + + +(provide 'erbcompat) + +;; erbcompat.el ends here diff --git a/elisp/erbot/erbcountry.el b/elisp/erbot/erbcountry.el new file mode 100644 index 0000000..3e2d717 --- /dev/null +++ b/elisp/erbot/erbcountry.el @@ -0,0 +1,518 @@ +;; 2003-02-13 T13:36:31-0500 (Thursday) D. Goel +;; countries list is copied from http://www.iana.org/cctld/cctld-whois.htm +;;; Real Code: + +(defvar erbcountry-list) +(defvar erbcountry-string) + + +;; This is an incomplete, old list. We don't want to spend time to +;; create it again, so we will simply dump the contents into +;; erbcountry-string and use a routine to alistify that. +(unless (boundp 'erbcountry-list) + (setq erbcountry-list + '( + (".ac" "Ascension Island") + (".ad" "Andorra") + (".ae" "United Arab Emirates") + (".af" "Afghanistan") + (".ag" "Antigua and Barbuda") + (".ai" "Anguilla") + (".al" "Albania") + (".am" "Armenia") + (".an" "Netherlands Antilles") + (".ao" "Angola") + (".aq" "Antarctica") + (".ar" "Argentina") + (".as" "American Samoa") + (".at" "Austria") + (".au" "Australia") + (".aw" "Aruba") + (".az" "Azerbaijan") + (".ba" "Bosnia and Herzegovina") + (".bb" "Barbados") + (".bd" "Bangladesh") + (".be" "Belgium") + (".bf" "Burkina Faso") + (".bg" "Bulgaria") + (".bh" "Bahrain") + (".bi" "Burundi") + (".bj" "Benin") + (".bm" "Bermuda") + (".bn" "Brunei Darussalam") + (".bo" "Bolivia") + (".br" "Brazil") + (".bs" "Bahamas") + (".bt" "Bhutan") + (".bv" "Bouvet Island") + (".bw" "Botswana") + (".by" "Belarus") + (".bz" "Belize") + (".ca" "Canada") + (".cc" "Cocos (Keeling) Islands") + (".cd" "Congo, Democratic Republic of the") + (".cf" "Central African Republic") + (".cg" "Congo, Republic of") + (".ch" "Switzerland") + (".ci" "Cote d'Ivoire") + (".ck" "Cook Islands") + (".cl" "Chile") + (".cm" "Cameroon") + (".cn" "China") + (".co" "Colombia") + (".cr" "Costa Rica") + (".cu" "Cuba") + (".cv" "Cap Verde") + (".cx" "Christmas Island") + (".cy" "Cyprus") + (".cz" "Czech Republic") + (".de" "Germany") + (".dj" "Djibouti") + (".dk" "Denmark") + (".dm" "Dominica") + (".do" "Dominican Republic") + (".dz" "Algeria") + (".ec" "Ecuador") + (".ee" "Estonia") + (".eg" "Egypt") + (".eh" "Western Sahara") + (".er" "Eritrea") + (".es" "Spain") + (".et" "Ethiopia") + (".fi" "Finland") + (".fj" "Fiji") + (".fk" "Falkland Islands (Malvina)") + (".fm" "Micronesia, Federal State of") + (".fo" "Faroe Islands") + (".fr" "France") + (".ga" "Gabon") + (".gd" "Grenada") + (".ge" "Georgia") + (".gf" "French Guiana") + (".gg" "Guernsey") + (".gh" "Ghana") + (".gi" "Gibraltar") + (".gl" "Greenland") + (".gm" "Gambia") + (".gn" "Guinea") + (".gp" "Guadeloupe") + (".gq" "Equatorial Guinea") + (".gr" "Greece") + (".gs" "South Georgia and the South Sandwich Islands") + (".gt" "Guatemala") + (".gu" "Guam") + (".gw" "Guinea-Bissau") + (".gy" "Guyana") + (".hk" "Hong Kong") + (".hm" "Heard and McDonald Islands") + (".hn" "Honduras") + (".hr" "Croatia/Hrvatska") + (".ht" "Haiti") + (".hu" "Hungary") + (".id" "Indonesia") + (".ie" "Ireland") + (".il" "Israel") + (".im" "Isle of Man") + (".in" "India") + (".io" "British Indian Ocean Territory") + (".iq" "Iraq") + (".ir" "Iran (Islamic Republic of)") + (".is" "Iceland") + (".it" "Italy") + (".je" "Jersey") + (".jm" "Jamaica") + (".jo" "Jordan") + (".jp" "Japan") + (".ke" "Kenya") + (".kg" "Kyrgyzstan") + (".kh" "Cambodia") + (".ki" "Kiribati") + (".km" "Comoros") + (".kn" "Saint Kitts and Nevis") + (".kp" "Korea, Democratic People's Republic") + (".kr" "Korea, Republic of") + (".kw" "Kuwait") + (".ky" "Cayman Islands") + (".kz" "Kazakhstan") + (".la" "Lao People's Democratic Republic") + (".lb" "Lebanon") + (".lc" "Saint Lucia") + (".li" "Liechtenstein") + (".lk" "Sri Lanka") + (".lr" "Liberia") + (".ls" "Lesotho") + (".lt" "Lithuania") + (".lu" "Luxembourg") + (".lv" "Latvia") + (".ly" "Libyan Arab Jamahiriya") + (".ma" "Morocco") + (".mc" "Monaco") + (".md" "Moldova, Republic of") + (".mg" "Madagascar") + (".mh" "Marshall Islands") + (".mk" "Macedonia, Former Yugoslav Republic") + (".ml" "Mali") + (".mm" "Myanmar") + (".mn" "Mongolia") + (".mo" "Macau") + (".mp" "Northern Mariana Islands") + (".mq" "Martinique") + (".mr" "Mauritania") + (".ms" "Montserrat") + (".mt" "Malta") + (".mu" "Mauritius") + (".mv" "Maldives") + (".mw" "Malawi") + (".mx" "Mexico") + (".my" "Malaysia") + (".mz" "Mozambique") + (".na" "Namibia") + (".nc" "New Caledonia") + (".ne" "Niger") + (".nf" "Norfolk Island") + (".ng" "Nigeria") + (".ni" "Nicaragua") + (".nl" "Netherlands") + (".no" "Norway") + (".np" "Nepal") + (".nr" "Nauru") + (".nu" "Niue") + (".nz" "New Zealand") + (".om" "Oman") + (".pa" "Panama") + (".pe" "Peru") + (".pf" "French Polynesia") + (".pg" "Papua New Guinea") + (".ph" "Philippines") + (".pk" "Pakistan") + (".pl" "Poland") + (".pm" "St. Pierre and Miquelon") + (".pn" "Pitcairn Island") + (".pr" "Puerto Rico") + (".ps" "Palestinian Territories") + (".pt" "Portugal") + (".pw" "Palau") + (".py" "Paraguay") + (".qa" "Qatar") + (".re" "Reunion Island") + (".ro" "Romania") + (".ru" "Russian Federation") + (".rw" "Rwanda") + (".sa" "Saudi Arabia") + (".sb" "Solomon Islands") + (".sc" "Seychelles") + (".sd" "Sudan") + (".se" "Sweden") + (".sg" "Singapore") + (".sh" "St. Helena") + (".si" "Slovenia") + (".sj" "Svalbard and Jan Mayen Islands") + (".sk" "Slovak Republic") + (".sl" "Sierra Leone") + (".sm" "San Marino") + (".sn" "Senegal") + (".so" "Somalia") + (".sr" "Suriname") + (".st" "Sao Tome and Principe") + (".sv" "El Salvador") + (".sy" "Syrian Arab Republic") + (".sz" "Swaziland") + (".tc" "Turks and Caicos Islands") + (".td" "Chad") + (".tf" "French Southern Territories") + (".tg" "Togo") + (".th" "Thaila") + (".us" "USA") + + + ))) + + + +(unless (boundp 'erbcountry-string) + (setq erbcountry-string + ".ac Ascension Island +.ad Andorra +.ae United Arab Emirates +.af Afghanistan +.ag Antigua and Barbuda +.ai Anguilla +.al Albania +.am Armenia +.an Netherlands Antilles +.ao Angola +.aq Antarctica +.ar Argentina +.as American Samoa +.at Austria +.au Australia +.aw Aruba +.ax Aland Islands +.az Azerbaijan +.ba Bosnia and Herzegovina +.bb Barbados +.bd Bangladesh +.be Belgium +.bf Burkina Faso +.bg Bulgaria +.bh Bahrain +.bi Burundi +.bj Benin +.bm Bermuda +.bn Brunei Darussalam +.bo Bolivia +.br Brazil +.bs Bahamas +.bt Bhutan +.bv Bouvet Island +.bw Botswana +.by Belarus +.bz Belize +.ca Canada +.cc Cocos (Keeling) Islands +.cd Congo, The Democratic Republic of the +.cf Central African Republic +.cg Congo, Republic of +.ch Switzerland +.ci Cote d'Ivoire +.ck Cook Islands +.cl Chile +.cm Cameroon +.cn China +.co Colombia +.cr Costa Rica +.cs Serbia and Montenegro +.cu Cuba +.cv Cape Verde +.cx Christmas Island +.cy Cyprus +.cz Czech Republic +.de Germany +.dj Djibouti +.dk Denmark +.dm Dominica +.do Dominican Republic +.dz Algeria +.ec Ecuador +.ee Estonia +.eg Egypt +.eh Western Sahara +.er Eritrea +.es Spain +.et Ethiopia +.fi Finland +.fj Fiji +.fk Falkland Islands (Malvinas) +.fm Micronesia, Federal State of +.fo Faroe Islands +.fr France +.ga Gabon +.gb United Kingdom +.gd Grenada +.ge Georgia +.gf French Guiana +.gg Guernsey +.gh Ghana +.gi Gibraltar +.gl Greenland +.gm Gambia +.gn Guinea +.gp Guadeloupe +.gq Equatorial Guinea +.gr Greece +.gs South Georgia and the South Sandwich Islands +.gt Guatemala +.gu Guam +.gw Guinea-Bissau +.gy Guyana +.hk Hong Kong +.hm Heard and McDonald Islands +.hn Honduras +.hr Croatia/Hrvatska +.ht Haiti +.hu Hungary +.id Indonesia +.ie Ireland +.il Israel +.im Isle of Man +.in India +.io British Indian Ocean Territory +.iq Iraq +.ir Iran, Islamic Republic of +.is Iceland +.it Italy +.je Jersey +.jm Jamaica +.jo Jordan +.jp Japan +.ke Kenya +.kg Kyrgyzstan +.kh Cambodia +.ki Kiribati +.km Comoros +.kn Saint Kitts and Nevis +.kp Korea, Democratic People's Republic +.kr Korea, Republic of +.kw Kuwait +.ky Cayman Islands +.kz Kazakhstan +.la Lao People's Democratic Republic +.lb Lebanon +.lc Saint Lucia +.li Liechtenstein +.lk Sri Lanka +.lr Liberia +.ls Lesotho +.lt Lithuania +.lu Luxembourg +.lv Latvia +.ly Libyan Arab Jamahiriya +.ma Morocco +.mc Monaco +.md Moldova, Republic of +.mg Madagascar +.mh Marshall Islands +.mk Macedonia, The Former Yugoslav Republic of +.ml Mali +.mm Myanmar +.mn Mongolia +.mo Macau +.mp Northern Mariana Islands +.mq Martinique +.mr Mauritania +.ms Montserrat +.mt Malta +.mu Mauritius +.mv Maldives +.mw Malawi +.mx Mexico +.my Malaysia +.mz Mozambique +.na Namibia +.nc New Caledonia +.ne Niger +.nf Norfolk Island +.ng Nigeria +.ni Nicaragua +.nl Netherlands +.no Norway +.np Nepal +.nr Nauru +.nu Niue +.nz New Zealand +.om Oman +.pa Panama +.pe Peru +.pf French Polynesia +.pg Papua New Guinea +.ph Philippines +.pk Pakistan +.pl Poland +.pm Saint Pierre and Miquelon +.pn Pitcairn Island +.pr Puerto Rico +.ps Palestinian Territory, Occupied +.pt Portugal +.pw Palau +.py Paraguay +.qa Qatar +.re Reunion Island +.ro Romania +.ru Russian Federation +.rw Rwanda +.sa Saudi Arabia +.sb Solomon Islands +.sc Seychelles +.sd Sudan +.se Sweden +.sg Singapore +.sh Saint Helena +.si Slovenia +.sj Svalbard and Jan Mayen Islands +.sk Slovak Republic +.sl Sierra Leone +.sm San Marino +.sn Senegal +.so Somalia +.sr Suriname +.st Sao Tome and Principe +.sv El Salvador +.sy Syrian Arab Republic +.sz Swaziland +.tc Turks and Caicos Islands +.td Chad +.tf French Southern Territories +.tg Togo +.th Thailand +.tj Tajikistan +.tk Tokelau +.tl Timor-Leste +.tm Turkmenistan +.tn Tunisia +.to Tonga +.tp East Timor +.tr Turkey +.tt Trinidad and Tobago +.tv Tuvalu +.tw Taiwan +.tz Tanzania +.ua Ukraine +.ug Uganda +.uk United Kingdom +.um United States Minor Outlying Islands +.us United States +.uy Uruguay +.uz Uzbekistan +.va Holy See (Vatican City State) +.vc Saint Vincent and the Grenadines +.ve Venezuela +.vg Virgin Islands, British +.vi Virgin Islands, U.S. +.vn Vietnam +.vu Vanuatu +.wf Wallis and Futuna Islands +.ws Western Samoa +.ye Yemen +.yt Mayotte +.yu Yugoslavia +.za South Africa +.zm Zambia +.zw Zimbabwe")) + + + +(defun erbcountry-create-list () + "Creates erbcountry-list from erbcountry-string. " + (let ((strlist (split-string erbcountry-string "[\n]+")) splits dom name) + (dolist (str strlist) + (setq splits (split-string str "[ \t\n]+")) + (setq dom (first splits)) + (setq name (mapconcat 'identity (cdr splits) " ")) + (add-to-list 'erbcountry-list (list dom name))))) + +(erbcountry-create-list) + + + +(defun erbcountry-search (name) + (with-temp-buffer + (insert erbcountry-string) + (goto-char (point-min)) + (if (search-forward name nil t) + (buffer-substring-no-properties (line-beginning-position) + (line-end-position)) + (error "No match. ")))) + + +(defun erbcountry-lookup (ct) + ;;(unless (stringp ct) (setq ct (format "%s" ct))) + (second (assoc ct erbcountry-list))) + +(defalias 'erbcountry 'erbcountry-lookup) + +(provide 'erbcountry) + + + + +;;; erbcountry.el ends here diff --git a/elisp/erbot/erbcspecial.el b/elisp/erbot/erbcspecial.el new file mode 100644 index 0000000..a4d54f7 --- /dev/null +++ b/elisp/erbot/erbcspecial.el @@ -0,0 +1,148 @@ +;;; erbcspecial.el --- Special/dangerous implementation functions. +;; Many fs-functions can simply be defined in terms of other +;; fs-functions (and always should be!, for security.) +;; This file is for the remaining few, that can't be. +;; Thus, CODE IN THIS FILE SHOULD BE CONSTRUCTED VERY CAREFULLY. +1 +;; Time-stamp: <2007-11-23 11:30:12 deego> +;; Copyright (C) 2004 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbcspecial.el +;; Package: erbcspecial +;; Author: D. Goel +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; For latest version: + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + +(defconst erbcspecial-version "0.0dev") + +;;========================================== +;;; Requires: +(eval-when-compile (require 'cl)) + + +;;; Code: + +(defun erbn-special-quote-function (fcn) + (cond + ((symbolp fcn) + (erblisp-sandbox-quoted fcn)) + ((and (listp fcn) + (equal (first fcn) 'lambda) + fcn)) + ;; notice the recursion below: + ((listp fcn) (erbn-special-quote-function (fs-eval fcn))) + (t (error "Cannot apply this as a function!")))) + + +;; (defun fs-mapcar-old (sym seq) +;; "only symbols allowed at this time. " +;; (unless (symbolp sym) +;; (error "Function argument to mapcar for this bot can only be a symbol.")) +;; (setq sym (erblisp-sandbox-quoted sym)) +;; ;; everything should already be boxquoted.. cool +;; (mapcar sym seq)) + +(defun fsi-mapcar (fcn ls) + (apply 'mapcar + (erbn-special-quote-function fcn) + ls nil)) + + + + +;; (defun fs-mapc (sym seq) +;; "only symbols allowed at this time. " +;; (unless (symbolp sym) +;; (error "Function argument to mapcar for this bot can only be a symbol.")) +;; (setq sym (erblisp-sandbox-quoted-ensure-symbol sym)) +;; ;; everything should already be boxquoted.. cool +;; (mapc sym seq)) + + + + +(defun fsi-mapc (fcn ls) + (apply 'mapc + (erbn-special-quote-function fcn) + ls nil)) + + + +(defun fsi-mapconcat (fcn ls sep) + (apply 'mapconcat + (erbn-special-quote-function fcn) + ls sep nil)) + + + + + + + +(defun fsi-maplist (fcn ls &rest args) + (require 'cl) + (apply 'maplist + (erbn-special-quote-function fcn) + ls args)) + + + +(defun fsi-mapl (fcn ls &rest args) + (require 'cl) + (apply 'mapl + (erbn-special-quote-function fcn) + ls args)) + +(defun fsi-mapcar* (fcn ls &rest args) + (require 'cl) + (apply 'mapcar* + (erbn-special-quote-function fcn) + ls args)) + + + +(defun fsi-mapcon (fcn ls &rest args) + (require 'cl) + (apply 'mapcon + (erbn-special-quote-function fcn) + ls args)) + + + + + + +;;; Real Code: + + + +(provide 'erbcspecial) +(run-hooks 'erbcspecial-after-load-hook) + + + +;;; erbcspecial.el ends here diff --git a/elisp/erbot/erbdata.el b/elisp/erbot/erbdata.el new file mode 100644 index 0000000..406b86b --- /dev/null +++ b/elisp/erbot/erbdata.el @@ -0,0 +1,66 @@ +;;; erbdata.el --- +;; Time-stamp: <2007-11-23 11:30:12 deego> +;; Copyright (C) 2002 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbdata.el +;; Package: erbdata +;; Author: D. Goel +;; Version: 0.0DEV +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + + +(defvar erbdata-home-page + "http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot") + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + +(defvar erbdata-version "0.0dev") + +;;========================================== +;;; Code: + +(defgroup erbdata nil + "The group erbdata" + :group 'applications) +(defcustom erbdata-before-load-hooks nil "" :group 'erbdata) +(defcustom erbdata-after-load-hooks nil "" :group 'erbdata) +(run-hooks 'erbdata-before-load-hooks) + +(defvar erbdata-flames + '( + "%s: Are you smoking crack?" + "%s: Is it larger than a breadbox?" + "What are you smoking, %s?" + "You are confused, but this is your normal state. " + )) + + + + + +(provide 'erbdata) +(run-hooks 'erbdata-after-load-hooks) + + + +;;; erbdata.el ends here diff --git a/elisp/erbot/erbedit.el b/elisp/erbot/erbedit.el new file mode 100644 index 0000000..8831444 --- /dev/null +++ b/elisp/erbot/erbedit.el @@ -0,0 +1,150 @@ +;;; erbedit.el --- quicker operator editing of bots' bbdb +;; Time-stamp: <2007-11-23 11:30:12 deego> +;; Copyright (C) 2003 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbedit.el +;; Package: erbedit +;; Author: D. Goel +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; For latest version: + +(defconst erbedit-home-page + "http://gnufans.net/~deego") + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + + +(defconst erbedit-version "0.0dev") + +;;========================================== +;;; Requires: +(eval-when-compile (require 'cl)) + +;;; Code: + +(defgroup erbedit nil + "The group erbedit." + :group 'applications) +(defcustom erbedit-before-load-hook nil + "Hook to run before loading erbedit." + :group 'erbedit) +(defcustom erbedit-after-load-hook nil + "Hook to run after loading erbedit." + :group 'erbedit) +(run-hooks 'erbedit-before-load-hook) + +(defcustom erbedit-verbosity 0 + "How verbose to be. +Once you are experienced with this lib, 0 is the recommended +value. Values between -90 to +90 are \"sane\". The +rest are for debugging." + :type 'integer + :group 'erbedit) +(defcustom erbedit-interactivity 0 + "How interactive to be. +Once you are experienced with this lib, 0 is the recommended +value. Values between -90 and +90 are \"sane\". The rest are for +debugging." + :type 'integer + :group 'erbedit) +(defcustom erbedit-y-or-n-p-function 'erbedit-y-or-n-p + "Function to use for interactivity-dependent `y-or-n-p'. +Format same as that of `erbedit-y-or-n-p'." + :type 'function + :group 'erbedit) +(defcustom erbedit-n-or-y-p-function 'erbedit-y-or-n-p + "Function to use for interactivity-dependent `n-or-y-p'. +Format same as that of `erbedit-n-or-y-p'." + :type 'function + :group 'erbedit) +(defun erbedit-message (points &rest args) + "Signal message, depending on POINTS anderbedit-verbosity. +ARGS are passed to `message'." + (unless (minusp (+ points erbedit-verbosity)) + (apply #'message args))) +(defun erbedit-y-or-n-p (add prompt) + "Query or assume t, based on `erbedit-interactivity'. +ADD is added to `erbedit-interactivity' to decide whether +to query using PROMPT, or just return t." + (if (minusp (+ add erbedit-interactivity)) + t + (funcall 'y-or-n-p prompt))) +(defun erbedit-n-or-y-p (add prompt) + "Query or assume t, based on `erbedit-interactivity'. +ADD is added to `erbedit-interactivity' to decide whether +to query using PROMPT, or just return t." + (if (minusp (+ add erbedit-interactivity)) + nil + (funcall 'y-or-n-p prompt))) + +;;; Real Code: + + + +(provide 'erbedit) +(run-hooks 'erbedit-after-load-hook) + + +(defun erbedit-replace-string (from to) + "Like fs-replace-string, but acts across the entire bbdb" + "Forget all terms containing occurrence of regexp REG. + +REMINDER: DO NOT FORGET TO exclude terms like fsbot hbot erbot deego +Deepak (author) in prevent-reg +when using this command. +\\(bot\\|emacs\\|deego\\|goel\\|deepak\\|alex\\|bpt\\|oddmuse\\|iam\\) +.. for example.. +" + (let* + ((lenterms + (fs-search-basic (regexp-quote from) + nil nil 'describe)) + (len (first lenterms)) + (terms (second lenterms))) + (cond + ((= len 0 ) (message "No terms. ")) + (t + (when (y-or-n-p (format "Act on these %S terms? " len)) + (erbedit-replace-string-slowly terms from to)))))) + +(defun erbedit-replace-string-slowly (terms from to) + (let + ((len (length terms)) + (ctr 0) + thisterm + skipp + notes + ) + (while terms + (setq thisterm (car terms) terms (cdr terms)) + (setq ctr (+ ctr 1)) + (message "Acting on term %S of %S: %S" ctr len thisterm) + (sleep-for 0.1) + (fs-replace-string from to thisterm "all") + (message "Acting on term %S of %S: %S ... done" ctr len thisterm) + (sleep-for 0.1) + ))) + + + +;;; erbedit.el ends here diff --git a/elisp/erbot/erbeng.el b/elisp/erbot/erbeng.el new file mode 100644 index 0000000..7aa7aa3 --- /dev/null +++ b/elisp/erbot/erbeng.el @@ -0,0 +1,300 @@ +;;; erbeng.el --- +;; Time-stamp: <2007-11-23 11:30:11 deego> +;; Copyright (C) 2002 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbeng.el +;; Package: erbeng +;; Author: D. Goel +;; Version: 0.0DEV +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + + +(defvar erbeng-home-page + "http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot") + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + + +(defvar erbeng-version "0.0dev") + +;;========================================== +;;; Code: + +(require 'cl) +(defgroup erbeng nil + "The group erbeng" + :group 'applications) +(defcustom erbeng-before-load-hooks nil "" :group 'erbeng) +(defcustom erbeng-after-load-hooks nil "" :group 'erbeng) + +(defcustom erbeng-reply-timeout 20 + "Time after which the bot times out...") + +(run-hooks 'erbeng-before-load-hooks) + + + + + +(defvar erbeng-msg nil ) +(defvar erbeng-proc nil) +(defvar erbeng-nick nil) +(defvar erbeng-tgt nil) +(defvar erbeng-localp nil) +(defvar erbeng-userinfo nil) + + +(defvar erbot-show-type-p t + "Whether to show type of non-string objects when replying... + +The old behavior was equivalent to having this as nil.") + + +;;;###autoload +(defun erbeng-main (msg proc nick tgt localp userinfo) + " The main function: Takes a line of message and generates a reply to it. +The result is a string. If the result is 'noreply, that means: Do NOT reply... +The last field localp is here for historical reasons, and shall be +ignored... + +One very important criterion here should be: + +erbot should learn to avoid runaway talks with other bots. For this +reason: + + [a] it should take a break every now and then, say: a 1-minute break +after every 1000 commands. It should probably announce its break. +AND/OR + [b] It should learn to reply only 99 out of 100 times. Moreover, +before it shuts up, it should let any humans know what it is doing. +tgt, nick and sspec will probably mostly remain unused... + +proc == name of the process in the channel +tgt == channel +nick == who from +userninfo looks like (\"deego\" \"user\" \"24-197......\") +sspec looks like: [\"PRIVMSG\" +\"deego!~user@24-197-159-102.charterga.net\" \"#testopn\" \"hi erbot\" \nil +nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil +nil nil\ nil nil nil nil nil nil nil nil] + +" + (let* + ( + (erbeng-nick nick) + (erbeng-msg msg) + (erbeng-proc proc) + (erbeng-tgt tgt) + (erbeng-localp localp) + (erbeng-userinfo userinfo) + (fs-found-query-p nil) + (fs-internal-addressedatlast nil) + (fs-internal-message-sans-bot-name fs-internal-message-sans-bot-name) + (fsi-prestring fsi-prestring) + tmpvar + parsed-msg rep + (fs-msg fs-msg) + (fs-msglist fs-msglist) + (fs-msgsansbot fs-msgsansbot) + (fs-msglistsansbot fs-msglistsansbot) + (fs-lispa fs-lispa) + (fs-lispb fs-lispb) + (fs-lispc fs-lispc) + (fs-lispd fs-lispd) + (fs-lispe fs-lispe) + ) + ;;(concat nick ": " "/leave Test.. one big big test...") + ;;(erbutils-ignore-errors + + ;; this can also modify fs-found-query + (setq parsed-msg + (or (condition-case tmpvar + (fs-parse msg proc nick tgt localp userinfo) + (error + ;;"(error \"Please supply a completed lisp form\")" + ;; Note that this could be bad: + ;; someone may not even be referring to the bot here: + (if + fs-internal-parse-error-p + (format "(error %S )" + (error-message-string tmpvar)) + (format "(fs-english-only %S)" msg)) + + )) + (and (featurep 'erbmsg) + erbot-erbmsg-p + (erbmsg-parse msg proc nick tgt localp userinfo)))) + + ;;(if (and (first parsed-msg) erbot-nick + ;; (string= (first parsed-msg) + ;; erbot-nick)) + ;; parsed-msg will never be null if the msg was addressed to fsbot.. + (if + parsed-msg + (progn + (setq rep + ;;(erbutils-ignore-errors + (with-timeout + (erbeng-reply-timeout + "overall timeout") + (erbutils-ignore-errors + (erbeng-get-reply parsed-msg proc nick tgt ))) + ) + (cond + ((string= "noreply" (format "%s" rep)) 'noreply) + ((and (stringp rep) (not (equal rep ""))) (format "%s%s" + fsi-prestring + rep)) + (t + (cond + (erbot-show-type-p + (format "%s%S ..(%s)" fsi-prestring rep (type-of rep))) + ((equal "" rep) "EMPTY STRING RETURNED") + (t (format "%s%S" fsi-prestring rep)))))) + + 'noreply))) + + + +(defun erbeng-lisp-object-p (msg) + (setq msg (ignore-errors (erbn-read msg))) + (and (listp msg) + (let ((fir (format "%s" (first msg)))) + (or + (string-match "concat" fir) + (string-match "regexp-quote" fir) + ;; want to allow fs-rq to show the regexp without quoting.. + ;;(string-match "fs-rq" fir) + )))) + + + +;(defun erbeng-init-parse (msg) +; (if (equal 0 (string-match "," msg)) +; (setq msg (concat "erbot " +; (substring msg 1 (length msg))))) +; (let ((spl (split-string msg))) +; (if (> (length spl) 0) +; (erbeng-init-frob-split-string spl) +; nil)));;; + +;;; ;(defun erbeng-init-frob-split-string (spl) +;;; ; "spl is the split string ..;;;; + +;;; ;now, we do not need to split wrt commas... in fact, that will be +;;; ;dangerous, and can spoil the meanings of commas inside parse +;;; ;commands...;; + +;;; ;converts all accepted formats to look like this: + + +;;; ; \(\"erbot\" \"foo\" \"bar\"\) + +;;; ;" +;;; ; (let* ((do-again t) +;;; ; (new-spl +;;; ; (cond +;;; ; ;; , foo bar +;;; ;((string= (first spl) ",") +;;; (cons erbot-nick (cdr spl))) +;;; ((equal +;;; (string-match "," (first spl)) 0) +;;; (cons erbot-nick +;;; (append (split-string (first spl) ",") +;;; (cdr spl)))) +;;; ((equal +;;; ;; erbot: +;;; (string-match (concat erbot-nick ":") (first spl)) 0) +;;; (append (split-string (first spl) ":") +;;; (cdr spl))) +;;; ((equal +;;; ;; fdbot, +;;; (string-match (concat erbot-nick ",") (first spl)) 0) +;;; (append (split-string (first spl) ",") +;;; (cdr spl))) +;;; (t (progn (setq do-again nil) spl))))) +;;; (if do-again +;;; (erbeng-init-frob-split-string new-spl) +;;; ;; removed the extra "" etc. and all , ; erc. etc. +;;; (split-string +;;; (mapconcat 'identity +;;; new-spl " ") +;;; "[ \f\t\n\r\v,;]+")))) + + + + +(defun erbeng-get-reply (msg &optional proc nick tgt &rest foo) + " ;; now assumes that the msg is (a string) in lisp format... and this just + ;; evals it.." + (eval (erbn-read msg))) +; (let* ( +; (lispmsg +; (erbeng-read (erbutils-stringify msg)))) +; (if (and lispmsg (listp lispmsg)) +; (erblisp-process-msg proc nick tgt +; lispmsg) +; (let ((englispmsg (fs-parse-english msg proc nick))) +; (erblisp-process-msg proc nick tgt englispmsg))))) + + + +(defun erbeng-read (msg) + (ignore-errors (erbn-read msg))) + + + + + + + + + + +;; proposed register syntax.. +(defun erbeng-register-syntax (fsbot-command priority check &optional + remap) + +"If CHECK is a function, then it is passed the user input as a +string... If it claims a match, it should return (t arglist). +Arglist is a list of arguments to be passed to the FSBOT-COMMAND. + +If CHECK is a regexp, it is matched against the user input string. If +it is a match, all the submatches 1....n (NOT 0) are passed to the +function as arguments in that order, except that you can remap using +the optional REMAP list. That list is a list of numbers, like, say (0 +1 2 4).<-- this tells us that the arguments to be passed to the +fsbot-command are the regexp-matches 0,1,2 4 in that order. If REMAP +is not supplied, you can see that the default value is more-or-less +equivalent to (1 2 3 4....) + +" +nil) + + +(provide 'erbeng) +(run-hooks 'erbeng-after-load-hooks) + + + +;;; erbeng.el ends here diff --git a/elisp/erbot/erbforget.el b/elisp/erbot/erbforget.el new file mode 100644 index 0000000..99e02e6 --- /dev/null +++ b/elisp/erbot/erbforget.el @@ -0,0 +1,138 @@ +;;; erbforget.el --- Help make the bots forget some TERMS. +;; Time-stamp: <2007-11-23 11:30:10 deego> +;; Copyright (C) 2003 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbforget.el +;; Package: erbforget +;; Author: D. Goel +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;;========================================== +;;; Requires: +(eval-when-compile (require 'cl)) + +;;; Code: + +(defgroup erbforget nil + "The group erbforget." + :group 'applications) +(defcustom erbforget-before-load-hooks nil + "Hooks to run before loading erbforget." + :group 'erbforget) +(defcustom erbforget-after-load-hooks nil + "Hooks to run after loading erbforget." + :group 'erbforget) +(run-hooks 'erbforget-before-load-hooks) + +;;; Real Code: + + +(defun erbforget-sw (reg &optional prevent-reg matchingonly) + "RUN THIS AS MYBOT WHEN SU-ED TO THE BOT. + +Forget all terms containing occurrence of regexp REG. + +REMINDER: DO NOT FORGET TO exclude terms like fsbot hbot erbot deego +Deepak (author) in prevent-reg +when using this command. +\\(bot\\|emacs\\|deego\\|goel\\|deepak\\|alex\\|bpt\\|oddmuse\\|iam\\) +.. for example.. +Return len, which may (or may not) correspond to the number of items +removed. +" + (interactive "sRegex to forget: ") + (let* + ((lenterms + (fs-search-basic reg nil nil 'describe)) + (len (first lenterms)) + (terms (second lenterms))) + (cond + ((= len 0 ) (message "No such terms. ")) + (t + (when (erbforget-y-or-n-p 40 (format "Forget %S terms? " len)) + (erbforget-slowly terms prevent-reg matchingonly reg)))) + len)) + + +(defun erbforget-slowly (terms &optional prevent-reg matchingonly reg) + "When matchingonly is t, we forget only the particular entry in the +NOTES that matches the regexp REG, if any..." + (let + ((len (length terms)) + (ctr 0) + thisterm + skipp + notes + ) + (while terms + (setq thisterm (car terms) terms (cdr terms)) + (setq ctr (+ ctr 1)) + (setq notes (fs-notes thisterm)) + (setq skipp + (and prevent-reg + (string-match prevent-reg + (mapconcat 'identity notes " ")))) + (cond + + (skipp + (message "NOT FORGETTING term %S of %S: %S" ctr len thisterm) + (sleep-for 1) + ) + (matchingonly + (let ((num -1) (donep nil)) + (while (not donep) + (incf num 1) + (cond + ((>= num (length notes)) + (setq donep t)) + ((string-match reg (nth num notes)) + (setq donep t) + (message "Forgetting term %S of %S: %S" ctr len thisterm) + (sleep-for 0.1) + (fs-forget thisterm num)) + (t nil))))) + + (t + (message "Forgetting term %S of %S: %S" ctr len thisterm) + (sleep-for 0.1) + (fs-forget thisterm "all") + (message "Forgetting term %S of %S: %S.. done" ctr len thisterm) + (sleep-for 0.1) + ) + + + )))) + + + + + + +(provide 'erbforget) +(run-hooks 'erbforget-after-load-hooks) + + + +;;; erbforget.el ends here diff --git a/elisp/erbot/erbim.el b/elisp/erbot/erbim.el new file mode 100644 index 0000000..f43a386 --- /dev/null +++ b/elisp/erbot/erbim.el @@ -0,0 +1,216 @@ +;;; erbim.el --- input method searching +;; Time-stamp: <2006-08-22 01:16:17 fledermaus> +;; Copyright (C) 2006 V. Dasmohapatra +;; Emacs Lisp Archive entry +;; Filename: erbim.el +;; Package: erbim +;; Author: V. Dasmohapatra +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; For latest version: + +(require 'quail) +(require 'iso-transl) + +(defvar erbim-keymaps-map nil + "Storage for the inverted keymaps for the input methods we have searched.") + +(defun erbim-enc (thing) + "Standard encoding for all strings (many chars don't work in an emacs +running screen, so chars and unencoded strings may not be safe or work)." + (encode-coding-string thing 'utf-8)) + +(defun erbim-c2s (thing) + "map a character to the appropriate string. This is not a straightforward +operation using char-to-string (for some reason)." + (if (> 256 thing) (single-key-description thing) (char-to-string thing))) + +(defun erbim-map (map) + "Traverse the input method's MAP, invert it, and return that." + (let ((char-map nil)) + (mapc (lambda (M) (erbim-map-internal M "")) (cdr map)) char-map)) + +(defun erbim-interpret-target (target) + "Examine the TARGET of a given input method map entry and turn it +into a list of (unencoded) strings.\n +Destinations can be symbols (keyboard macros) vectors of strings or +vectors of characters, or a cons of the form (LIST . TARGET)." + ;;(message "target %S" target) + (if (vectorp target) + (mapcar (lambda (T) (if (integerp T) (erbim-c2s T) T)) target) + (if (and (listp target) (listp (car target))) + (progn (message "weird target: %S" target) + (erbim-interpret-target (cdr target))) + (if (symbolp target) + (and (fboundp target) + (and (vectorp (symbol-function target)) + (erbim-interpret-target (symbol-function target)) )) + (list (if (integerp target) (string target) target)) )) )) + +(defun erbim-map-internal (map &optional so-far) + "Does the actual work of `erbim-map'." + (let ((iseq-str + (format (if (symbolp (car map)) "%s %S " "%s%c") (or so-far "") + (car map))) + (tgt nil) + (tail nil)) + ;;(message "%S %S" map so-far) + (setq tgt (cdr map)) + (if (setq tgt (or (car-safe tgt) + (and (vectorp tgt) tgt) + (and (symbolp tgt) tgt))) + (progn + ;;(message "tgt: %S" tgt) + (setq char-map + (append char-map + (mapcar + (lambda (T) (cons (erbim-enc T) iseq-str)) + (erbim-interpret-target tgt)) )) + (when (and (listp (cdr map)) (setq tail (cddr map))) + (if (listp (cdar tail)) + (erbim-map-internal (car tail) iseq-str) + ;;(message "path B: %S" tail) + (mapcar (lambda (M) (erbim-map-internal M iseq-str)) tail)) )) + (when (listp (cdr map)) + (mapcar + (lambda (M) (erbim-map-internal M iseq-str)) (cddr map))) ) )) + +(defun erbim-package-list () + "Return the list of input methods that erbim can understand. +iso-transl is not exactly an input method, but it is a special case." + (cons "iso-transl" + (mapcar (lambda (I) (if (eq (caddr I) 'quail-use-package) (car I))) + input-method-alist) )) + +(defun erbim-keymap-map (im) + "Return the inside-out keymap for input method IM (IM is a string)." + (or (cdr (assoc im erbim-keymaps-map)) + (let ( (map (erbim-map + (nth 2 (assoc im quail-package-alist)))) ) + (setq erbim-keymaps-map (cons (cons im map) erbim-keymaps-map)) map) )) + +(defun where-is-char (c &optional im-list) + "Given a string C (usually, but not always, one character (but NOT +necessarily one byte)) in length, search the input methods in either IM-LIST +or `erbim-package-list' and return a help string describing the key sequences +\(per input method) that can be used to enter C." + ;; assume we got a string: char functions are broken in fsbot becuase of + ;; some screen/emacs/terminal black magic (which I do not understand) + ;; so we cannot use (aref string 0) or string-to-char reliably. + (let ((char (erbim-enc c)) + (res nil) + (qsec nil)) + (mapc (lambda (Q) + ;; exclude chinese-* methods (too big) and misc problematic ones: + (when (and Q + (not (string-match "^chinese-" Q)) + (not (member Q '("tibetan-wylie" ;; too big? + ;; "greek-ibycus4" ;; ok actually + )) )) + ;; load the input method if it's not iso-transl (special case) + ;; and we haven't already done so: + (or (equal Q "iso-transl") + (with-temp-buffer + (or (assoc Q quail-package-alist) + (activate-input-method Q)) )) + (message "checking %s" Q) + ;; check to see if we have a quail package (iso-transl is + ;; not a quail package, don't check for it here): + (when (or (equal Q "iso-transl") (assoc Q quail-package-alist)) + ;;(message "%s keymap - %d" Q (length (erbim-keymap-map Q))) + ;; extract the inverse keymap if there is one, and pull + ;; out the first entry for the char we are looking for: + (when (setq qsec (assoc char (erbim-keymap-map Q))) + ;;(message "found sequence %s" qsec) + (setq res (cons (cons Q (cdr qsec)) res)) )) )) + (or im-list (erbim-package-list))) + ;; feed the results to the user (if there are lots of input methods, + ;; just list the input methods instead): + (if (> (length res) 10) + (format "%s is in the following input methods:\n%s" + c (mapconcat 'car res " ")) + (mapconcat + (lambda (R) + (if (equal (car R) "iso-transl") + (mapconcat 'identity + (cons "C-x 8" (split-string (cdr R) "")) " ") + (format "%s: %s" (car R) (cdr R)) )) res "\n")) )) + +(defun fsi-where-is-char (&optional key &rest im-list) + (let ((imlist nil) + (key (if key (if (symbolp key) (symbol-name key) key) nil))) + (if key (where-is-char key (mapcar 'symbol-name im-list)) + "where-is-char [ INPUT-METHOD INPUT-METHOD... ]") )) + +;; load iso-transl's inverted keymap +(add-to-list 'erbim-keymaps-map + (cons "iso-transl" (erbim-map iso-transl-ctl-x-8-map))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Unicode information functions: +(defvar erbim-unidata-file "/usr/share/perl/5.8.4/unicore/UnicodeData.txt") + +(defun erbim-name-by-character (thing) + (let ((char (if (stringp thing) (string-to-char thing) thing)) + (unicode nil)) + (setq unicode + (when (or (< char 256) + (memq 'coding-category-utf-8 + (mapcar 'coding-system-category + (find-coding-systems-string thing)))) + (encode-char char 'ucs)) ) + (erbim-name-by-codepoint unicode)) ) + +(defun erbim-name-by-codepoint (codepoint) + (let ((cpstring (format "%04X" codepoint)) + (unidata (find-file-noselect erbim-unidata-file))) + (with-current-buffer unidata + (goto-char (point-min)) + (if (re-search-forward (concat "^" cpstring ";\\([^;]*\\);") nil t) + (format "#x%s: %s" cpstring (match-string 1)) + (format "Unknown character #x%s" cpstring) )) )) + +(defun erbim-search-by-description (pat) + (let ( (unidata (find-file-noselect erbim-unidata-file)) + (pattern nil) + (case-fold-search t) + (count 0) + (limit 10) + (found nil) + (char nil) + (cp nil) + (matches nil)) + (setq pattern (replace-regexp-in-string "^\\^\\|\\$$" "" pat) + pattern + (concat "^\\([0-9A-F]+\\);\\(" (if (eq (aref pat 0) ?^) "" "[^;]*") + pattern + (if (eq (aref pat (1- (length pat))) ?$) "" "[^;]*") "\\);")) + (with-current-buffer unidata + (goto-char (point-min)) + (while (re-search-forward pattern nil t) + (when (< (setq count (1+ count)) limit) + (setq cp (string-to-int (match-string 1) #x10) + char (or (decode-char 'ucs cp) ?�) + found (format "#x%04x (%c): %s" cp char (match-string 2)) + matches (cons found matches)) )) ) + (if (< count limit) + (mapconcat 'identity (nreverse matches) "\n") + (format "Too many matches (%d) for %S" count pat)) )) + +(defun fs-unicode-find (&optional pattern) + (if pattern (erbim-search-by-description pattern) + "Usage: unicode-find ")) + +(defun fs-unicode-describe (&optional thing) + (cond ((not thing) "Usage: unicode-describe ") + ((integerp thing) (erbim-name-by-codepoint thing)) + ((symbolp thing) (erbim-name-by-character (symbol-name thing))) + (thing (erbim-name-by-character thing)) )) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; trigger the preprocessing of the rest of the input methods: +(where-is-char "x") + +(provide 'erbim) + diff --git a/elisp/erbot/erbjavadoc.el b/elisp/erbot/erbjavadoc.el new file mode 100644 index 0000000..eeb4ead --- /dev/null +++ b/elisp/erbot/erbjavadoc.el @@ -0,0 +1,169 @@ +;;; erbjavadoc.el --- Learn terms from a url. +;; Time-stamp: +;; Copyright (C) 2004 Pete Kazmier +;; Emacs Lisp Archive entry +;; Filename: erbjavadoc.el +;; Package: erbjavadoc +;; Author: Pete Kazmier +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + +(defconst erbtrain-home-page + "http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot") + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + +;;========================================== +;;; Requires: +(require 'cl) +(require 'erburl) + +;;; Code: + +(defgroup erbjavadoc nil + "The group erbjavadoc." + :group 'applications) + +(defcustom erbjavadoc-before-load-hooks nil + "Hooks to run before loading erbjavadoc." + :group 'erbjavadoc) + +(defcustom erbjavadoc-after-load-hooks nil + "Hooks to run after loading erbjavadoc." + :group 'erbjavadoc) + +(run-hooks 'erbjavadoc-before-load-hooks) + +;;; Real Code: + +;; I need to persist this var somehow, are there any facilities +;; in erbot to do this? +(defvar erbjavadoc-scraped-urls '() + "A list of javadoc urls that have been learned already. This +is used to prevent users from learning a url more than once.") + +;; In the meantime until a better way to persist immutable vars +;; is in place, I'll just write out the value to a file. +(defvar erbjavadoc-data-file "~/public_html/data/state-erbjavadoc.el") + +(defun erbjavadoc-load-data () + (when (file-exists-p erbjavadoc-data-file) + (ignore-errors (load erbjavadoc-data-file)))) + +(defun erbjavadoc-save-data () + (erbn-write-sexps-to-file erbjavadoc-data-file + (list `(setq erbjavadoc-scraped-urls + ',erbjavadoc-scraped-urls)))) + +(erbjavadoc-load-data) + +(defvar erbjavadoc-pages '("allclasses-frame.html" "overview-frame.html") + "The names of the index pages generated by javadoc. These names +will be appended to a base url and then these pages will be scraped +for terms.") + +(defun erbjavadoc-base-url (url) + "Returns the base url for a given URL. Strips off any trailing +filename component and/or trailing slash. Converts the following: + + http://example.com/test/ -> http://example.com/test + http://example.com/test/name.html -> http://example.com/test +" + (let ((p (string-match "/\\([^/]+\\.[^/]+\\)?$" url))) + (if p + (substring url 0 p) + url))) + +(defun fsi-learn-javadocs (url) + "Add the Java package and class names as terms in the bot's bbdb +with links to the appropriate pages. A single URL is passed as the +only argument and can only be learned once until its been forgotten. +It should be noted that this command can only be executed via a user +in IRC because in relies on various vars that are in scope when +erbot.el invokes this function." + (unless (stringp url) (setq url (format "%s" url))) + (let ((base (erbjavadoc-base-url url))) + (if (member base erbjavadoc-scraped-urls) + "That set of javadocs has already been learned." + (dolist (page erbjavadoc-pages) + (let ((pageurl (concat base "/" page))) + ;; See the docsting for erburl-scrape-terms for more + ;; information on its arguments. Lack of closures + ;; makes this more complicated than need be. + (erburl-scrape-terms pageurl + ;; Entry parser callback, we use the + ;; standard parser and supply it with + ;; the appropriate base url to use and + ;; limit the terms learned to terms + ;; that don't contain spaces. + (lambda (base &rest not-used) + (erburl-href-parser base t)) + ;; Progress callback, the default is + ;; to use 'message, but we want the + ;; progress to be sent back to the + ;; user that invoked the command, so + ;; we use erbot-reply. + (lambda (msg not-used proc nick tgt) + (save-excursion + (set-buffer (process-buffer proc)) + (erbot-reply msg proc nick tgt "" nil))) + ;; These arguments are passed as + ;; extra parameters to our callback + ;; functions. We need these so that + ;; we can invoke erbot-reply. + (list base proc erbn-nick tgt)))) + (push base erbjavadoc-scraped-urls) + (erbjavadoc-save-data) + (format "I'm downloading the javadocs now ...")))) + +;; This function should not be made available to users until I can +;; figure out how to make the underlying erburl-forget-terms an +;; asychronous operation. Currently, if a user invokes this and there +;; are a large number of entries to remove, the operation times out +;; from the top-level timer in erbot (I think) +;; +;; (defun fsi-forget-javadocs (url) +;; "Remove all terms and entries for the URL specified. This will +;; remove the appropriate entries from the bbdb. If an entry has more +;; than one definition, only the relevant entry is removed." +;; (unless (stringp url) (setq url (format "%s" url))) +;; (let ((base (erbjavadoc-base-url url))) +;; (if (not (member base erbjavadoc-scraped-urls)) +;; "This set of javadocs has not been learned." +;; (let ((count (erburl-forget-terms base))) +;; (setq erbjavadoc-scraped-urls (remove base erbjavadoc-scraped-urls)) +;; (erbjavadoc-save-data) +;; (format "I have removed %S entries for %S" count base))))) + +(defun fsi-learned-javadocs () + "Return a list of learned javadocs." + (cond ((= 0 (length erbjavadoc-scraped-urls)) + "I have not learned any javadocs.") + (t + (format "I know about the following javadocs: %s" + (mapconcat 'identity erbjavadoc-scraped-urls ", "))))) + +(provide 'erbjavadoc) +(run-hooks 'erbjavadoc-after-load-hooks) + +;;; erbjavadoc.el ends here diff --git a/elisp/erbot/erbkarma.el b/elisp/erbot/erbkarma.el new file mode 100644 index 0000000..3b27103 --- /dev/null +++ b/elisp/erbot/erbkarma.el @@ -0,0 +1,163 @@ +;;; erbkarma.el --- karma is not currently functional, we think.. +;; Time-stamp: <2007-11-23 11:30:09 deego> +;; Copyright (C) 2002 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbkarma.el +;; Package: erbkarma +;; Authors: D. Goel +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; 2003-01-29 T13:10:42-0500 (Wednesday) D. Goel +;; removed +;; Dheeraj Buduru +;; from authors' list at his request. :( + + +;;; 2004-01-22 T07:18:36-0500 (Thursday) D. Goel +;; deego: fsbot should get the old silly karma system back. fsbot +;; forget all karma points whenever he disconnects. the only +;; important thing is that we can say b0ef++ and fsbot responds with +;; "Noted, kensanata. One (brownie|karma|wiki|rms|lispy)-point for +;; b0ef!" + +;;========================================== +;;; Requires: +(eval-when-compile (require 'cl)) +(require 'pp) +(require 'thingatpt) +;;; Code: + +(defgroup erbkarma nil + "The group erbkarma." + :group 'applications) +(defcustom erbkarma-before-load-hooks nil + "Hooks to run before loading erbkarma." + :group 'erbkarma) +(defcustom erbkarma-after-load-hooks nil + "Hooks to run after loading erbkarma." + :group 'erbkarma) +(run-hooks 'erbkarma-before-load-hooks) + +;;; Real Code: + + +(defcustom erbkarma-file "~/public_html/karma/karma" + "") + +(defcustom erbkarma-min -1000 "") +(defcustom erbkarma-max +1000 "") + +(defvar erbkarma nil + "stores all karma" + ) + + +(defun erbkarma-read () + (save-window-excursion + (unless erbkarma + (setq erbkarma + (ignore-errors + (find-file erbkarma-file) + (goto-char (point-min)) + (sexp-at-point)))))) + +(defun erbkarma (&optional entity) + (cond + ((not entity) (fs-karma-best)) + (t + (unless (stringp entity) + (setq entity (format "%s" entity))) + (erbkarma-read) + (second + (assoc entity erbkarma))))) + +(defun erbkarma-save () + (save-window-excursion + (find-file erbkarma-file) + (delete-region (point-min) (point-max)) + (insert (pp-to-string erbkarma)) + (write-file erbkarma-file) + (kill-buffer (current-buffer)))) + + + + +(defun erbkarma-increase (entity &optional points) + (format "%s" entity) + (erbkarma-tgt-check) + (unless points (setq points 1)) + (erbkarma-read) + (let* ((eass (assoc entity erbkarma)) + (val (if eass (second eass) 0)) + (newval (+ val points)) + (removed (remove eass erbkarma))) + (setq erbkarma + (if (= newval 0) + removed + (cons + (list entity newval) + removed))) + (erbkarma-save) + (format "%s" newval))) + +(defun erbkarma-decrease (entity &optional points) + (erbkarma-tgt-check) + (unless points (setq points 1)) + (erbkarma-increase entity (- points))) + +(defun erbkarma-sort () + (setq erbkarma + (sort + erbkarma + '(lambda (a b) + (> (second a) (second b))))) + (erbkarma-save)) + +(defun erbkarma-best (&optional n bottomp) + (unless n (setq n 5)) + (erbkarma-sort) + (let ((result (if bottomp + (reverse erbkarma) + erbkarma))) + (if (> n (length result)) + result + (subseq result 0 n)))) +(defalias 'fs-best-karma 'fs-karma-best) + +(defcustom erbkarma-tgt-check-string + "^\\(#emacs\\|#gnu\\|#fsf\\|#hurd-bunny\\|deego\\|#wiki\\)$" + "" :group 'erbkarma + ) + +(defun erbkarma-tgt-check () + (unless (string-match erbkarma-tgt-check-string fs-tgt) + (error + "Do it publicly. "))) + +(provide 'erbkarma) +(run-hooks 'erbkarma-after-load-hooks) + + + +;;; erbkarma.el ends here diff --git a/elisp/erbot/erblisp.el b/elisp/erbot/erblisp.el new file mode 100644 index 0000000..6530b94 --- /dev/null +++ b/elisp/erbot/erblisp.el @@ -0,0 +1,276 @@ +;;; erblisp.el --- +;; Time-stamp: <2007-11-23 11:30:08 deego> +;; Copyright (C) 2002 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erblisp.el +;; Package: erblisp +;; Author: D. Goel +;; Version: 0.0DEV +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + + +(defvar erblisp-version "0.0dev") + +;;========================================== +;;; Code: + +(defgroup erblisp nil + "The group erblisp" + :group 'applications) +(defcustom erblisp-before-load-hooks nil "" :group 'erblisp) +(defcustom erblisp-after-load-hooks nil "" :group 'erblisp) +(run-hooks 'erblisp-before-load-hooks) + + +(defun erblisp-process-msg (msg &optional proc nick tgt) + "MSG is either a string or a tree.. If it is a tree, it looks +something like + '(foo bar (bar foo)) + +This command sandboxes the message and then processes it.." + + (if (stringp msg) + (setq msg (erbn-read msg))) + (format "%s" (eval (erblisp-sandbox-fuzzy msg)))) + +(defun erblisp-sandbox-quoted-maybe (expr) + "sandboxes the whole expression even if it starts with a quote." + (cond + ((and (listp expr) + (equal (first expr) 'quote)) + (cons 'quote + (mapcar 'erblisp-sandbox (cdr expr)))) + (t (erblisp-sandbox expr)))) + + +(defun erblisp-sandbox-quoted (expr) + "Assumes that the expression will result in a quoted thingy and +tries to make sure that we sandbox that whole quoted thing.. " + (cond + ((and (listp expr) + (equal (first expr) 'quote)) + (cons 'quote + (mapcar 'erblisp-sandbox (cdr expr)))) + ((listp expr) + (list 'erblisp-sandbox-quoted (erblisp-sandbox expr))) + ;; just an atom + (t (erblisp-sandbox expr)))) + + +(defvar erblisp-allowed-words + '(nil t + ;; Also consider: + ;; &rest + ;; &optional + + ) + "You should add &rest and &optional to this list. +We WON'T do this by default since this could lead to exploits if you +*happen* to have bound these keywords to weird stuff like +\(setq &rest (shell-command \"rm -rf /\")) in your .emacs." +) + +(defvar erblisp-max-list-length 2000 + "If non-numeric, we will skip this check." + ) + +(defun erblisp-safe-length-args-p (list so-far len) + (let ((cur list) + stack) + (while (and cur + (<= so-far len)) + (if (consp (car cur)) + (progn (setq cur (car cur)) + (when (consp (cdr cur)) + (push (cdr cur) stack))) + (setq cur (cdr cur))) + (unless cur + (setq cur (pop stack))) + (setq so-far (1+ so-far))) + (if (<= so-far len) + t + nil))) + +(defmacro erblisp-check-args (&rest args) + "All we do in this macro we remove some bindings for things like +&rest, etc, things that do not have values but got passed to us -- +this occurs when a user attempts to use &rest in his function +definitions -- see `erblisp-allowed-words'. + +All the arguments to this macro should have been in their evalled form +and hence constants already, so we do not bother protecting against +multiple evaluations here -- evaluating a constant causes no harm. +All we do in this macro we remove some bindings for things like &rest, +etc, things that are not defined, but passed on here in any case." + `(erblisp-check-args-nascent + ,@(remove-if + #'(lambda (arg) (and + (symbolp arg) + (not (boundp arg)))) + args))) + + + +(defun erblisp-check-args-nascent (&rest args) + (if (or + (not (numberp erblisp-max-list-length)) + (erblisp-safe-length-args-p args 0 erblisp-max-list-length)) + t + (error "encountered overlong expression, ignoring") nil)) + + + + +(defun erblisp-sandbox (expr) + "" + (cond + ;; first condition + ((null expr) nil) + ;; second condition + ((listp expr) + (when (erblisp-check-args expr) + (let ((fir (first expr))) + (cond + ((listp fir) + (cons (erblisp-sandbox fir) + (mapcar 'erblisp-sandbox (cdr expr)))) + ((equal (format "%S" fir) "quote") + ;; if quoted, it is fine... + expr) + (t (cons + (if (or (equal 0 (string-match "fs-" (format "%S" fir))) + (member fir erblisp-allowed-words)) + fir + (intern (concat "fs-" (format "%S" fir)))) + (mapcar 'erblisp-sandbox (cdr expr)))))))) + + ;; final condition.. --> when the expr is an atom.. It should be a + ;; a constant.. or an allowed atom.. allowed == prefixed with fs- + (t (cond + ((and (symbolp expr) + (equal 0 (string-match "fs-" (format "%s" expr)))) + expr) + ((equal expr t) expr) + ((member expr erblisp-allowed-words) expr) + ((symbolp expr) + ;;(boundp (intern (concat "fs-" (format "%S" expr))))) + (intern (concat "fs-" (format "%s" expr)))) + ;; other symbol + ;;((symbolp expr) (list 'quote expr)) + ;; a number or string now.. + ;; this actually happens when they feed byte-compiled code to + ;; the bot, like: + ;;, (funcall #[nil "\300\207" [1] 1]) + ((not (or (symbolp expr) (numberp expr) (stringp expr))) + (error "%s %s" "Should not reach here. Quantum Tunnelling! " + "What are you trying to feed me? Byte-compiled code? Vectors?" )) + (t expr))) + )) + +(defun erblisp-sandbox-fuzzy (expr) + "Sandboxes a message.. Ensures that the functions are all fs- +and the arguments are NOT variable-names... This one sandboxes +preferably by quoting unless fs-symbol is bound.." + (cond + + ;; first condition + ((null expr) nil) + + ;; second condition + ((listp expr) + (let ((fir (first expr))) + (cond + ((listp fir) + (cons (erblisp-sandbox-fuzzy fir)) + (mapcar 'erblisp-sandbox-fuzzy (cdr expr))) + ((equal (format "%S" fir) "quote") + ;; if quoted, it is fine... + expr) + (t (cons + (if (equal 0 (string-match "fs-" (format "%S" fir))) + fir + (intern (concat "fs-" (format "%S" fir)))) + (mapcar 'erblisp-sandbox-fuzzy (cdr expr))))))) + + + ;; final condition.. --> when the expr is an atom.. It should be a + ;; a constant.. or an allowed atom.. allowed == prefixed with fs- + (t (cond + ((and (symbolp expr) + (equal 0 (string-match "fs-" (format "%s" expr)))) + expr) + ((and (symbolp expr) + (or + (boundp (intern (concat "fs-" (format "%S" expr)))) + (fboundp (intern (concat "fs-" (format "%S" expr)))) + )) + (intern (concat "fs-" (format "%s" expr)))) + ;; other symbol + ((symbolp expr) (list 'quote expr)) + ;; a number or string now.. + + ((not (or (symbolp expr) (numberp expr) (stringp expr))) + (error "Should not reach here. Fuzzy tunnels!")) + (t expr))) + )) + + + + +(defun erblisp-sandbox-full(expr &optional midstream) + " +This will ensure that anything rigt after parens is sandboxed by a +fs- prefix. And anything else is either a symbol , or a string, +but not a variable... viz: quoted ...else converted into one. + +midstream is in internal variable..." + (cond + ((null expr) nil) + ((listp expr) + (let* ((fir (first expr))) + (if (eql fir 'quote) + expr + (cons (erblisp-sandbox-full fir) + (mapcar '(lambda (arg) + (erblisp-sandbox-full arg t)) + (cdr expr)))))) + ;; now we know that expr is a non-nil atom... + (midstream + (if (stringp expr) expr + (list 'quote expr))) + + + + ;; midstream is untrue... expr is thus an atom at the beginning.. + (t + (if (equal 0 (string-match "fs-" (format "%s" expr))) + expr (intern (concat "fs-" (format "%s" expr))))))) + +(provide 'erblisp) +(run-hooks 'erblisp-after-load-hooks) + + + +;;; erblisp.el ends here diff --git a/elisp/erbot/erblog.el b/elisp/erbot/erblog.el new file mode 100644 index 0000000..0e46803 --- /dev/null +++ b/elisp/erbot/erblog.el @@ -0,0 +1,78 @@ +;;; erblog.el --- +;; Time-stamp: <2007-11-23 11:30:08 deego> +;; Copyright (C) 2002 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erblog.el +;; Package: erblog +;; Author: D. Goel +;; Version: 0.0DEV +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + +(defvar erblog-version "0.0dev") + +;;========================================== +;;; Code: + +(defgroup erblog nil + "The group erblog" + :group 'applications) +(defcustom erblog-before-load-hooks nil "" :group 'erblog) +(defcustom erblog-after-load-hooks nil "" :group 'erblog) +(run-hooks 'erblog-before-load-hooks) + + +(defvar erblog-active-targets nil + "This stores the list of targets that have had some activity... + +The idea is that the operator sets this to nil (see commands +below).. goes away, comes back and examined this variables to find +out which channels have had activity... +") + +(defun erblog-log-target (target &rest stuff) + (unless (member (format "%s" target) + erblog-active-targets) + (progn + (add-to-list 'erblog-active-targets + (format "%s" target)) + (erblog-show-targets)))) + +;; operator bind to C-c s +(defun erblog-show-targets () + (interactive) + (message "%s" erblog-active-targets)) + +;; bind to C-c r +(defun erblog-reset-targets () + (interactive) + (message "Nulling.. was %s" erblog-active-targets) + (setq erblog-active-targets nil)) + +(provide 'erblog) +(run-hooks 'erblog-after-load-hooks) + + + +;;; erblog.el ends here diff --git a/elisp/erbot/erbmerge.el b/elisp/erbot/erbmerge.el new file mode 100644 index 0000000..2d1e5db --- /dev/null +++ b/elisp/erbot/erbmerge.el @@ -0,0 +1,48 @@ +;;; erbmerge.el --- merge 2 bbdb's -- NOT YET IMPLEMENTED +;; Time-stamp: <2007-11-23 11:30:07 deego> +;; Copyright (C) 2004 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbmerge.el +;; Package: erbmerge +;; Author: D. Goel +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; For latest version: + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + +;;; Requires: +(eval-when-compile (require 'cl)) + +;;; Real Code: +;; Use functions like fs-notes... See the code of erbforget-slowly.. +;; NOT YET IMPLEMENTED. + + +(provide 'erbmerge) +(run-hooks 'erbmerge-after-load-hook) + + + +;;; erbmerge.el ends here diff --git a/elisp/erbot/erbmsg.el b/elisp/erbot/erbmsg.el new file mode 100644 index 0000000..4a0f748 --- /dev/null +++ b/elisp/erbot/erbmsg.el @@ -0,0 +1,583 @@ +;;; erbmsg.el --- memoserv-esque functions for Erbot +;; $Id: erbmsg.el,v 1.26 2007/11/23 16:31:59 deego Exp $ +;; Copyright (C) 2004 Sebastian Freundt +;; Emacs Lisp Archive entry +;; Filename: erbmsg.el +;; Package: erbmsg +;; Authors: Sebastian Freundt +;; Keywords: memo, message, +;; Version: still conceptional +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErbMsg +;; For latest version: + +(defconst erbot-home-page + "http://savannah.nongnu.org/projects/erbot") +(defconst erbmsg-version + "Version 0.2 $Revision: 1.26 $") + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + +;;; Comments: + +;; - To automagically save the whole message table with each incoming message +;; put following to your .erbot: +;; +;; (add-hook 'erbmsg-new-msg-post-hook 'erbmsg-regular-dump) +;; +;; - To clean up message cookies with every flushed message, add +;; +;; (add-hook 'erbmsg-flush-post-hook 'erbmsg-garbage-cleanse-cookies) + + +;;; TODOs that have been done: + +;; 2004/06/22: +;; - added dump routines to dump message hash tables to hard disk +;; - added routines for restoring from dumped message files +;; - added interval within erbot does not notify on channel joins +;; - added erbmsg-new-msg-(pre|post)-hook +;; 2004/04/09: +;; - added support for multiple recipients (see fs-memo for syntax) +;; - abstracted fs-memo stuff to two defuns (erbmsg-memo-parse-msg and erbmsg-memorize-msg) +;; 2004/04/01: +;; - added hooks +;; 2004/03/31: +;; - store which channel the memo came from +;; - added garbage collection function (erbmsg-garbage-cleanse-cookies) to +;; clean up erbmsg-msg-cookie-hash-table from unreferenced cookies + +;;; TODO: +;; - functionality to forget the erbmsg-question-* pile effectively +;; - save erbmsg-msg-hash-table across sessions +;; - expire cookies in erbmsg-msg-cookie-hash-table some time (after 3 notifications?) + +;;; Data + + +(defvar erbmsg-msg-hash-table (make-hash-table :test 'equal) + "This is a hash-table holding all the messages via cookies.") + +(defvar erbmsg-internal-msg-cookie nil + "Message cookie for internal communication.") + +(defvar erbmsg-msg-cookie-hash-table (make-hash-table :test 'equal) + "This is the hash-table for message cookies, the actual +messages are saved here") + +(defgroup erbmsg nil + "The erbmsg module for erbot" + :group 'erbot) + +(defcustom erbmsg-default-magic-words nil + "List of default magic words for messages with magic words." + :group 'erbmsg) + + +;;; dump settings + +(defcustom erbmsg-dump-file "~/public_html/data/messages.dump" + "File to dump message hash tables to." + :group 'erbmsg) + +(defcustom erbmsg-auto-restore-message-tables t + "Whether to automagically restore contents of `erbmsg-dump-file'." + :group 'erbmsg + :type 'boolean) + +(defcustom erbmsg-auto-dump-message-tables nil + "Whether to automagically dump hash tables to `erbmsg-dump-file'." + :group 'erbmsg + :type 'boolean) + + + +;;; uncomment this to normalize to UTC +;;(set-time-zone-rule "UTC0") + +(defvar erbmsg-after-load-hook nil + "Hook called after `erbmsg' has been loaded.") + +(defvar erbmsg-new-msg-pre-hook nil + "Hook called before a new message has been posted. +The raw message is passed as argument.") +(defvar erbmsg-new-msg-post-hook + (when erbmsg-auto-dump-message-tables + '(erbmsg-regular-dump)) + "Hook called after a new message has been posted. +The parsed message \(split to nicks and actual message text\) +is passed as argument.") +(defvar erbmsg-flush-pre-hook nil + "Hook called before erbmsg-flush-pending-msgs is called.") +(defvar erbmsg-flush-post-hook nil + "Hook called before erbmsg-flush-pending-msgs is called.") + + +;;; this is too useful to not add it here +(add-hook 'erbmsg-flush-post-hook 'erbmsg-garbage-cleanse-cookies) + + +;; interface functions +(defun fs-memo (&rest msg) + "Specify your message and the nick to dedicate to here, as in: + +#somechan> ,memo somenick hello somenick, don't forget + +Allowed syntaxes: +,memo [to|for] msg +,memo [to|for] : msg + +Note: magic words are not currently implemented." + (or (and erbot-erbmsg-p + msg + (let* ((msg-raw (erbutils-stringize msg)) + (nicks+msg (erbmsg-memo-parse-msg msg-raw))) + (run-hook-with-args 'erbmsg-new-msg-pre-hook msg-raw) + (mapc (lambda (nick+msg) + (let* ((nick (car nick+msg)) + (msg (nth 1 nick+msg))) + (erbmsg-memorize-msg nick msg))) + nicks+msg) + (run-hook-with-args 'erbmsg-new-msg-post-hook nicks+msg) + "msg memorized for delivery")) + (if msg (format "error: %S NOT parsed") (fs-memos)) + 'noreply)) +(defalias 'fs-msg-wmw 'fs-memo) ;; just for compatibility +(defalias 'fs-msg-with-magic-words 'fs-memo) + + +(defun erbmsg-memo-parse-msg (raw-msg) + "Parses MSG for any of the allowed memo syntaxes and returns a list +\(\(nick msg) (nick msg) ...)" + (let* ((nick-msg (cond ((string-match "^\\(?:to\\|for\\)?\\b\\(.+\\)\\b:\\(.*\\)" raw-msg) + (cons (match-string 1 raw-msg) (match-string 2 raw-msg))) + ((string-match "^\\(?:to\\|for\\)?\\(?:\\s-\\|\\b\\)\\(\\S-+\\)\\s-\\(.*\\)" raw-msg) + (cons (match-string 1 raw-msg) (match-string 2 raw-msg))) + (t nil))) + (nicks (split-string (replace-regexp-in-string ",\\|\\band\\b" "" (car nick-msg)))) + (msg (replace-regexp-in-string "^\\s-+" "" (cdr nick-msg)))) + (mapcar (lambda (nick) + (list nick msg)) + nicks))) +;;(erbmsg-memo-parse-msg "hroptatyr and deego: huhu! :)") + +(defun erbmsg-memorize-msg (nick msg &optional magic-words) + "Memorizes NICKs MSG." + (let* ((nicks-ht (or (gethash nick erbmsg-msg-hash-table) + (puthash nick + (make-hash-table :test 'equal) + erbmsg-msg-hash-table))) + (cnick fs-nick) + (cchan fs-tgt) + (ctime (current-time)) + ;; composition of the new memo + (newmsg (vector cnick cchan msg ctime magic-words)) + (newcookie (erbmsg-generate-msg-cookie newmsg)) + ;; now memos from that user already in the system + (cmsgs (gethash cnick nicks-ht))) + (add-to-list 'cmsgs newcookie) + (puthash cnick cmsgs nicks-ht))) + + + +(defun fs-memos (&rest line) + "This is redundant but more clean than in `erbmsg-parse'." + (and erbot-erbmsg-p + (let* ((linecar (car line)) + (internalp (and erbmsg-internal-msg-cookie + (eq linecar ':internal) + (eq erbmsg-internal-msg-cookie (cadr line)))) + (nick (or (and internalp + (car (cdr-safe (cdr-safe line)))) + fs-nick)) + (fromnicks (and (null internalp) + (mapcar (lambda (s) (format "%s" s)) line))) + (nicks-ht (gethash nick erbmsg-msg-hash-table)) + pending-msgs) + (and nicks-ht + (maphash (lambda (fromnick msg-cookies) + (setq pending-msgs + (append pending-msgs (or (and (null fromnicks) + msg-cookies) + (and (member fromnick fromnicks) + msg-cookies))))) + nicks-ht)) + (or (and pending-msgs + (let ((msg-cookie)) + (format "erm, %s, %s msgs pending, see them? %s" + nick + (length pending-msgs) + (erbmsg-question `((notice (erbmsg-notice-pending-msgs ,nick ',pending-msgs)) + (query (erbmsg-query-pending-msgs ,nick ',pending-msgs)) + (post (erbmsg-post-pending-msgs ,nick ',pending-msgs)) + (flush (erbmsg-flush-pending-msgs ,nick ',pending-msgs)) + (no (ignore)) + (memo-help (erbmsg-help))) + nick)))) + (and (null internalp) + (format ":( no msgs for you, %s\n%s" nick + (fs-describe "help-memo"))))))) +(defalias 'fs-msg-mymsgs 'fs-memos) +(defalias 'fs-mymemos 'fs-memos) +(defalias 'fs-msgs 'fs-msg-mymsgs) +(defalias 'fs-mymsgs 'fs-msg-mymsgs) + +(defun fsi-erbmsg-version (&rest ignore) + "Spits out `erbmsg-version'." + erbmsg-version) +(defalias 'fs-msg-version 'fs-erbmsg-version) + + +(defcustom erbmsg-notify-on-join-timeout 2 + "Interval in seconds to wait between notification on channel joins." + :group 'erbmsg) + +(defvar erbmsg-last-nicks-join nil + "List of nicks with last join time.") + +(defun erbmsg-put-alist (item value alist) + "Modify ALIST to set VALUE to ITEM. +If there is a pair whose car is ITEM, replace its cdr by VALUE. +If there is not such pair, create new pair (ITEM . VALUE) and +return new alist whose car is the new pair and cdr is ALIST. +\[tomo's ELIS like function]" + (let ((pair (assoc item alist))) + (if pair + (progn + (setcdr pair value) + alist) + (cons (cons item value) alist) + ))) + +(defun erbmsg-set-alist (symbol item value) + "Modify a alist indicated by SYMBOL to set VALUE to ITEM." + (or (boundp symbol) + (set symbol nil)) + (set symbol (erbmsg-put-alist item value (symbol-value symbol)))) + +(defun erbmsg-notify-msg-on-JOIN (process parsed) + "Notifies users about left messages +when joining the channel" + (and erbot-erbmsg-p + (let* ((usernickhost (if erbot-on-new-erc-p + (erc-response.sender parsed) + (aref parsed 1))) + (channel (if erbot-on-new-erc-p + (nth 0 (erc-response.command-args parsed)) + (aref parsed 2))) + (nick (car (erc-parse-user usernickhost))) + (last-access (cdr-safe (assoc nick erbmsg-last-nicks-join)))) + (erbmsg-set-alist 'erbmsg-last-nicks-join nick (current-time)) + (setq erbmsg-internal-msg-cookie (random)) + (let* ((msgs (fs-msg-mymsgs :internal erbmsg-internal-msg-cookie nick))) + (and msgs + (or (null last-access) + (> (- (nth 1 (current-time)) (nth 1 last-access)) + erbmsg-notify-on-join-timeout)) + (erc-message "PRIVMSG" + (format "%s %s" + channel + msgs))) + 'noreply)))) +(if (and (boundp 'erbot-on-new-erc-p) erbot-on-new-erc-p) + (add-hook 'erc-server-JOIN-functions 'erbmsg-notify-msg-on-JOIN) + (add-hook 'erc-server-JOIN-hook 'erbmsg-notify-msg-on-JOIN)) + + + +(defun erbmsg-parse (msg proc nick tgt localp userinfo) + "When having (require 'erbmsg) and (setq erbot-erbmsg-p t) +this function is called with every message typed. + +It checks for `nick' being in `erbmsg-msg-hash-table', +if so, i.e. `nick' is about to have messages pending for delivery, +it will be checked here if `nick' says the ~magic words~, +if that's also the case, the message will be spit out. + +Currently this function also plays the role as question handler, +see erbmsg-question part below :)." + (let* ((nicks-ht (gethash nick erbmsg-msg-hash-table)) + (pending-msgs) + + ;; now the stuff for question handling + (nicks-q-ht (gethash nick erbmsg-question-hash-table)) + (pending-actions)) + + ;; erbmsg-question handling + (and nicks-q-ht + (maphash (lambda (keyword action-forms) + (and (string-match (format "\\b%S\\b" keyword) + msg) + (let ((func (intern (format "fs-%s" keyword)))) + (and (fboundp func) + (funcall func))))) + nicks-q-ht)))) + + +(defun erbmsg-generate-msg-cookie (message) + "Generates a message cookie for `message' and returns it." + (let* ((msg-cookie (format "%.4x%.4x" + (mod (random) 65536) (mod (random) 65536)))) + (puthash msg-cookie message erbmsg-msg-cookie-hash-table) + msg-cookie)) + +(defun erbmsg-get-msgs (msg-cookies) + "Gets messages by `msg-cookie'." + (mapcar (lambda (msg-cookie) + (gethash msg-cookie erbmsg-msg-cookie-hash-table)) + msg-cookies)) + + +;; reply functions +(defun erbmsg-notice-pending-msgs (nick msg-cookies) + "NOTICEs all `msgs' to the user `nick'." + (erbmsg-send-pending-msgs nick msg-cookies "NOTICE" nick)) + +(defun erbmsg-query-pending-msgs (nick msg-cookies) + "PRIVMSGs all `msgs' to the user `nick'." + (erbmsg-send-pending-msgs nick msg-cookies "PRIVMSG" nick)) + +(defun erbmsg-post-pending-msgs (nick msg-cookies) + "Publically post all `msgs' to current channel" + (erbmsg-send-pending-msgs nick msg-cookies "PRIVMSG" fs-tgt)) + +(defun erbmsg-send-pending-msgs (nick msg-cookies &optional method target) + "PRIVMSGs all `msgs' to the user `nick', +instead of PRIVMSG you may specify another sending method." + (let ((msgs (erbmsg-get-msgs msg-cookies)) + (method (or method "PRIVMSG")) + (target (or target fs-nick))) + (and msgs + (mapc (lambda (msg) + (or (and msg + (let ((msgfrom (aref msg 0)) + (msgchan (aref msg 1)) + (msgtext (aref msg 2)) + (msgtime (aref msg 3))) + (erc-message method + (format "%s %s@%s %s: %s" + target + msgfrom + msgchan + (format-time-string "%D %T (%Z)" msgtime) + msgtext)))) + (erc-message method (format "%s invalid message cookie" target)))) + msgs)))) + +(defun erbmsg-flush-pending-msgs (nick msg-cookies) + "Flushes all pending messages for user `nick'." + (run-hook-with-args 'erbmsg-flush-pre-hook nick msg-cookies) + (erbmsg-flush-msg-cookies msg-cookies) + (remhash nick erbmsg-msg-hash-table) + (remhash nick erbmsg-question-hash-table) + (erc-send-message "flushed") + (run-hook-with-args 'erbmsg-flush-post-hook nick msg-cookies)) + +(defun erbmsg-flush-msg-cookie (msg-cookie) + "Flushes `msg-cookie'." + (remhash msg-cookie erbmsg-msg-cookie-hash-table)) +(defun erbmsg-flush-msg-cookies (msg-cookies) + "Flushes a collection of `msg-cookies'." + (mapc 'erbmsg-flush-msg-cookie msg-cookies)) + + +(defun erbmsg-help (&rest ignore) + "Spits out some detour to the wiki help page." + (erc-send-message "help? whom to help? see http://www.emacswiki.org/cgi-bin/wiki/ErbMsg")) + + + + + +;; garbage collection + +(defun erbmsg-garbage-cleanse-cookies (&rest ignore) + "Collects garbage from `erbmsg-msg-cookie-hash-table' when +there's no referring entry in `erbmsg-msg-hash-table'." + (maphash (lambda (cookie-k cookie-v) + (let ((cookie cookie-k) + (referred)) + (catch 'ref-exists-p + (maphash (lambda (memo-k memo-v) + (maphash (lambda (from cookie-list) + (and (member cookie cookie-list) + (setq referred t) + (throw 'ref-exists-p t))) + memo-v)) + erbmsg-msg-hash-table)) + (unless referred + (remhash cookie erbmsg-msg-cookie-hash-table)))) + erbmsg-msg-cookie-hash-table)) +;; erbmsg-msg-cookie-hash-table +;; (erbmsg-garbage-cleanse-cookies) + + + + + +;;; just some tricks to create gazillions of msgs w/o IRC +;; (clrhash erbmsg-msg-hash-table) +;; (puthash "hroptatyr" (make-hash-table :test 'equal) erbmsg-msg-hash-table) +;; (puthash "asathor" '("22224444" "33336666") (gethash "hroptatyr" erbmsg-msg-hash-table)) + + + + + + + +;;; this will get more abstract and move to an own modules soon :) +(defvar erbmsg-question-hash-table (make-hash-table :test 'equal) + "Hash table to hold who may be about to have the choice.") + +(defvar erbmsg-question-verbosity nil + "Controls how talkative erbot is when being in question mode.") + +(defvar erbmsg-question-handler nil + "command temporarily bound to certain users.") + +(defun erbmsg-question (choices nick) + "Declares choices for interactively control erbot's +more complex tasks. + +`choices' is an alist (action action-forms), +`action-forms' will be eval'd if nick uses the magic word once again." + (let* ((nicks-ht (puthash nick (make-hash-table :test 'equal) erbmsg-question-hash-table))) + (mapc (lambda (choice) + (let* ((magic-word (car choice)) + (action-forms (cdr choice)) + (internal-name (intern (format "fs-%s" magic-word)))) + (and ;;(not (fboundp internal-name)) + (fset internal-name + `(lambda (&rest ignore) + (and (erbmsg-question-user-allowed-p fs-nick ',magic-word) + (mapc 'eval ',action-forms)) + (erbmsg-question-user-answer fs-nick ',magic-word)))) + (puthash magic-word action-forms nicks-ht))) + choices) + (format "[type %s]" + (mapconcat (lambda (choice) + (format "%s%s" + erbn-char + (car choice))) + choices "/")))) + +;;(symbol-function 'fs-flush) + + +(defun erbmsg-question-user-allowed-p (nick erbot-command) + "Tests whether the user `nick' is allowed to use `erbot-command', +i.e. if the user has been offered such an action." + (let* ((nicks-ht (gethash nick erbmsg-question-hash-table)) + (command-p (and nicks-ht + (gethash erbot-command nicks-ht)))) + (null (null command-p)))) +(defun erbmsg-question-user-answer (nick erbot-command &optional answer) + "Tests whether the user `nick' is allowed to use `erbot-command', +if so return 'noreply, if not return an according answer." + (or (and (not (erbmsg-question-user-allowed-p nick erbot-command)) + 'noreply) ;;; "You are currently not allowed to use this function. :(") + 'noreply)) + + +;;; dumping code +;; this code is to make erbot remember messages after restarts + +(defun erbmsg-regular-dump (&rest ignore) + "Fun wrapper to call `erbmsg-dump-tables'." + (interactive) + (erbmsg-dump-tables)) + +(defun erbmsg-dump-tables (&optional file) + "Dumps known message hash tables to a buffer in order to save it." + (interactive "Ferbmsg dump file: ") + (let ((file (or file + erbmsg-dump-file))) + (with-temp-buffer + (mapc (lambda (htable) + (insert (format "[%s \n [\n" htable)) + (maphash + (lambda (key val) + (insert + (format " [%S %s]\n" key + (cond + ((hash-table-p val) + (let (valstring) + (maphash + (lambda (k2 v2) + (setq valstring + (format "%s[%S %S]" + (or valstring "") k2 v2))) + val) + (format "(%s)" valstring))) + (t (format "%S" val)))))) + (eval htable)) + (insert (format " ]\n]\n"))) + '(erbmsg-msg-hash-table erbmsg-msg-cookie-hash-table)) + (write-file erbmsg-dump-file)))) + +(defun erbmsg-restore-tables (&optional file) + "Restores known message hash tables from FILE or `erbmsg-dump-file'." + (interactive "ferbmsg dump file: ") + (let* ((file (or file + erbmsg-dump-file)) + (file-vector + (and (file-readable-p file) + (with-temp-buffer + (insert-file-contents file) + (eval (erbn-read (format "(setq file-vector '(%s))" + (erbutils-buffer-string)))))))) + (mapvector + (lambda (tablevector) + (let ((table (aref tablevector 0)) + (vector (aref tablevector 1))) + (mapvector + (lambda (keyval) + (let ((key (aref keyval 0)) + (val (aref keyval 1))) + (cond ((listp val) + (let ((nickht (make-hash-table :test 'equal))) + (mapc + (lambda (htvec) + (let ((k2 (aref htvec 0)) + (v2 (aref htvec 1))) + (puthash k2 v2 nickht))) + val) + (puthash key nickht (eval table)))) + (t (puthash key val (eval table)))))) + vector))) + file-vector))) + +(when (and erbot-erbmsg-p + erbmsg-auto-restore-message-tables + ;;(eq (hash-table-count erbmsg-msg-hash-table) 0) + ) + (erbmsg-restore-tables)) + + +(provide 'erbmsg) + +;;; erbmsg.el ends here + +;; Local variables: +;; indent-tab-mode: nil +;; End: diff --git a/elisp/erbot/erbot-lispy.el b/elisp/erbot/erbot-lispy.el new file mode 100644 index 0000000..a63ba4c --- /dev/null +++ b/elisp/erbot/erbot-lispy.el @@ -0,0 +1,89 @@ +;;; erbot-lispy.el --- ErBot integration in Lispy +;; Time-stamp: <2006-04-20 14:14:33 deego> +;; Emacs Lisp Archive entry +;; Filename: erbot-lispy.el +;; Package: erbot +;; Authors: Yann Hodique +;; Version: 0.0 +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + +;; Lispy can be found at http://mtpforge.melting-pot.org/projects/lispy + +;; Installation +;; put an additional (require 'erbot-lispy) in you erbot's .emacs +;; *before* running (erbot-install) +;; then launch a lispy session + +(require 'lispy) +(require 'erbot) + +(defvar backup-buffer nil) + +(defun erbot-lispy-remote (line) + (let* ((nick nil) + (tgt nil) + (msg nil)) + + (cond + ((string-match "^ \\(\\w+\\) tells you: \\(.*\\)$" line) + (setq nick (match-string 1 line)) + (setq tgt nick) + (setq msg (match-string 2 line))) + ((string-match (format "^<\\(Mtp\\|%s\\)>.*$" lispy-remote-user) line) + nil) + ((string-match "^<\\(\\w+\\)> \\(.*\\)$" line) + (setq nick (match-string 1 line)) + (setq tgt "#chan") + (setq msg (match-string 2 line))) + ) + (setq backup-buffer (current-buffer)) + (when (and lispy-connected nick) + (progn + (setq erbot-end-user-nick-latest nick) + (setq fs-tgt tgt) + (setq erbn-tgt tgt) + + (setq fs-nick nick) + (setq erbn-nick nick) + + (let ((msgg + (erbeng-main msg nil nick tgt nil (list nick nick nick)))) + + (cond + (erbot-quiet-p nil) + ((and erbot-quiet-target-p-function + (funcall erbot-quiet-target-p-function tgt nick msg)) + nil) + (t (erbot-lispy-reply msgg tgt))) + )))) + nil + ) + +(defun erbot-lispy-reply (main-reply tgt) + (unless (stringp main-reply) + (setq main-reply (format "%S" main-reply))) + (let ((reply (erbot-frob-with-init-string main-reply))) + (unless + (or + (null erbot-reply-p) + (equal main-reply 'noreply) + (equal main-reply "noreply")) + ;; now we are actually gonna reply. + (setq reply (fs-limit-lines reply)) + (set-buffer backup-buffer) + (let ((lines (split-string reply "\n"))) + (mapc + (lambda (line) + (lispy-message (concat (if (string-match "^#" tgt) + (if (erbot-lispy-safe-p line) "" " ") + (format "tell %s " tgt)) line "\n"))) + lines))))) + +;; Mtp does not use prefixed commands, activate the right ones via aliases +(defun erbot-lispy-safe-p (msg) + (string-match "^/" line)) + +(defadvice erbot-install (after ad-erbot-install-lispy-after act) + (add-hook 'lispy-post-insert-hook 'erbot-lispy-remote)) + +(provide 'erbot-lispy) diff --git a/elisp/erbot/erbot.el b/elisp/erbot/erbot.el new file mode 100644 index 0000000..9769dbf --- /dev/null +++ b/elisp/erbot/erbot.el @@ -0,0 +1,961 @@ +;;; erbot.el --- Another robot for ERC. +;; Time-stamp: <2009-09-26 22:28:50 fledermaus> +;; Emacs Lisp Archive entry +;; Filename: erbot.el +;; Package: erbot +;; Authors: David Edmunston (dme@dme.org) +;; Modified by: D. Goel , V Dasmohapatra +;; Version: 0.0 +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; Maintainer: Deepak Goel + + +(defvar erbot-home-page + "http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot/") + +;; Version: +;; Keywords: ERC, IRC, chat, robot, bot + +;; Copyright (C) 2002 Deepak Goel, FSF + +;; 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 3 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 this program; if not, write to the Free Software +;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + + + +;; See also: +;; erc-robot.el from which this was derived... + + + + +;; See http://www.emacswiki.org/cgi-bin/wiki/ErBot + +;; OLD DOCS: +;; Thanks for erbot's/erbot's behavior and their data go to a lot +;; of people on #emacs, like: +;; kensanata (Alex Schroeder) +;; resolve (Damien Elmes) +;; bpt (Brian P. Templeton) +;; forcer (Jorgen "forcer" Schaefer) +;; and many others + +;; and also to bot(s): +;; apt on debian, for english syntax examples. + +;; Thanks for code go to: +;; David Edmonsdon (who wrote erc-robot.el which is what this started +;; out from). +;; Nick Hober (who wrote google.el) + + + + + + +;;; David E's Commentary: + +;; erbot is a derivative of David's erc-robot.el --- that code was +;; copied over on 2002-09-02 into erbot.el. Erbot seeks to make the +;; bot similar to apt on #debian.. viz: English style.. yet allowing +;; access to commands via the "cmd" command. Erbot shall seek to +;; save all its information periodically, and publicly... + + +;; Erc-robot implements a simple robot for ERC. + +;; Installation: + +;; The robot uses hooks to gain access to ERC. The following need to +;; be executed after ERC has loaded: + +;; (load-library "erbot") + + +;; It is particularly important that the remote robot function is added +;; to the tail of the PRIVMSG hook. + +;; Robot commands are declared using the list "erbot-commands". +;; XXX better description of the functions. +;; An example might be: + +;; (setq erbot-commands +;; '( +;; ("cmds" t (lambda (args) +;; (concat "commands available: " +;; (mapconcat +;; (lambda (e) +;; (car e)) +;; erbot-commands " ")))) +;; ("hello" t (lambda (args) "hello to you too !")) +;; ("zippy" t (lambda (args) (erc-replace-regexp-in-string "\n" " " (yow)))) +;; ("music" t (lambda (args) (concat "now playing: " +;; (let ((track (dme:now-playing))) +;; (if track +;; track +;; "nothing."))))) +;; ("echo" t (lambda (args) args)) +;; ; only i'm allowed to talk to my doctor ! +;; ("doctor" nil erc-doctor) +;; ("version" t (lambda (args) (erc-version))) +;; )) + + +; compatability +;(if (featurep 'xemacs) +; (defun erc-replace-regexp-in-string +; (regexp rep string &optional fixedcase literal subexp start) +; (replace-in-string string regexp rep literal)) + +(defalias 'erc-replace-regexp-in-string 'replace-regexp-in-string) + +(defvar erbot-paranoid-p t + " Meant as a CATCHALL for security. Setting this variable to non-nil +should disable most features. When non-nil, all potentially funny +functions are disabled. We think these functions are safe, but we +disable them in any case. We also disable all functions that we can +that may potentially freeze the bot or severly slow it down upon +receiving weird requests. + + +t by default. No enablings like erbot-setf-p, etc. will work +unless this is non-nil. If this is non-nil, erbot is paranoid, it will +not allow apply, setf, funcall, sregex, etc. even if the corresponding +variables are turned on. + +NOTE: Making this variable nil and later non-nil in the middle of a +running emacs session will NOT make your bot completely paranoid. You +need to have this function non-nil BEFORE you load erbot. See, for +example, how we define fs-kbd. +") + + + + +(defun erbot-commentary () + "Provides electric help regarding variable `erbot-commentary'." + (interactive) + (with-electric-help + '(lambda () (insert erbot-commentary) nil) "*doc*")) + +;;; History: + +;;; Bugs: + +;;; New features: +(defvar erbot-new-features + "Help..." +) + +(defun erbot-new-features () + "Provides electric help regarding variable `erbot-new-features'." + (interactive) + (with-electric-help + '(lambda () (insert erbot-new-features) nil) "*doc*")) + +;;; TO DO: +(defvar erbot-todo + "Current shortcomings:" + +) + +(defun erbot-todo () + "Provides electric help regarding variable `erbot-todo'." + (interactive) + (with-electric-help + '(lambda () (insert erbot-todo) nil) "*doc*")) + +(defvar erbot-version "0.0") + +;;========================================== +;;; Code: +(require 'cl) + +(defcustom erbot-before-load-hooks nil "" :group 'erbot) +(defcustom erbot-after-load-hooks nil "" :group 'erbot) + + + +(defcustom erbot-ignore-nicks '("^apt[0-9]?$" "bot" "google" "serv") + "A list of REGEXPS. +Nicks matching these regexps will be ignored by the bot, viz. not +generate replies. + +I would suggest including atleast bot, google and serv here to prevent +infinite chat loops with other bots. :) +" +:type '(repeat regexp) +:group 'erbot) + +(defcustom erbot-use-whitelist nil "Use a whitelist for accessing the bot. +Any request from another source will be ignored. If a source is present in whitelist +and in `erbot-ignore-nicks' it is ignored" +:type 'boolean +:group 'erbot) + +(defcustom erbot-whitelist-nicks nil +"List of the entries that have access to the bot. Used only when `erbot-use-whitelist' is non-nil" +:type '(repeat regexp) +:group 'erbot) + +(defcustom erbot-ignore-userinfos "" "list of regex's" :group 'erbot) +(run-hooks 'erbot-before-load-hooks) + + +(defgroup erbot nil + "The group erbot" + :group 'applications) + +(defcustom erbot-nick "fsbot" +"Changing this in the middle of things +may have unspecified and unpleasant results..." +:group 'erbot) + +(defvar erbot-end-user-nick "dummy-nick" + "just a temporary variable..") + +(defvar erbot-end-user-nick-latest "dummy-end-user-nick-latest" + "just a temporary variable..") + + + + + +(defcustom erbot-servers-channels + '(("irc.openprojects.net" + ("#testopn" + )) + (".gnome.org" + ("#testgnome") + ;; optional but: + 6667 + )) + "Servers and channels ..." + :group 'erbot) + + + +; (defalias 'erc-replace-regexp-in-string 'replace-regexp-in-string)) + + +(defface erbot-face '((t (:foreground "yellow"))) + "Face used for your robot's output." + :group 'erc-faces) + +(defcustom erbot-commands nil + "A list of robot commands and the functions which implement them." + :group 'erc + :type '(repeat (list string (choice (const nil) (const t) string) function)) + ) + + + +(defcustom erbot-erbmsg-p nil + "When true, erball.el loads the erbmsg module by default ") + + +(defcustom erbot-notify-p t + "Set it to t if you want RSS notification +for your erbot. + +Note that even if it is t, we will internally setq it to nil temporarily during +the inner workings of the bot. ") + +;; The next part suggested by forcer, See +;; http://www.kollektiv-hamburg.de/~forcer/erbot-notify.txt, which is +;; also copied here: + +;; erbot should include the following function lists, which are +;; called on these events with the specified arguments: + +;; erbot-notify-add-functions +;; arguments: nick channel term entry-num entry + +(defvar erbot-notify-add-functions nil + "Functions to call when an erbot add takes place. Each of these is +called with the arguments arguments: nick channel term entry-num +entry") + +;; erbot-notify-forget-functions +;; arguments: nick channel term entry-num entry +;; If entry-num is 'all, entry is a list of entries + + +;; SPECS CHANGED! +(defvar erbot-notify-forget-functions nil + "Functions to call when an erbot forget takes place. Each of these +is called with the arguments arguments: nick channel term entry-num +entry remaining-entries. If entry-num is 'all, entry is a list of +entries") + +;; erbot-notify-move-functions +;; arguments: nick channel old-term new-term + +(defvar erbot-notify-move-functions nil + "Functions to call when an erbot move operation takes place. Each +of these is called with the arguments arguments: nick channel old-term +new-term ") + +;; erbot-notify-rearrange-functions +;; arguments: nick channel term from-num from-entry to-num +;; entries + +(defvar erbot-notify-rearrange-functions nil + "Functions to call when an erbot rearrange operation takes place. Each +of these is called with the arguments arguments: nick channel term +from-num from-entry to-num entries. Entries refers to the rearranged +entries. ") + + +;; erbot-notify-substitute-functions +;; arguments: nick channel term entry-num old-entry new-entry +(defvar erbot-notify-substitute-functions nil + "Functions to call when an erbot substitute operation takes place. +Each of these is called with the arguments arguments: nick channel +term entry-num old-entry new-entry") + +;;; 2005-08-31 T10:56:27-0400 (Wednesday) D. Goel +(defvar erbot-nickserv-p nil + "When t, erbot will load the appropriate erc modules and will try to +auto-identify to nickserv. + +If using this, we recommend these settings at the *BEGINNING* of your +bot's .emacs: + + (setq erbot-nickserv-p t) + (setq erc-prompt-for-nickserv-password nil) + + (setq erc-nickserv-passwords + '((freenode ((\"mybot\" . \"mypassword\"))))) + +See this page for more details: +http://www.emacswiki.org/cgi-bin/wiki?ErcNickserv +") + +(when erbot-nickserv-p + (require 'erc-nickserv nil t) ;; old erc + (require 'erc-services nil t) ;; erc from emacs22 + (erc-nickserv-mode 1) + ) + + + + +;; erbot-notify-merge-functions +;; arguments: nick channel old-term new-term new-entries +;; NOW CHANGED SPEC! +(defvar erbot-notify-merge-functions nil + "Functions to call when an erbot merge operation takes place. +Each of these is called with the arguments arguments: nick channel +from-term to-term from-entries to-entries final-entries") + + + +; This function is used by the example above. +(defun erbot-doctor (args) + "Glue the doctor into the ERC robot." + (let* ((thisbuf (current-buffer)) + (dbuf (concat "*doctor: " (buffer-name thisbuf) "*")) + (docbuf (get-buffer dbuf)) + outpoint + res) + (if (not docbuf) + (progn + (set-buffer (get-buffer-create dbuf)) + (make-doctor-variables) + (set-buffer thisbuf) + (setq docbuf (get-buffer dbuf)) + (bury-buffer docbuf))) + (save-excursion + (set-buffer docbuf) + (goto-char (point-max)) + (insert args) + (goto-char (point-max)) + (setq outpoint (point)) + (doctor-ret-or-read 1) + (doctor-ret-or-read 1) + (goto-char outpoint) + (re-search-forward "^.") + (setq outpoint (- (point) 1)) + (re-search-forward "^$") + (erc-replace-regexp-in-string + "\n" " " (buffer-substring outpoint (point))) + ))) + + + +(defun erbot-dunnet (arg) + "Glue the dunnet into the ERC robot." + (save-excursion + (let ((freshp nil) + outpoint res ans + (pre "") + full + ) + (when (or (not (boundp 'dun-dead)) dun-dead + (not (get-buffer "*dungeon*")) + ) + (setq freshp t) + (setq dun-dead nil)) + (when freshp (dunnet)) + (set-buffer "*dungeon*") + (goto-char (point-max)) + (when (string-match "save" arg) + (setq arg "save ~/pub/dunnet/dunnet.game") + (setq pre "Will save to ~/pub/dunnet/dunnet.game")) + (cond + ((string-match "^.?more" arg) + (setq ans (fsi-more))) + (t + (unless freshp (insert arg)) + (goto-char (point-max)) + (setq outpoint (if freshp (point-min) (point))) + (unless freshp (dun-parse 1)) + (setq ans + (buffer-substring-no-properties + outpoint (- (point-max) 1))) + (when (equal arg "quit") + (when (kill-buffer "*dungeon*"))))) + (setq full (concat pre ans)) + (when + (string-match + "I don't understand that" + full) + (setq + full + (concat + full + " I am in dunnet mode. For regular fsbot, type , (dunnet-mode)"))) + full))) + +(defvar erbot-quiet-p nil + "When non-nil, the erbot only listens, never replies") +(defun erbot-quiet () + (interactive) + (setq erbot-quiet-p + (not erbot-quiet-p)) + (message "set to %S" erbot-quiet-p)) + +(defvar erbot-quiet-target-p-function nil + "A function. The function should take up to 3 arguments, TARGET +\(channel) , nick and msg. If it returns non-nil, then erbot will +listen and do everything but never reply back.") + + +(defvar erbot-on-new-erc-p nil + "Whether we use erc >1.660 with new erc-backend. +The value should not be set but is auto-guessed within +`erbot-install'.") + + +;; A very very main function.. +(defun erbot-remote (proc parsed) + "Implements a simple robot for erc. Messages to the robot are of the form: +\"nick: !command args\", where: +nick - the nickname of the user who is the target of the command, +command - the specific command, +args - arguments to the command (optional). + +For newer erc, see `erbot-on-new-erc-p' and read the specs of +the new erc-backend functions." + (set-buffer (process-buffer proc)) + (let* ( + (erbn-buffer (erc-server-buffer)) + (sspec (cond (erbot-on-new-erc-p + (erc-response.sender parsed)) + (t (aref parsed 1)))) + (userinfo (erc-parse-user sspec)) + (nick (erbutils-remove-text-properties-maybe (nth 0 userinfo))) + ;; bind fs-nick in a let.. so that changes to fs-nick are + ;; independent and do not affect each other.. when it is + ;; parsing too many messages once.. + (fs-nick nick) + (erbn-nick fs-nick) + (cmdargs (and erbot-on-new-erc-p + (erc-response.command-args parsed))) + (tgta + (erbutils-remove-text-properties-maybe + (cond (cmdargs + (nth 0 cmdargs)) + (t (aref parsed 2))))) + (tgt (if (equalp tgta (or (erc-current-nick) erbot-nick)) + nick + tgta)) + (erbn-tgt tgt) + (fs-tgt tgt) + (msg + (erbutils-remove-text-properties-maybe + (erc-response.contents parsed))) + (erbot-end-user-nick nick) + (csys (if (fboundp 'erc-coding-system-for-target) + (erc-coding-system-for-target tgt) + 'utf-8)) + (code-in (if (consp csys) (cdr csys) csys)) + (code-out (if (consp csys) (car csys) csys)) + ) + ;; changing the structure here.. + ;; also changing erbot-command to erbot-reply.. + ;; from now on, erend-main will take care of what to reply.. + ;; erbot-reply will simply take the reply and reply that... + ;; should not be setq.. else other invocations may change it.. + ;;(setq erbot-end-user-nick nick) + + (setq erbot-end-user-nick-latest erbot-end-user-nick) + ;;(setq fs-tgt tgt) + ;;(setq erbn-tgt tgt) + + ;;(setq fs-nick nick) + ;;(setq erbn-nick nick) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; make sure we decode the raw text we received... + (unless (multibyte-string-p msg) + (setq msg (decode-coding-string msg code-in))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (let ((msgg + (erbeng-main msg proc nick tgt nil userinfo))) + ;; erbot-reply needs a correct buffer... + (set-buffer (process-buffer proc)) + + (cond + (erbot-quiet-p nil) + ((and erbot-quiet-target-p-function + (funcall erbot-quiet-target-p-function tgt nick msg)) + nil) + (t (erbot-reply + msgg + proc erbn-nick erbn-tgt msg nil + ))) + + )) + nil) + + +(defun erbot-frob-with-init-string (reply) + (cond + ((or (not (stringp reply)) (string= erbot-init-string "")) reply) + (t + (with-temp-buffer + (insert reply) + (goto-char (point-min)) + (while (re-search-forward "\n" nil t) + (replace-match + (concat "\n" erbot-init-string) nil t)) + (concat erbot-init-string (erbutils-buffer-string)))))) + +(defvar erbot-init-string "" + "The basic init string.. should be concated to ALL lines of +replies... right at last.. the values it will hold will look like /msg +foo, and will be set by fs-parse-english, when that function +determines it appropriate.. +Currently: we do not use it, since we have found a better way to do +those things.. + +") + +;; this one is probably never used any more... just to make sure, +;; introduced an error command.. +;(defun erbot-local (str) +; "Funnel text typed by the local user to the local robot. See +;\"erbot-remote\" for details of the command format." +; (error "foo") +; (erbot-command erc-process (erc-current-nick) (buffer-name) str t)) + +(defcustom erbot-reply-p t + "when nil, don't reply") + +(defun erbot-toggle-reply () + (interactive) + (setq erbot-reply-p (not erbot-reply-p)) + (message "erbot-reply-p set to %S" erbot-reply-p) + ) +(defun erbot-reply (main-reply proc from tgt msg locally-generated) + "Robot worker. Should do nothing when main-reply is nil or 'noreply +or \"noreply\" + +" + (unless (stringp main-reply) + (setq main-reply (format "%S" main-reply))) + (let ( + linen + (me (or (erc-current-nick) erbot-nick)) + ;;(if (and erbot-commands + ;; (string-match (concat "^" (regexp-quote me) + ;; ": !\\([^ ]+\\) ?\\(.*\\)") msg)) + ;; ; this is a robot command to me. + ;; (let* ((cmd (substring msg (match-beginning 1) (match-end 1))) + ;; (args (substring msg (match-beginning 2))) + ;; (l (assoc cmd erbot-commands)) + ;; (allowed-users (nth 1 l)) + ;; (function (nth 2 l)) + ;; (permitted (or (eq t allowed-users) + ;; (and (eq nil allowed-users) locally-generated) + ;; (and (stringp allowed-users) + ;; (string-match allowed-users + ;; (regexp-quote from))))) + + + + ;;(reply (concat from ": " main-reply)) + ;; my frobbing of reply.. + (reply + (erbot-frob-with-init-string main-reply)) + + + (rep-buffer (erc-get-buffer tgt proc))) + ;;(if permitted + ;; (if l + ;; (funcall function args) + ;;(concat "unknown command: " cmd + ;; ": try \"cmds\"")) + ;; (concat "no access to command \"" cmd + ;; "\" for " from "."))))) + (erc-log reply) + + + (unless + (or + (null erbot-reply-p) + (equal main-reply 'noreply) + (equal main-reply "noreply")) + ;; now we are actually gonna reply. + (save-excursion + (setq reply (fs-limit-lines reply)) + (if rep-buffer (set-buffer rep-buffer) + ;;; this alternative reply somehow never gets sent out.. + ;;(setq reply (concat "msg " from " " + ;; "No private msgs.. try #testopn")) + ;;(set-buffer (erc-get-buffer tgt proc)) + (progn + (ding t) + (message "WTF? no rep-buffer? ")) + ) + + (let* ((inhibit-read-only t) + (lines (split-string reply "[\n\r]+")) + (multiline-p (< 1 (length lines))) + p) + (mapc + (lambda (line) + (when (and line + (not (erbot-safe-p line))) + (setq line (erbot-safe-make line))) + (goto-char (point-max)) + (setq p (re-search-backward (erc-prompt))) + ;;(insert (erc-format-timestamp) "<" me "> ") + (insert ;;(erc-format-timestamp) + "<" me "> ") + (erc-put-text-property 0 (length line) 'face + 'erbot-face line) + (insert line "\n") + (save-excursion + (save-match-data + (save-restriction + (narrow-to-region p (point)) + (run-hook-with-args 'erc-send-modify-hook) + (run-hook-with-args 'erc-send-post-hook)))) + (set-marker (process-mark erc-process) (point)) + (set-marker erc-insert-marker (point)) + (goto-char (point-max)) + (setq linen (concat line "\n")) + ;; fledermaus: I used to force the encoding here, but I now + ;; think that's the wrong thing to do. Hopefully if the data-path + ;; through erc->fsbot->erc is clean, erc will do the right thing + ;; to outbound data. + (erc-process-input-line linen nil multiline-p)) + lines)))))) + + +(defcustom erbot-setf-p nil + "If you want your bot to allow setf, set this symbol to non-nil at +the beginning of your .emacs") + + +(defcustom erbot-setf-symbols + '(caar cadr car cdar cddr cdr eighth elt + first fourth + ninth nth + nthcdr + second + seventh sixth + subseq substring + tenth third) +"Safe symbols for setf...") + + +;;;###autoload +(defun erbot-install () + "Run this function AFTER loading all the files..." + (interactive) + (setq erbot-on-new-erc-p + (and (boundp 'erc-server-PRIVMSG-functions) + (featurep 'erc-backend))) + (cond (erbot-on-new-erc-p + (add-hook 'erc-server-PRIVMSG-functions 'erbot-remote t) + ;; Do we need this local command thing...? + ;;(add-hook 'erc-send-completed-hook 'erbot-local t) + (add-hook 'erc-server-001-functions + 'erbot-autojoin-channels)) + (t + (add-hook 'erc-server-PRIVMSG-hook 'erbot-remote t) + ;; Do we need this local command thing...? + ;;(add-hook 'erc-send-completed-hook 'erbot-local t) + (add-hook 'erc-server-001-hook + 'erbot-autojoin-channels)) + ) + (erbot-install-symbols) + (when (and erbot-setf-p (not erbot-paranoid-p)) + (erbot-install-setf)) + ;; A running bot should have these nil, else userfunctions will not + ;; function right: + (setq eval-expression-print-length nil) + (setq eval-expression-print-level nil) + (setq print-length nil) + (setq print-level nil) + ) + + + +(defun erbot-install-setf () + (interactive) + (defalias 'fs-setf 'setf) + (require 'cl) + (let* + ( + ;; all possible symbols + ;;(syms + ;;(apropos-internal "" (lambda (a) (get a 'setf-method)))) + (syms erbot-setf-symbols) + (fssyms + (mapcar + (lambda (a) (intern (format "fs-%s" a))) + syms)) + (fsisyms + (mapcar + (lambda (a) (intern (format "fsi-%s" a))) + syms))) + (mapcar* + (lambda (a b c) + (let ((foo (get a 'setf-method))) + (when (fboundp b) (put b 'setf-method foo)) + (when (fboundp c) (put c 'setf-method foo)))) + syms fssyms fsisyms))) + + + + +(defun erbot-install-symbols () + "By now, you should have loaded all pertinent erbot files... If you +add any new functions, don't forget to run (erbot-install) AFTER +that.." + (interactive) + (let ((ss (fsi-command-list-readonly))) + (dolist (s ss) + + (if (symbolp s) + (let ((f-s (erbutils-concat-symbols 'fs- s)) + (fi-s (erbutils-concat-symbols 'fsi- s))) + + (defalias f-s fi-s) + (put f-s 'readonly t)) + (message "Ignoring fsi->fs for %s" s))))) + + + + +;;;###autoload +(defun erbot-autojoin-channels (server nick) + ;;(interactive) + (dolist (l erbot-servers-channels) + (when (string-match (car l) (process-name server)) + (dolist (chan (cadr l)) + (erc-send-command (concat "join " chan)))))) + + + +(defun erbot-get-servers () + (mapcar '(lambda (arg) (list (car arg) (caddr arg))) + erbot-servers-channels)) + + +;;;###autoload +(defun erbot-alive-p () + "Is atleast one connection still alive?" + ;;(require 'cl-extra) + (some + 'identity + (mapcar + (lambda (buf) + (save-excursion + (set-buffer buf) + (erc-process-alive))) + (erc-buffer-list)))) + +(defvar erbot-reconnection-attempts nil) + +;;;###autoload +(defun erbot-keep-alive (&rest args) + "Periodically check if atleast one connection is still alive. If +not, try to reconnect. " + (require 'idledo) + (idledo-add-periodic-action-crude + '(unless (erbot-alive-p) + (add-to-list 'erbot-reconnection-attempts + (message "Erbot trying to reconnect at %s" + (format-time-string + "%Y%m%d-%H%M-%S"))) + (ignore-errors (apply 'erbot-join-servers args))))) + +;;;###autoload +(defun erbot-join-servers (&optional server port nick + user-full-name + not-connect-arg passwd) + "Try to never join if already joined..." + (interactive) + (require 'erc) + (if (null server) + (mapcar + '(lambda (arg) + (erbot-join-servers + (car arg) (cadr arg) nick user-full-name not-connect-arg passwd) + (sit-for 1) + ) + + ;; get the list of servers + (erbot-get-servers) + + ) + (progn + ;;(if (null server) + ;; (setq server erc-server)) + ;; 2002-08-21 T11:22:35-0400 (Wednesday) D. Goel + (setq erc-current-server-my server) + (if (null port) + (setq port + (if (fboundp 'erc-compute-port) + (erc-compute-port) + erc-port))) + (setq nick (or erbot-nick (erc-compute-nick nick))) + (let* ( + (foo 'bar) + (version nil) + ;(nick + ; (if (erc-already-logged-in server port nick) + ;; (read-from-minibuffer + ;; (erc-format-message 'nick-in-use ?n nick) + ;; nick + ;; nil nil 'erc-nick-history-list) + ;; nick))) + ) + (if (and passwd (string= "" passwd)) + (setq passwd nil)) + ;; (while (erc-already-logged-in server port nick) + ;; (setq nick (read-from-minibuffer + ;; (erc-format-message 'nick-in-use ?n nick) + ;; nick + ;; nil nil 'erc-nick-history-list))) + + (run-hook-with-args 'erc-before-connect server port nick) + (if (string-match "\\(\\<[[:digit:]]+.[[:digit:]]+\\>\\)" + erc-version-string) + (setq version (string-to-number + (match-string 1 erc-version-string))) + (setq version 0)) + + (unless (erc-already-logged-in server port nick) + (if (<= 5.0 version) + (erc :server server + :port port + :nick nick + :password passwd + :full-name user-full-name) + (erc + server port nick user-full-name (not not-connect-arg) passwd) )) + )))) + + +(defun erbot-safe-make (line) + (let* ((ans line) + (rlist (string-to-list line))) + (when (string-match "^/" line) + (unless (string-match "^/me " line) + (setq ans (concat " " line)))) + (when (member-if (lambda (a) + (and (< a 32) + (not (= a 9)))) + rlist) + (setq ans "")) + (when (string-match "[\n\r]" line) + (setq ans " ")) + ans)) + + + + + +(defun erbot-safe-p (reply) + "Determine whether a reply is safe. Any newlines are simply +reported as unsafe. + +If this functions deems a reply as unsafe, you should not send it to +ERC but call `erbot-safe-make' first. " + (and + (not (string-match "[\n\r]" reply)) + ;; err on the side of caution. Demand that the 1st char. be VERY + ;; safe. + (or + (string-match "^[0-9a-zA-Z]" reply) + ;;(not (string-match "^/" reply)) -- this is bad.. since, control + ;;characters are bad... beginnning ^A for example, will send CTCP requests.. + + ;; Allow /me commands.. but only when the rest of the text has no + ;; control characters.. + (equal 0 (string-match "^/me " reply))) + ;; And there be no control characters whatsoever anywhere. + (erbot-safe-nocontrol-p reply))) + +(defun erbot-safe-nocontrol-p (reply) + (let ((rlist (string-to-list reply))) + (not (member-if (lambda (a) (< a 32)) rlist)))) + + + + + + +(defun erbot-dunnet-install () + "Defines some dunnet specific aliases. " + (interactive) + (require 'dunnet) + (defalias 'dun-read-line 'fs-botread) + ;;(defalias 'dun-mprinc + ;;'fs-dun-mprinc)) + ) + + +(defmacro erbot-working (&rest args) + `(let ((erbbdb-save-p nil) + (erbot-notify-p nil)) + ,@args)) + + + +(provide 'erbot) +(run-hooks 'erbot-after-load-hooks) + + + +;;; erbot.el ends here diff --git a/elisp/erbot/erbp.el b/elisp/erbot/erbp.el new file mode 100644 index 0000000..bc59be7 --- /dev/null +++ b/elisp/erbot/erbp.el @@ -0,0 +1,3376 @@ +;;; erbp.el --- not yet functional, personal erbot-interface, stolen from dunnet.el +;; we should perhaps remove this file, is not in use -- DG. + +;; Copyright (C) 1992, 1993, 2001 Free Software Foundation, Inc. + +;; Author: Ron Schnell +;; Created: 25 Jul 1992 +;; Version: 0.0dev +;; Keywords: games + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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 3, or (at your option) +;; any later version. + +;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; For starters, namespaces: dun, dunnet, erbpeon, mostly get mapped +;; to erbp, erbpne and erbpeon respectively. +;; room-->erbp-room + +;;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +;;; The log file should be set for your system, and it must +;;; be writable by all. + +;;; Code: + +(defgroup erbpnet nil + "Text adventure for Emacs." + :prefix "erbp-" + :group 'games) + +(defconst erbp-version "0.0dev") + +(defcustom erbp-log-file "/usr/local/erbpnet.score" + "Name of file to store score information for erbpnet." + :type 'file + :group 'erbpnet) + +(if nil + (eval-and-compile (setq byte-compile-warnings nil))) + +(eval-when-compile + (require 'cl)) + +;;;; Mode definitions for interactive mode + +(defun erbp-mode () + "Major mode for running erbpnet." + (interactive) + (text-mode) + (make-local-variable 'scroll-step) + (setq scroll-step 2) + (use-local-map erbpeon-mode-map) + (setq major-mode 'erbp-mode) + (setq mode-name "Erbpeon")) + +(defun erbp-parse (arg) + "Function called when return is pressed in interactive mode to parse line." + (interactive "*p") + (beginning-of-line) + (setq beg (+ (point) 1)) + (end-of-line) + (if (and (not (= beg (point))) (not (< (point) beg)) + (string= ">" (buffer-substring (- beg 1) beg))) + (progn + (setq line (downcase (buffer-substring beg (point)))) + (princ line) + (if (eq (erbp-vparse erbp-ignore erbp-verblist line) -1) + (erbp-mprinc "I don't understand that.\n"))) + (goto-char (point-max)) + (erbp-mprinc "\n")) + (erbp-messages)) + +(defun erbp-messages () + (if erbp-dead + (text-mode) + (if (eq erbpeon-mode 'erbpeon) + (progn + (if (not (= erbp-room erbp-current-room)) + (progn + (erbp-describe-room erbp-current-room) + (setq erbp-room erbp-current-room))) + (erbp-fix-screen) + (erbp-mprinc ">"))))) + + +;;;###autoload +(defun erbpnet () + "Switch to *erbpeon* buffer and start game." + (interactive) + (switch-to-buffer "*erbpeon*") + (erbp-mode) + (setq erbp-dead nil) + (setq erbp-room 0) + (erbp-messages)) + +;;;; +;;;; This section contains all of the verbs and commands. +;;;; + +;;; Give long description of room if haven't been there yet. Otherwise +;;; short. Also give long if we were called with negative room number. + +(defun erbp-describe-room (erbp-room) + (if (and (not (member (abs erbp-room) erbp-light-rooms)) + (not (member obj-lamp erbp-inventory))) + (erbp-mprincl "It is pitch dark. You are likely to be eaten by a grue.") + (erbp-mprincl (cadr (nth (abs erbp-room) erbp-rooms))) + (if (and (and (or (member erbp-room erbp-visited) + (string= erbp-mode "erbp-superb")) (> erbp-room 0)) + (not (string= erbp-mode "long"))) + nil + (erbp-mprinc (car (nth (abs erbp-room) erbp-rooms))) + (erbp-mprinc "\n")) + (if (not (string= erbp-mode "long")) + (if (not (member (abs erbp-room) erbp-visited)) + (setq erbp-visited (append (list (abs erbp-room)) erbp-visited)))) + (dolist (xobjs (nth erbp-current-room erbp-room-objects)) + (if (= xobjs obj-special) + (erbp-special-object) + (if (>= xobjs 0) + (erbp-mprincl (car (nth xobjs erbp-objects))) + (if (not (and (= xobjs obj-bus) erbp-inbus)) + (progn + (erbp-mprincl (car (nth (abs xobjs) erbp-perm-objects))))))) + (if (and (= xobjs obj-jar) erbp-jar) + (progn + (erbp-mprincl "The jar contains:") + (dolist (x erbp-jar) + (erbp-mprinc " ") + (erbp-mprincl (car (nth x erbp-objects))))))) + (if (and (member obj-bus (nth erbp-current-room erbp-room-objects)) erbp-inbus) + (erbp-mprincl "You are on the bus.")))) + +;;; There is a special object in the erbp-room. This object's description, +;;; or lack thereof, depends on certain conditions. + +(defun erbp-special-object () + (if (= erbp-current-room computer-room) + (if erbp-computer + (erbp-mprincl +"The panel lights are flashing in a seemingly organized pattern.") + (erbp-mprincl "The panel lights are steady and motionless."))) + + (if (and (= erbp-current-room red-room) + (not (member obj-towel (nth red-room erbp-room-objects)))) + (erbp-mprincl "There is a hole in the floor here.")) + + (if (and (= erbp-current-room marine-life-area) erbp-black) + (erbp-mprincl +"The room is lit by a black light, causing the fish, and some of +your objects, to give off an eerie glow.")) + (if (and (= erbp-current-room fourth-vermont-intersection) erbp-hole) + (progn + (if (not erbp-inbus) + (progn + (erbp-mprincl"You fall into a hole in the ground.") + (setq erbp-current-room vermont-station) + (erbp-describe-room vermont-station)) + (progn + (erbp-mprincl +"The bus falls down a hole in the ground and explodes.") + (erbp-die "burning"))))) + + (if (> erbp-current-room endgame-computer-room) + (progn + (if (not erbp-correct-answer) + (erbp-endgame-question) + (erbp-mprincl "Your question is:") + (erbp-mprincl erbp-endgame-question)))) + + (if (= erbp-current-room sauna) + (progn + (erbp-mprincl (nth erbp-sauna-level '( +"It is normal room temperature in here." +"It is luke warm in here." +"It is comfortably hot in here." +"It is refreshingly hot in here." +"You are dead now."))) + (if (= erbp-sauna-level 3) + (progn + (if (or (member obj-rms erbp-inventory) + (member obj-rms (nth erbp-current-room erbp-room-objects))) + (progn + (erbp-mprincl +"You notice the wax on your statuette beginning to melt, until it completely +melts off. You are left with a beautiful diamond!") + (if (member obj-rms erbp-inventory) + (progn + (erbp-remove-obj-from-inven obj-rms) + (setq erbp-inventory (append erbp-inventory + (list obj-diamond)))) + (erbp-remove-obj-from-room erbp-current-room obj-rms) + (erbp-replace erbp-room-objects erbp-current-room + (append (nth erbp-current-room erbp-room-objects) + (list obj-diamond)))))) + (if (or (member obj-floppy erbp-inventory) + (member obj-floppy (nth erbp-current-room erbp-room-objects))) + (progn + (erbp-mprincl +"You notice your floppy disk beginning to melt. As you grab for it, the +disk bursts into flames, and disintegrates.") + (erbp-remove-obj-from-inven obj-floppy) + (erbp-remove-obj-from-room erbp-current-room obj-floppy)))))))) + + +(defun erbp-die (murderer) + (erbp-mprinc "\n") + (if murderer + (erbp-mprincl "You are dead.")) + (erbp-do-logfile 'erbp-die murderer) + (erbp-score nil) + (setq erbp-dead t)) + +(defun erbp-quit (args) + (erbp-die nil)) + +;;; Print every object in player's inventory. Special case for the jar, +;;; as we must also print what is in it. + +(defun erbp-inven (args) + (erbp-mprinc "You currently have:") + (erbp-mprinc "\n") + (dolist (curobj erbp-inventory) + (if curobj + (progn + (erbp-mprincl (cadr (nth curobj erbp-objects))) + (if (and (= curobj obj-jar) erbp-jar) + (progn + (erbp-mprincl "The jar contains:") + (dolist (x erbp-jar) + (erbp-mprinc " ") + (erbp-mprincl (cadr (nth x erbp-objects)))))))))) + +(defun erbp-shake (obj) + (let (objnum) + (when (setq objnum (erbp-objnum-from-args-std obj)) + (if (member objnum erbp-inventory) + (progn +;;; If shaking anything will do anything, put here. + (erbp-mprinc "Shaking ") + (erbp-mprinc (downcase (cadr (nth objnum erbp-objects)))) + (erbp-mprinc " seems to have no effect.") + (erbp-mprinc "\n") + ) + (if (and (not (member objnum (nth erbp-current-room erbp-room-silents))) + (not (member objnum (nth erbp-current-room erbp-room-objects)))) + (erbp-mprincl "I don't see that here.") +;;; Shaking trees can be deadly + (if (= objnum obj-tree) + (progn + (erbp-mprinc + "You begin to shake a tree, and notice a coconut begin to fall from the air. +As you try to get your hand up to block it, you feel the impact as it lands +on your head.") + (erbp-die "a coconut")) + (if (= objnum obj-bear) + (progn + (erbp-mprinc +"As you go up to the bear, it removes your head and places it on the ground.") + (erbp-die "a bear")) + (if (< objnum 0) + (erbp-mprincl "You cannot shake that.") + (erbp-mprincl "You don't have that."))))))))) + + +(defun erbp-drop (obj) + (if erbp-inbus + (erbp-mprincl "You can't drop anything while on the bus.") + (let (objnum ptr) + (when (setq objnum (erbp-objnum-from-args-std obj)) + (if (not (setq ptr (member objnum erbp-inventory))) + (erbp-mprincl "You don't have that.") + (progn + (erbp-remove-obj-from-inven objnum) + (erbp-replace erbp-room-objects erbp-current-room + (append (nth erbp-current-room erbp-room-objects) + (list objnum))) + (erbp-mprincl "Done.") + (if (member objnum (list obj-food obj-weight obj-jar)) + (erbp-drop-check objnum)))))))) + +;;; Dropping certain things causes things to happen. + +(defun erbp-drop-check (objnum) + (if (and (= objnum obj-food) (= erbp-room bear-hangout) + (member obj-bear (nth bear-hangout erbp-room-objects))) + (progn + (erbp-mprincl +"The bear takes the food and runs away with it. He left something behind.") + (erbp-remove-obj-from-room erbp-current-room obj-bear) + (erbp-remove-obj-from-room erbp-current-room obj-food) + (erbp-replace erbp-room-objects erbp-current-room + (append (nth erbp-current-room erbp-room-objects) + (list obj-key))))) + + (if (and (= objnum obj-jar) (member obj-nitric erbp-jar) + (member obj-glycerine erbp-jar)) + (progn + (erbp-mprincl + "As the jar impacts the ground it explodes into many pieces.") + (setq erbp-jar nil) + (erbp-remove-obj-from-room erbp-current-room obj-jar) + (if (= erbp-current-room fourth-vermont-intersection) + (progn + (setq erbp-hole t) + (setq erbp-current-room vermont-station) + (erbp-mprincl +"The explosion causes a hole to open up in the ground, which you fall +through."))))) + + (if (and (= objnum obj-weight) (= erbp-current-room maze-button-room)) + (erbp-mprincl "A passageway opens."))) + +;;; Give long description of current erbp-room, or an object. + +(defun erbp-examine (obj) + (let (objnum) + (setq objnum (erbp-objnum-from-args obj)) + (if (eq objnum obj-special) + (erbp-describe-room (* erbp-current-room -1)) + (if (and (eq objnum obj-computer) + (member obj-pc (nth erbp-current-room erbp-room-silents))) + (erbp-examine '("pc")) + (if (eq objnum nil) + (erbp-mprincl "I don't know what that is.") + (if (and (not (member objnum + (nth erbp-current-room erbp-room-objects))) + (not (and (member obj-jar erbp-inventory) + (member objnum erbp-jar))) + (not (member objnum + (nth erbp-current-room erbp-room-silents))) + (not (member objnum erbp-inventory))) + (erbp-mprincl "I don't see that here.") + (if (>= objnum 0) + (if (and (= objnum obj-bone) + (= erbp-current-room marine-life-area) erbp-black) + (erbp-mprincl +"In this light you can see some writing on the bone. It says: +For an explosive time, go to Fourth St. and Vermont.") + (if (nth objnum erbp-physobj-desc) + (erbp-mprincl (nth objnum erbp-physobj-desc)) + (erbp-mprincl "I see nothing special about that."))) + (if (nth (abs objnum) erbp-permobj-desc) + (progn + (erbp-mprincl (nth (abs objnum) erbp-permobj-desc))) + (erbp-mprincl "I see nothing special about that."))))))))) + +(defun erbp-take (obj) + (setq obj (erbp-firstword obj)) + (if (not obj) + (erbp-mprincl "You must supply an object.") + (if (string= obj "all") + (let (gotsome) + (if erbp-inbus + (erbp-mprincl "You can't take anything while on the bus.") + (setq gotsome nil) + (dolist (x (nth erbp-current-room erbp-room-objects)) + (if (and (>= x 0) (not (= x obj-special))) + (progn + (setq gotsome t) + (erbp-mprinc (cadr (nth x erbp-objects))) + (erbp-mprinc ": ") + (erbp-take-object x)))) + (if (not gotsome) + (erbp-mprincl "Nothing to take.")))) + (let (objnum) + (setq objnum (cdr (assq (intern obj) erbp-objnames))) + (if (eq objnum nil) + (progn + (erbp-mprinc "I don't know what that is.") + (erbp-mprinc "\n")) + (if (and erbp-inbus (not (and (member objnum erbp-jar) + (member obj-jar erbp-inventory)))) + (erbp-mprincl "You can't take anything while on the bus.") + (erbp-take-object objnum))))))) + +(defun erbp-take-object (objnum) + (if (and (member objnum erbp-jar) (member obj-jar erbp-inventory)) + (let (newjar) + (erbp-mprincl "You remove it from the jar.") + (setq newjar nil) + (dolist (x erbp-jar) + (if (not (= x objnum)) + (setq newjar (append newjar (list x))))) + (setq erbp-jar newjar) + (setq erbp-inventory (append erbp-inventory (list objnum)))) + (if (not (member objnum (nth erbp-current-room erbp-room-objects))) + (if (not (member objnum (nth erbp-current-room erbp-room-silents))) + (erbp-mprinc "I do not see that here.") + (erbp-try-take objnum)) + (if (>= objnum 0) + (progn + (if (and (car erbp-inventory) + (> (+ (erbp-inven-weight) (nth objnum erbp-object-lbs)) 11)) + (erbp-mprinc "Your load would be too heavy.") + (setq erbp-inventory (append erbp-inventory (list objnum))) + (erbp-remove-obj-from-room erbp-current-room objnum) + (erbp-mprinc "Taken. ") + (if (and (= objnum obj-towel) (= erbp-current-room red-room)) + (erbp-mprinc + "Taking the towel reveals a hole in the floor.")))) + (erbp-try-take objnum))) + (erbp-mprinc "\n"))) + +(defun erbp-inven-weight () + (let (total) + (setq total 0) + (dolist (x erbp-jar) + (setq total (+ total (nth x erbp-object-lbs)))) + (dolist (x erbp-inventory) + (setq total (+ total (nth x erbp-object-lbs)))) total)) + +;;; We try to take an object that is untakable. Print a message +;;; depending on what it is. + +(defun erbp-try-take (obj) + (erbp-mprinc "You cannot take that.")) + +(defun erbp-dig (args) + (if erbp-inbus + (erbp-mprincl "Digging here reveals nothing.") + (if (not (member 0 erbp-inventory)) + (erbp-mprincl "You have nothing with which to dig.") + (if (not (nth erbp-current-room erbp-diggables)) + (erbp-mprincl "Digging here reveals nothing.") + (erbp-mprincl "I think you found something.") + (erbp-replace erbp-room-objects erbp-current-room + (append (nth erbp-current-room erbp-room-objects) + (nth erbp-current-room erbp-diggables))) + (erbp-replace erbp-diggables erbp-current-room nil))))) + +(defun erbp-climb (obj) + (let (objnum) + (setq objnum (erbp-objnum-from-args obj)) + (cond ((not objnum) + (erbp-mprincl "I don't know what that object is.")) + ((and (not (eq objnum obj-special)) + (not (member objnum (nth erbp-current-room erbp-room-objects))) + (not (member objnum (nth erbp-current-room erbp-room-silents))) + (not (and (member objnum erbp-jar) (member obj-jar erbp-inventory))) + (not (member objnum erbp-inventory))) + (erbp-mprincl "I don't see that here.")) + ((and (eq objnum obj-special) + (not (member obj-tree (nth erbp-current-room erbp-room-silents)))) + (erbp-mprincl "There is nothing here to climb.")) + ((and (not (eq objnum obj-tree)) (not (eq objnum obj-special))) + (erbp-mprincl "You can't climb that.")) + (t + (erbp-mprincl + "You manage to get about two feet up the tree and fall back down. You +notice that the tree is very unsteady."))))) + +(defun erbp-eat (obj) + (let (objnum) + (when (setq objnum (erbp-objnum-from-args-std obj)) + (if (not (member objnum erbp-inventory)) + (erbp-mprincl "You don't have that.") + (if (not (= objnum obj-food)) + (progn + (erbp-mprinc "You forcefully shove ") + (erbp-mprinc (downcase (cadr (nth objnum erbp-objects)))) + (erbp-mprincl " down your throat, and start choking.") + (erbp-die "choking")) + (erbp-mprincl "That tasted horrible.") + (erbp-remove-obj-from-inven obj-food)))))) + +(defun erbp-put (args) + (let (newargs objnum objnum2 obj) + (setq newargs (erbp-firstwordl args)) + (if (not newargs) + (erbp-mprincl "You must supply an object") + (setq obj (intern (car newargs))) + (setq objnum (cdr (assq obj erbp-objnames))) + (if (not objnum) + (erbp-mprincl "I don't know what that object is.") + (if (not (member objnum erbp-inventory)) + (erbp-mprincl "You don't have that.") + (setq newargs (erbp-firstwordl (cdr newargs))) + (setq newargs (erbp-firstwordl (cdr newargs))) + (if (not newargs) + (erbp-mprincl "You must supply an indirect object.") + (setq objnum2 (cdr (assq (intern (car newargs)) erbp-objnames))) + (if (and (eq objnum2 obj-computer) (= erbp-current-room pc-area)) + (setq objnum2 obj-pc)) + (if (not objnum2) + (erbp-mprincl "I don't know what that indirect object is.") + (if (and (not (member objnum2 + (nth erbp-current-room erbp-room-objects))) + (not (member objnum2 + (nth erbp-current-room erbp-room-silents))) + (not (member objnum2 erbp-inventory))) + (erbp-mprincl "That indirect object is not here.") + (erbp-put-objs objnum objnum2))))))))) + +(defun erbp-put-objs (obj1 obj2) + (if (and (= obj2 obj-drop) (not erbp-nomail)) + (setq obj2 obj-chute)) + + (if (= obj2 obj-disposal) (setq obj2 obj-chute)) + + (if (and (= obj1 obj-cpu) (= obj2 obj-computer)) + (progn + (erbp-remove-obj-from-inven obj-cpu) + (setq erbp-computer t) + (erbp-mprincl +"As you put the CPU board in the computer, it immediately springs to life. +The lights start flashing, and the fans seem to startup.")) + (if (and (= obj1 obj-weight) (= obj2 obj-button)) + (erbp-drop '("weight")) + (if (= obj2 obj-jar) ;; Put something in jar + (if (not (member obj1 (list obj-paper obj-diamond obj-emerald + obj-license obj-coins obj-egg + obj-nitric obj-glycerine))) + (erbp-mprincl "That will not fit in the jar.") + (erbp-remove-obj-from-inven obj1) + (setq erbp-jar (append erbp-jar (list obj1))) + (erbp-mprincl "Done.")) + (if (= obj2 obj-chute) ;; Put something in chute + (progn + (erbp-remove-obj-from-inven obj1) + (erbp-mprincl +"You hear it slide down the chute and off into the distance.") + (erbp-put-objs-in-treas (list obj1))) + (if (= obj2 obj-box) ;; Put key in key box + (if (= obj1 obj-key) + (progn + (erbp-mprincl +"As you drop the key, the box begins to shake. Finally it explodes +with a bang. The key seems to have vanished!") + (erbp-remove-obj-from-inven obj1) + (erbp-replace erbp-room-objects computer-room (append + (nth computer-room + erbp-room-objects) + (list obj1))) + (erbp-remove-obj-from-room erbp-current-room obj-box) + (setq erbp-key-level (1+ erbp-key-level))) + (erbp-mprincl "You can't put that in the key box!")) + + (if (and (= obj1 obj-floppy) (= obj2 obj-pc)) + (progn + (setq erbp-floppy t) + (erbp-remove-obj-from-inven obj1) + (erbp-mprincl "Done.")) + + (if (= obj2 obj-urinal) ;; Put object in urinal + (progn + (erbp-remove-obj-from-inven obj1) + (erbp-replace erbp-room-objects urinal (append + (nth urinal erbp-room-objects) + (list obj1))) + (erbp-mprincl + "You hear it plop down in some water below.")) + (if (= obj2 obj-mail) + (erbp-mprincl "The mail chute is locked.") + (if (member obj1 erbp-inventory) + (erbp-mprincl +"I don't know how to combine those objects. Perhaps you should +just try dropping it.") + (erbp-mprincl"You can't put that there."))))))))))) + +(defun erbp-type (args) + (if (not (= erbp-current-room computer-room)) + (erbp-mprincl "There is nothing here on which you could type.") + (if (not erbp-computer) + (erbp-mprincl +"You type on the keyboard, but your characters do not even echo.") + (erbp-unix-interface)))) + +;;; Various movement directions + +(defun erbp-n (args) + (erbp-move north)) + +(defun erbp-s (args) + (erbp-move south)) + +(defun erbp-e (args) + (erbp-move east)) + +(defun erbp-w (args) + (erbp-move west)) + +(defun erbp-ne (args) + (erbp-move northeast)) + +(defun erbp-se (args) + (erbp-move southeast)) + +(defun erbp-nw (args) + (erbp-move northwest)) + +(defun erbp-sw (args) + (erbp-move southwest)) + +(defun erbp-up (args) + (erbp-move up)) + +(defun erbp-down (args) + (erbp-move down)) + +(defun erbp-in (args) + (erbp-move in)) + +(defun erbp-out (args) + (erbp-move out)) + +(defun erbp-go (args) + (if (or (not (car args)) + (eq (erbp-doverb erbp-ignore erbp-verblist (car args) + (cdr (cdr args))) -1)) + (erbp-mprinc "I don't understand where you want me to go.\n"))) + +;;; Uses the erbpeon-map to figure out where we are going. If the +;;; requested direction yields 255, we know something special is +;;; supposed to happen, or perhaps you can't go that way unless +;;; certain conditions are met. + +(defun erbp-move (dir) + (if (and (not (member erbp-current-room erbp-light-rooms)) + (not (member obj-lamp erbp-inventory))) + (progn + (erbp-mprinc +"You trip over a grue and fall into a pit and break every bone in your +body.") + (erbp-die "a grue")) + (let (newroom) + (setq newroom (nth dir (nth erbp-current-room erbpeon-map))) + (if (eq newroom -1) + (erbp-mprinc "You can't go that way.\n") + (if (eq newroom 255) + (erbp-special-move dir) + (setq erbp-room -1) + (setq erbp-lastdir dir) + (if erbp-inbus + (progn + (if (or (< newroom 58) (> newroom 83)) + (erbp-mprincl "The bus cannot go this way.") + (erbp-mprincl + "The bus lurches ahead and comes to a screeching halt.") + (erbp-remove-obj-from-room erbp-current-room obj-bus) + (setq erbp-current-room newroom) + (erbp-replace erbp-room-objects newroom + (append (nth newroom erbp-room-objects) + (list obj-bus))))) + (setq erbp-current-room newroom))))))) + +;;; Movement in this direction causes something special to happen if the +;;; right conditions exist. It may be that you can't go this way unless +;;; you have a key, or a passage has been opened. + +;;; coding note: Each check of the current room is on the same 'if' level, +;;; i.e. there aren't else's. If two rooms next to each other have +;;; specials, and they are connected by specials, this could cause +;;; a problem. Be careful when adding them to consider this, and +;;; perhaps use else's. + +(defun erbp-special-move (dir) + (if (= erbp-current-room building-front) + (if (not (member obj-key erbp-inventory)) + (erbp-mprincl "You don't have a key that can open this door.") + (setq erbp-current-room old-building-hallway)) + (if (= erbp-current-room north-end-of-cave-passage) + (let (combo) + (erbp-mprincl +"You must type a 3 digit combination code to enter this room.") + (erbp-mprinc "Enter it here: ") + (setq combo (erbp-read-line)) + (if (not erbp-batch-mode) + (erbp-mprinc "\n")) + (if (string= combo erbp-combination) + (setq erbp-current-room gamma-computing-center) + (erbp-mprincl "Sorry, that combination is incorrect.")))) + + (if (= erbp-current-room bear-hangout) + (if (member obj-bear (nth bear-hangout erbp-room-objects)) + (progn + (erbp-mprinc +"The bear is very annoyed that you would be so presumptuous as to try +and walk right by it. He tells you so by tearing your head off. +") + (erbp-die "a bear")) + (erbp-mprincl "You can't go that way."))) + + (if (= erbp-current-room vermont-station) + (progn + (erbp-mprincl +"As you board the train it immediately leaves the station. It is a very +bumpy ride. It is shaking from side to side, and up and down. You +sit down in one of the chairs in order to be more comfortable.") + (erbp-mprincl +"\nFinally the train comes to a sudden stop, and the doors open, and some +force throws you out. The train speeds away.\n") + (setq erbp-current-room museum-station))) + + (if (= erbp-current-room old-building-hallway) + (if (and (member obj-key erbp-inventory) + (> erbp-key-level 0)) + (setq erbp-current-room meadow) + (erbp-mprincl "You don't have a key that can open this door."))) + + (if (and (= erbp-current-room maze-button-room) (= dir northwest)) + (if (member obj-weight (nth maze-button-room erbp-room-objects)) + (setq erbp-current-room 18) + (erbp-mprincl "You can't go that way."))) + + (if (and (= erbp-current-room maze-button-room) (= dir up)) + (if (member obj-weight (nth maze-button-room erbp-room-objects)) + (erbp-mprincl "You can't go that way.") + (setq erbp-current-room weight-room))) + + (if (= erbp-current-room classroom) + (erbp-mprincl "The door is locked.")) + + (if (or (= erbp-current-room lakefront-north) + (= erbp-current-room lakefront-south)) + (erbp-swim nil)) + + (if (= erbp-current-room reception-area) + (if (not (= erbp-sauna-level 3)) + (setq erbp-current-room health-club-front) + (erbp-mprincl +"As you exit the building, you notice some flames coming out of one of the +windows. Suddenly, the building explodes in a huge ball of fire. The flames +engulf you, and you burn to death.") + (erbp-die "burning"))) + + (if (= erbp-current-room red-room) + (if (not (member obj-towel (nth red-room erbp-room-objects))) + (setq erbp-current-room long-n-s-hallway) + (erbp-mprincl "You can't go that way."))) + + (if (and (> dir down) (> erbp-current-room gamma-computing-center) + (< erbp-current-room museum-lobby)) + (if (not (member obj-bus (nth erbp-current-room erbp-room-objects))) + (erbp-mprincl "You can't go that way.") + (if (= dir in) + (if erbp-inbus + (erbp-mprincl + "You are already in the bus!") + (if (member obj-license erbp-inventory) + (progn + (erbp-mprincl + "You board the bus and get in the driver's seat.") + (setq erbp-nomail t) + (setq erbp-inbus t)) + (erbp-mprincl "You are not licensed for this type of vehicle."))) + (if (not erbp-inbus) + (erbp-mprincl "You are already off the bus!") + (erbp-mprincl "You hop off the bus.") + (setq erbp-inbus nil)))) + (if (= erbp-current-room fifth-oaktree-intersection) + (if (not erbp-inbus) + (progn + (erbp-mprincl "You fall down the cliff and land on your head.") + (erbp-die "a cliff")) + (erbp-mprincl +"The bus flies off the cliff, and plunges to the bottom, where it explodes.") + (erbp-die "a bus accident"))) + (if (= erbp-current-room main-maple-intersection) + (progn + (if (not erbp-inbus) + (erbp-mprincl "The gate will not open.") + (erbp-mprincl +"As the bus approaches, the gate opens and you drive through.") + (erbp-remove-obj-from-room main-maple-intersection obj-bus) + (erbp-replace erbp-room-objects museum-entrance + (append (nth museum-entrance erbp-room-objects) + (list obj-bus))) + (setq erbp-current-room museum-entrance))))) + (if (= erbp-current-room cave-entrance) + (progn + (erbp-mprincl +"As you enter the room you hear a rumbling noise. You look back to see +huge rocks sliding down from the ceiling, and blocking your way out.\n") + (setq erbp-current-room misty-room))))) + +(defun erbp-long (args) + (setq erbp-mode "long")) + +(defun erbp-turn (obj) + (let (objnum direction) + (when (setq objnum (erbp-objnum-from-args-std obj)) + (if (not (or (member objnum (nth erbp-current-room erbp-room-objects)) + (member objnum (nth erbp-current-room erbp-room-silents)))) + (erbp-mprincl "I don't see that here.") + (if (not (= objnum obj-dial)) + (erbp-mprincl "You can't turn that.") + (setq direction (erbp-firstword (cdr obj))) + (if (or (not direction) + (not (or (string= direction "clockwise") + (string= direction "counterclockwise")))) + (erbp-mprincl "You must indicate clockwise or counterclockwise.") + (if (string= direction "clockwise") + (setq erbp-sauna-level (+ erbp-sauna-level 1)) + (setq erbp-sauna-level (- erbp-sauna-level 1))) + + (if (< erbp-sauna-level 0) + (progn + (erbp-mprincl + "The dial will not turn further in that direction.") + (setq erbp-sauna-level 0)) + (erbp-sauna-heat)))))))) + +(defun erbp-sauna-heat () + (if (= erbp-sauna-level 0) + (erbp-mprincl + "The temperature has returned to normal room temperature.")) + (if (= erbp-sauna-level 1) + (erbp-mprincl "It is now luke warm in here. You are perspiring.")) + (if (= erbp-sauna-level 2) + (erbp-mprincl "It is pretty hot in here. It is still very comfortable.")) + (if (= erbp-sauna-level 3) + (progn + (erbp-mprincl +"It is now very hot. There is something very refreshing about this.") + (if (or (member obj-rms erbp-inventory) + (member obj-rms (nth erbp-current-room erbp-room-objects))) + (progn + (erbp-mprincl +"You notice the wax on your statuette beginning to melt, until it completely +melts off. You are left with a beautiful diamond!") + (if (member obj-rms erbp-inventory) + (progn + (erbp-remove-obj-from-inven obj-rms) + (setq erbp-inventory (append erbp-inventory + (list obj-diamond)))) + (erbp-remove-obj-from-room erbp-current-room obj-rms) + (erbp-replace erbp-room-objects erbp-current-room + (append (nth erbp-current-room erbp-room-objects) + (list obj-diamond)))))) + (if (or (member obj-floppy erbp-inventory) + (member obj-floppy (nth erbp-current-room erbp-room-objects))) + (progn + (erbp-mprincl +"You notice your floppy disk beginning to melt. As you grab for it, the +disk bursts into flames, and disintegrates.") + (if (member obj-floppy erbp-inventory) + (erbp-remove-obj-from-inven obj-floppy) + (erbp-remove-obj-from-room erbp-current-room obj-floppy)))))) + + (if (= erbp-sauna-level 4) + (progn + (erbp-mprincl +"As the dial clicks into place, you immediately burst into flames.") + (erbp-die "burning")))) + +(defun erbp-press (obj) + (let (objnum) + (when (setq objnum (erbp-objnum-from-args-std obj)) + (if (not (or (member objnum (nth erbp-current-room erbp-room-objects)) + (member objnum (nth erbp-current-room erbp-room-silents)))) + (erbp-mprincl "I don't see that here.") + (if (not (member objnum (list obj-button obj-switch))) + (progn + (erbp-mprinc "You can't ") + (erbp-mprinc (car line-list)) + (erbp-mprincl " that.")) + (if (= objnum obj-button) + (erbp-mprincl +"As you press the button, you notice a passageway open up, but +as you release it, the passageway closes.")) + (if (= objnum obj-switch) + (if erbp-black + (progn + (erbp-mprincl "The button is now in the off position.") + (setq erbp-black nil)) + (erbp-mprincl "The button is now in the on position.") + (setq erbp-black t)))))))) + +(defun erbp-swim (args) + (if (not (member erbp-current-room (list lakefront-north lakefront-south))) + (erbp-mprincl "I see no water!") + (if (not (member obj-life erbp-inventory)) + (progn + (erbp-mprincl +"You dive in the water, and at first notice it is quite cold. You then +start to get used to it as you realize that you never really learned how +to swim.") + (erbp-die "drowning")) + (if (= erbp-current-room lakefront-north) + (setq erbp-current-room lakefront-south) + (setq erbp-current-room lakefront-north))))) + + +(defun erbp-score (args) + (if (not erbp-endgame) + (let (total) + (setq total (erbp-reg-score)) + (erbp-mprinc "You have scored ") + (erbp-mprinc total) + (erbp-mprincl " out of a possible 90 points.") total) + (erbp-mprinc "You have scored ") + (erbp-mprinc (erbp-endgame-score)) + (erbp-mprincl " endgame points out of a possible 110.") + (if (= (erbp-endgame-score) 110) + (erbp-mprincl +"\n\nCongratulations. You have won. The wizard password is 'moby'")))) + +(defun erbp-help (args) + (erbp-mprincl +"Welcome to erbpnet (2.01), by Ron Schnell (ronnie@driver-aces.com). +Here is some useful information (read carefully because there are one +or more clues in here): +- If you have a key that can open a door, you do not need to explicitly + open it. You may just use 'in' or walk in the direction of the door. + +- If you have a lamp, it is always lit. + +- You will not get any points until you manage to get treasures to a certain + place. Simply finding the treasures is not good enough. There is more + than one way to get a treasure to the special place. It is also + important that the objects get to the special place *unharmed* and + *untarnished*. You can tell if you have successfully transported the + object by looking at your score, as it changes immediately. Note that + an object can become harmed even after you have received points for it. + If this happens, your score will decrease, and in many cases you can never + get credit for it again. + +- You can save your game with the 'save' command, and use restore it + with the 'restore' command. + +- There are no limits on lengths of object names. + +- Directions are: north,south,east,west,northeast,southeast,northwest, + southwest,up,down,in,out. + +- These can be abbreviated: n,s,e,w,ne,se,nw,sw,u,d,in,out. + +- If you go down a hole in the floor without an aid such as a ladder, + you probably won't be able to get back up the way you came, if at all. + +- To run this game in batch mode (no emacs window), use: + emacs -batch -l erbpnet +NOTE: This game *should* be run in batch mode! + +If you have questions or comments, please contact ronnie@driver-aces.com +My home page is http://www.driver-aces.com/ronnie.html +")) + +(defun erbp-flush (args) + (if (not (= erbp-current-room bathroom)) + (erbp-mprincl "I see nothing to flush.") + (erbp-mprincl "Whoooosh!!") + (erbp-put-objs-in-treas (nth urinal erbp-room-objects)) + (erbp-replace erbp-room-objects urinal nil))) + +(defun erbp-piss (args) + (if (not (= erbp-current-room bathroom)) + (erbp-mprincl "You can't do that here, don't even bother trying.") + (if (not erbp-gottago) + (erbp-mprincl "I'm afraid you don't have to go now.") + (erbp-mprincl "That was refreshing.") + (setq erbp-gottago nil) + (erbp-replace erbp-room-objects urinal (append + (nth urinal erbp-room-objects) + (list obj-URINE)))))) + + +(defun erbp-sleep (args) + (if (not (= erbp-current-room bedroom)) + (erbp-mprincl +"You try to go to sleep while standing up here, but can't seem to do it.") + (setq erbp-gottago t) + (erbp-mprincl +"As soon as you start to doze off you begin dreaming. You see images of +workers digging caves, slaving in the humid heat. Then you see yourself +as one of these workers. While no one is looking, you leave the group +and walk into a room. The room is bare except for a horseshoe +shaped piece of stone in the center. You see yourself digging a hole in +the ground, then putting some kind of treasure in it, and filling the hole +with dirt again. After this, you immediately wake up."))) + +(defun erbp-break (obj) + (let (objnum) + (if (not (member obj-axe erbp-inventory)) + (erbp-mprincl "You have nothing you can use to break things.") + (when (setq objnum (erbp-objnum-from-args-std obj)) + (if (member objnum erbp-inventory) + (progn + (erbp-mprincl +"You take the object in your hands and swing the axe. Unfortunately, you miss +the object and slice off your hand. You bleed to death.") + (erbp-die "an axe")) + (if (not (or (member objnum (nth erbp-current-room erbp-room-objects)) + (member objnum + (nth erbp-current-room erbp-room-silents)))) + (erbp-mprincl "I don't see that here.") + (if (= objnum obj-cable) + (progn + (erbp-mprincl +"As you break the ethernet cable, everything starts to blur. You collapse +for a moment, then straighten yourself up. +") + (erbp-replace erbp-room-objects gamma-computing-center + (append + (nth gamma-computing-center erbp-room-objects) + erbp-inventory)) + (if (member obj-key erbp-inventory) + (progn + (setq erbp-inventory (list obj-key)) + (erbp-remove-obj-from-room + gamma-computing-center obj-key)) + (setq erbp-inventory nil)) + (setq erbp-current-room computer-room) + (setq erbp-ethernet nil) + (erbp-mprincl "Connection closed.") + (erbp-unix-interface)) + (if (< objnum 0) + (progn + (erbp-mprincl "Your axe shatters into a million pieces.") + (erbp-remove-obj-from-inven obj-axe)) + (erbp-mprincl "Your axe breaks it into a million pieces.") + (erbp-remove-obj-from-room erbp-current-room objnum))))))))) + +(defun erbp-drive (args) + (if (not erbp-inbus) + (erbp-mprincl "You cannot drive when you aren't in a vehicle.") + (erbp-mprincl "To drive while you are in the bus, just give a direction."))) + +(defun erbp-superb (args) + (setq erbp-mode 'erbp-superb)) + +(defun erbp-reg-score () + (let (total) + (setq total 0) + (dolist (x (nth treasure-room erbp-room-objects)) + (setq total (+ total (nth x erbp-object-pts)))) + (if (member obj-URINE (nth treasure-room erbp-room-objects)) + (setq total 0)) total)) + +(defun erbp-endgame-score () + (let (total) + (setq total 0) + (dolist (x (nth endgame-treasure-room erbp-room-objects)) + (setq total (+ total (nth x erbp-object-pts)))) total)) + +(defun erbp-answer (args) + (if (not erbp-correct-answer) + (erbp-mprincl "I don't believe anyone asked you anything.") + (setq args (car args)) + (if (not args) + (erbp-mprincl "You must give the answer on the same line.") + (if (erbp-members args erbp-correct-answer) + (progn + (erbp-mprincl "Correct.") + (if (= erbp-lastdir 0) + (setq erbp-current-room (1+ erbp-current-room)) + (setq erbp-current-room (- erbp-current-room 1))) + (setq erbp-correct-answer nil)) + (erbp-mprincl "That answer is incorrect."))))) + +(defun erbp-endgame-question () +(if (not erbp-endgame-questions) + (progn + (erbp-mprincl "Your question is:") + (erbp-mprincl "No more questions, just do 'answer foo'.") + (setq erbp-correct-answer '("foo"))) + (let (which i newques) + (setq i 0) + (setq newques nil) + (setq which (random (length erbp-endgame-questions))) + (erbp-mprincl "Your question is:") + (erbp-mprincl (setq erbp-endgame-question (car + (nth which + erbp-endgame-questions)))) + (setq erbp-correct-answer (cdr (nth which erbp-endgame-questions))) + (while (< i which) + (setq newques (append newques (list (nth i erbp-endgame-questions)))) + (setq i (1+ i))) + (setq i (1+ which)) + (while (< i (length erbp-endgame-questions)) + (setq newques (append newques (list (nth i erbp-endgame-questions)))) + (setq i (1+ i))) + (setq erbp-endgame-questions newques)))) + +(defun erbp-power (args) + (if (not (= erbp-current-room pc-area)) + (erbp-mprincl "That operation is not applicable here.") + (if (not erbp-floppy) + (erbp-dos-no-disk) + (erbp-dos-interface)))) + +(defun erbp-feed (args) + (let (objnum) + (when (setq objnum (erbp-objnum-from-args-std args)) + (if (and (= objnum obj-bear) + (member obj-bear (nth erbp-current-room erbp-room-objects))) + (progn + (if (not (member obj-food erbp-inventory)) + (erbp-mprincl "You have nothing with which to feed it.") + (erbp-drop '("food")))) + (if (not (or (member objnum (nth erbp-current-room erbp-room-objects)) + (member objnum erbp-inventory) + (member objnum (nth erbp-current-room erbp-room-silents)))) + (erbp-mprincl "I don't see that here.") + (erbp-mprincl "You cannot feed that.")))))) + + +;;;; +;;;; This section defines various utility functions used +;;;; by erbpnet. +;;;; + + +;;; Function which takes a verb and a list of other words. Calls proper +;;; function associated with the verb, and passes along the other words. + +(defun erbp-doverb (erbp-ignore erbp-verblist verb rest) + (if (not verb) + nil + (if (member (intern verb) erbp-ignore) + (if (not (car rest)) -1 + (erbp-doverb erbp-ignore erbp-verblist (car rest) (cdr rest))) + (if (not (cdr (assq (intern verb) erbp-verblist))) -1 + (setq erbp-numcmds (1+ erbp-numcmds)) + (eval (list (cdr (assq (intern verb) erbp-verblist)) (quote rest))))))) + + +;;; Function to take a string and change it into a list of lowercase words. + +(defun erbp-listify-string (strin) + (let (pos ret-list end-pos) + (setq pos 0) + (setq ret-list nil) + (while (setq end-pos (string-match "[ ,:;]" (substring strin pos))) + (setq end-pos (+ end-pos pos)) + (if (not (= end-pos pos)) + (setq ret-list (append ret-list (list + (downcase + (substring strin pos end-pos)))))) + (setq pos (+ end-pos 1))) ret-list)) + +(defun erbp-listify-string2 (strin) + (let (pos ret-list end-pos) + (setq pos 0) + (setq ret-list nil) + (while (setq end-pos (string-match " " (substring strin pos))) + (setq end-pos (+ end-pos pos)) + (if (not (= end-pos pos)) + (setq ret-list (append ret-list (list + (downcase + (substring strin pos end-pos)))))) + (setq pos (+ end-pos 1))) ret-list)) + +(defun erbp-replace (list n number) + (rplaca (nthcdr n list) number)) + + +;;; Get the first non-ignored word from a list. + +(defun erbp-firstword (list) + (if (not (car list)) + nil + (while (and list (member (intern (car list)) erbp-ignore)) + (setq list (cdr list))) + (car list))) + +(defun erbp-firstwordl (list) + (if (not (car list)) + nil + (while (and list (member (intern (car list)) erbp-ignore)) + (setq list (cdr list))) + list)) + +;;; parse a line passed in as a string Call the proper verb with the +;;; rest of the line passed in as a list. + +(defun erbp-vparse (erbp-ignore erbp-verblist line) + (erbp-mprinc "\n") + (setq line-list (erbp-listify-string (concat line " "))) + (erbp-doverb erbp-ignore erbp-verblist (car line-list) (cdr line-list))) + +(defun erbp-parse2 (erbp-ignore erbp-verblist line) + (erbp-mprinc "\n") + (setq line-list (erbp-listify-string2 (concat line " "))) + (erbp-doverb erbp-ignore erbp-verblist (car line-list) (cdr line-list))) + +;;; Read a line, in window mode + +(defun erbp-read-line () + (let (line) + (setq line (read-string "")) + (erbp-mprinc line) line)) + +;;; Insert something into the window buffer + +(defun erbp-minsert (string) + (if (stringp string) + (insert string) + (insert (prin1-to-string string)))) + +;;; Print something out, in window mode + +(defun erbp-mprinc (string) + (if (stringp string) + (insert string) + (insert (prin1-to-string string)))) + +;;; In window mode, keep screen from jumping by keeping last line at +;;; the bottom of the screen. + +(defun erbp-fix-screen () + (interactive) + (forward-line (- 0 (- (window-height) 2 ))) + (set-window-start (selected-window) (point)) + (end-of-buffer)) + +;;; Insert something into the buffer, followed by newline. + +(defun erbp-minsertl (string) + (erbp-minsert string) + (erbp-minsert "\n")) + +;;; Print something, followed by a newline. + +(defun erbp-mprincl (string) + (erbp-mprinc string) + (erbp-mprinc "\n")) + +;;; Function which will get an object number given the list of +;;; words in the command, except for the verb. + +(defun erbp-objnum-from-args (obj) + (let (objnum) + (setq obj (erbp-firstword obj)) + (if (not obj) + obj-special + (setq objnum (cdr (assq (intern obj) erbp-objnames)))))) + +(defun erbp-objnum-from-args-std (obj) + (let (result) + (if (eq (setq result (erbp-objnum-from-args obj)) obj-special) + (erbp-mprincl "You must supply an object.")) + (if (eq result nil) + (erbp-mprincl "I don't know what that is.")) + (if (eq result obj-special) + nil + result))) + +;;; Take a short room description, and change spaces and slashes to dashes. + +(defun erbp-space-to-hyphen (string) + (let (space) + (if (setq space (string-match "[ /]" string)) + (progn + (setq string (concat (substring string 0 space) "-" + (substring string (1+ space)))) + (erbp-space-to-hyphen string)) + string))) + +;;; Given a unix style pathname, build a list of path components (recursive) + +(defun erbp-get-path (dirstring startlist) + (let (slash pos) + (if (= (length dirstring) 0) + startlist + (if (string= (substring dirstring 0 1) "/") + (erbp-get-path (substring dirstring 1) (append startlist (list "/"))) + (if (not (setq slash (string-match "/" dirstring))) + (append startlist (list dirstring)) + (erbp-get-path (substring dirstring (1+ slash)) + (append startlist + (list (substring dirstring 0 slash))))))))) + + +;;; Is a string a member of a string list? + +(defun erbp-members (string string-list) + (let (found) + (setq found nil) + (dolist (x string-list) + (if (string= x string) + (setq found t))) found)) + +;;; Function to put objects in the treasure room. Also prints current +;;; score to let user know he has scored. + +(defun erbp-put-objs-in-treas (objlist) + (let (oscore newscore) + (setq oscore (erbp-reg-score)) + (erbp-replace erbp-room-objects 0 (append (nth 0 erbp-room-objects) objlist)) + (setq newscore (erbp-reg-score)) + (if (not (= oscore newscore)) + (erbp-score nil)))) + +;;; Load an encrypted file, and eval it. + +(defun erbp-load-d (filename) + (let (old-buffer result) + (setq result t) + (setq old-buffer (current-buffer)) + (switch-to-buffer (get-buffer-create "*loadc*")) + (erase-buffer) + (condition-case nil + (insert-file-contents filename) + (error (setq result nil))) + (unless (not result) + (condition-case nil + (erbp-rot13) + (error (yank))) + (eval-current-buffer) + (kill-buffer (current-buffer))) + (switch-to-buffer old-buffer) + result)) + +;;; Functions to remove an object either from a room, or from inventory. + +(defun erbp-remove-obj-from-room (erbp-room objnum) + (let (newroom) + (setq newroom nil) + (dolist (x (nth erbp-room erbp-room-objects)) + (if (not (= x objnum)) + (setq newroom (append newroom (list x))))) + (rplaca (nthcdr erbp-room erbp-room-objects) newroom))) + +(defun erbp-remove-obj-from-inven (objnum) + (let (new-inven) + (setq new-inven nil) + (dolist (x erbp-inventory) + (if (not (= x objnum)) + (setq new-inven (append new-inven (list x))))) + (setq erbp-inventory new-inven))) + + +(let ((i 0) (lower "abcdefghijklmnopqrstuvwxyz") upper) + (setq erbp-translate-table (make-vector 256 0)) + (while (< i 256) + (aset erbp-translate-table i i) + (setq i (1+ i))) + (setq lower (concat lower lower)) + (setq upper (upcase lower)) + (setq i 0) + (while (< i 26) + (aset erbp-translate-table (+ ?a i) (aref lower (+ i 13))) + (aset erbp-translate-table (+ ?A i) (aref upper (+ i 13))) + (setq i (1+ i)))) + +(defun erbp-rot13 () + (let (str len (i 0)) + (setq str (buffer-substring (point-min) (point-max))) + (setq len (length str)) + (while (< i len) + (aset str i (aref erbp-translate-table (aref str i))) + (setq i (1+ i))) + (erase-buffer) + (insert str))) + +;;;; +;;;; This section defines the globals that are used in erbpnet. +;;;; +;;;; IMPORTANT +;;;; All globals which can change must be saved from 'save-game. Add +;;;; all new globals to bottom of file. + +(setq erbp-visited '(27)) +(setq erbp-current-room 1) +(setq erbp-exitf nil) +(setq erbp-badcd nil) +(defvar erbpeon-mode-map nil) +(setq erbpeon-mode-map (make-sparse-keymap)) +(define-key erbpeon-mode-map "\r" 'erbp-parse) +(defvar erbpeon-batch-map (make-keymap)) +(if (string= (substring emacs-version 0 2) "18") + (let (n) + (setq n 32) + (while (< 0 (setq n (- n 1))) + (aset erbpeon-batch-map n 'erbpeon-nil))) + (let (n) + (setq n 32) + (while (< 0 (setq n (- n 1))) + (aset (car (cdr erbpeon-batch-map)) n 'erbpeon-nil)))) +(define-key erbpeon-batch-map "\r" 'exit-minibuffer) +(define-key erbpeon-batch-map "\n" 'exit-minibuffer) +(setq erbp-computer nil) +(setq erbp-floppy nil) +(setq erbp-key-level 0) +(setq erbp-hole nil) +(setq erbp-correct-answer nil) +(setq erbp-lastdir 0) +(setq erbp-numsaves 0) +(setq erbp-jar nil) +(setq erbp-dead nil) +(setq room 0) +(setq erbp-numcmds 0) +(setq erbp-wizard nil) +(setq erbp-endgame-question nil) +(setq erbp-logged-in nil) +(setq erbpeon-mode 'erbpeon) +(setq erbp-unix-verbs '((ls . erbp-ls) (ftp . erbp-ftp) (echo . erbp-echo) + (exit . erbp-uexit) (cd . erbp-cd) (pwd . erbp-pwd) + (rlogin . erbp-rlogin) (uncompress . erbp-uncompress) + (cat . erbp-cat) (zippy . erbp-zippy))) + +(setq erbp-dos-verbs '((dir . erbp-dos-dir) (type . erbp-dos-type) + (exit . erbp-dos-exit) (command . erbp-dos-spawn) + (b: . erbp-dos-invd) (c: . erbp-dos-invd) + (a: . erbp-dos-nil))) + + +(setq erbp-batch-mode nil) + +(setq erbp-cdpath "/usr/toukmond") +(setq erbp-cdroom -10) +(setq erbp-uncompressed nil) +(setq erbp-ethernet t) +(setq erbp-restricted + '(erbp-room-objects erbpeon-map erbp-rooms + erbp-room-silents erbp-combination)) +(setq erbp-ftptype 'ascii) +(setq erbp-endgame nil) +(setq erbp-gottago t) +(setq erbp-black nil) + +(setq erbp-rooms '( + ( +"You are in the treasure room. A door leads out to the north." + "Treasure room" + ) + ( +"You are at a dead end of a dirt road. The road goes to the east. +In the distance you can see that it will eventually fork off. The +trees here are very tall royal palms, and they are spaced equidistant +from each other." + "Dead end" + ) + ( +"You are on the continuation of a dirt road. There are more trees on +both sides of you. The road continues to the east and west." + "E/W Dirt road" + ) + ( +"You are at a fork of two passages, one to the northeast, and one to the +southeast. The ground here seems very soft. You can also go back west." + "Fork" + ) + ( +"You are on a northeast/southwest road." + "NE/SW road" + ) + ( +"You are at the end of the road. There is a building in front of you +to the northeast, and the road leads back to the southwest." + "Building front" + ) + ( +"You are on a southeast/northwest road." + "SE/NW road" + ) + ( +"You are standing at the end of a road. A passage leads back to the +northwest." + "Bear hangout" + ) + ( +"You are in the hallway of an old building. There are rooms to the east +and west, and doors leading out to the north and south." + "Old Building hallway" + ) + ( +"You are in a mailroom. There are many bins where the mail is usually +kept. The exit is to the west." + "Mailroom" + ) + ( +"You are in a computer room. It seems like most of the equipment has +been removed. There is a VAX 11/780 in front of you, however, with +one of the cabinets wide open. A sign on the front of the machine +says: This VAX is named 'pokey'. To type on the console, use the +'type' command. The exit is to the east." + "Computer room" + ) + ( +"You are in a meadow in the back of an old building. A small path leads +to the west, and a door leads to the south." + "Meadow" + ) + ( +"You are in a round, stone room with a door to the east. There +is a sign on the wall that reads: 'receiving room'." + "Receiving room" + ) + ( +"You are at the south end of a hallway that leads to the north. There +are rooms to the east and west." + "Northbound Hallway" + ) + ( +"You are in a sauna. There is nothing in the room except for a dial +on the wall. A door leads out to west." + "Sauna" + ) + ( +"You are at the end of a north/south hallway. You can go back to the south, +or off to a room to the east." + "End of N/S Hallway" + ) + ( +"You are in an old weight room. All of the equipment is either destroyed +or completely broken. There is a door out to the west, and there is a ladder +leading down a hole in the floor." + "Weight room" ;16 + ) + ( +"You are in a maze of twisty little passages, all alike. +There is a button on the ground here." + "Maze button room" + ) + ( +"You are in a maze of little twisty passages, all alike." + "Maze" + ) + ( +"You are in a maze of thirsty little passages, all alike." + "Maze" ;19 + ) + ( +"You are in a maze of twenty little passages, all alike." + "Maze" + ) + ( +"You are in a daze of twisty little passages, all alike." + "Maze" ;21 + ) + ( +"You are in a maze of twisty little cabbages, all alike." + "Maze" ;22 + ) + ( +"You are in a reception area for a health and fitness center. The place +appears to have been recently ransacked, and nothing is left. There is +a door out to the south, and a crawlspace to the southeast." + "Reception area" + ) + ( +"You are outside a large building to the north which used to be a health +and fitness center. A road leads to the south." + "Health Club front" + ) + ( +"You are at the north side of a lake. On the other side you can see +a road which leads to a cave. The water appears very deep." + "Lakefront North" + ) + ( +"You are at the south side of a lake. A road goes to the south." + "Lakefront South" + ) + ( +"You are in a well-hidden area off to the side of a road. Back to the +northeast through the brush you can see the bear hangout." + "Hidden area" + ) + ( +"The entrance to a cave is to the south. To the north, a road leads +towards a deep lake. On the ground nearby there is a chute, with a sign +that says 'put treasures here for points'." + "Cave Entrance" ;28 + ) + ( +"You are in a misty, humid room carved into a mountain. +To the north is the remains of a rockslide. To the east, a small +passage leads away into the darkness." ;29 + "Misty Room" + ) + ( +"You are in an east/west passageway. The walls here are made of +multicolored rock and are quite beautiful." + "Cave E/W passage" ;30 + ) + ( +"You are at the junction of two passages. One goes north/south, and +the other goes west." + "N/S/W Junction" ;31 + ) + ( +"You are at the north end of a north/south passageway. There are stairs +leading down from here. There is also a door leading west." + "North end of cave passage" ;32 + ) + ( +"You are at the south end of a north/south passageway. There is a hole +in the floor here, into which you could probably fit." + "South end of cave passage" ;33 + ) + ( +"You are in what appears to be a worker's bedroom. There is a queen- +sized bed in the middle of the room, and a painting hanging on the +wall. A door leads to another room to the south, and stairways +lead up and down." + "Bedroom" ;34 + ) + ( +"You are in a bathroom built for workers in the cave. There is a +urinal hanging on the wall, and some exposed pipes on the opposite +wall where a sink used to be. To the north is a bedroom." + "Bathroom" ;35 + ) + ( +"This is a marker for the urinal. User will not see this, but it +is a room that can contain objects." + "Urinal" ;36 + ) + ( +"You are at the northeast end of a northeast/southwest passageway. +Stairs lead up out of sight." + "NE end of NE/SW cave passage" ;37 + ) + ( +"You are at the junction of northeast/southwest and east/west passages." + "NE/SW-E/W junction" ;38 + ) + ( +"You are at the southwest end of a northeast/southwest passageway." + "SW end of NE/SW cave passage" ;39 + ) + ( +"You are at the east end of an E/W passage. There are stairs leading up +to a room above." + "East end of E/W cave passage" ;40 + ) + ( +"You are at the west end of an E/W passage. There is a hole on the ground +which leads down out of sight." + "West end of E/W cave passage" ;41 + ) + ( +"You are in a room which is bare, except for a horseshoe shaped boulder +in the center. Stairs lead down from here." ;42 + "Horseshoe boulder room" + ) + ( +"You are in a room which is completely empty. Doors lead out to the north +and east." + "Empty room" ;43 + ) + ( +"You are in an empty room. Interestingly enough, the stones in this +room are painted blue. Doors lead out to the east and south." ;44 + "Blue room" + ) + ( +"You are in an empty room. Interestingly enough, the stones in this +room are painted yellow. Doors lead out to the south and west." ;45 + "Yellow room" + ) + ( +"You are in an empty room. Interestingly enough, the stones in this room +are painted red. Doors lead out to the west and north." + "Red room" ;46 + ) + ( +"You are in the middle of a long north/south hallway." ;47 + "Long n/s hallway" + ) + ( +"You are 3/4 of the way towards the north end of a long north/south hallway." + "3/4 north" ;48 + ) + ( +"You are at the north end of a long north/south hallway. There are stairs +leading upwards." + "North end of long hallway" ;49 + ) + ( +"You are 3/4 of the way towards the south end of a long north/south hallway." + "3/4 south" ;50 + ) + ( +"You are at the south end of a long north/south hallway. There is a hole +to the south." + "South end of long hallway" ;51 + ) + ( +"You are at a landing in a stairwell which continues up and down." + "Stair landing" ;52 + ) + ( +"You are at the continuation of an up/down staircase." + "Up/down staircase" ;53 + ) + ( +"You are at the top of a staircase leading down. A crawlway leads off +to the northeast." + "Top of staircase." ;54 + ) + ( +"You are in a crawlway that leads northeast or southwest." + "NE crawlway" ;55 + ) + ( +"You are in a small crawlspace. There is a hole in the ground here, and +a small passage back to the southwest." + "Small crawlspace" ;56 + ) + ( +"You are in the Gamma Computing Center. An IBM 3090/600s is whirring +away in here. There is an ethernet cable coming out of one of the units, +and going through the ceiling. There is no console here on which you +could type." + "Gamma computing center" ;57 + ) + ( +"You are near the remains of a post office. There is a mail drop on the +face of the building, but you cannot see where it leads. A path leads +back to the east, and a road leads to the north." + "Post office" ;58 + ) + ( +"You are at the intersection of Main Street and Maple Ave. Main street +runs north and south, and Maple Ave runs east off into the distance. +If you look north and east you can see many intersections, but all of +the buildings that used to stand here are gone. Nothing remains except +street signs. +There is a road to the northwest leading to a gate that guards a building." + "Main-Maple intersection" ;59 + ) + ( +"You are at the intersection of Main Street and the west end of Oaktree Ave." + "Main-Oaktree intersection" ;60 + ) + ( +"You are at the intersection of Main Street and the west end of Vermont Ave." + "Main-Vermont intersection" ;61 + ) + ( +"You are at the north end of Main Street at the west end of Sycamore Ave." ;62 + "Main-Sycamore intersection" + ) + ( +"You are at the south end of First Street at Maple Ave." ;63 + "First-Maple intersection" + ) + ( +"You are at the intersection of First Street and Oaktree Ave." ;64 + "First-Oaktree intersection" + ) + ( +"You are at the intersection of First Street and Vermont Ave." ;65 + "First-Vermont intersection" + ) + ( +"You are at the north end of First Street at Sycamore Ave." ;66 + "First-Sycamore intersection" + ) + ( +"You are at the south end of Second Street at Maple Ave." ;67 + "Second-Maple intersection" + ) + ( +"You are at the intersection of Second Street and Oaktree Ave." ;68 + "Second-Oaktree intersection" + ) + ( +"You are at the intersection of Second Street and Vermont Ave." ;69 + "Second-Vermont intersection" + ) + ( +"You are at the north end of Second Street at Sycamore Ave." ;70 + "Second-Sycamore intersection" + ) + ( +"You are at the south end of Third Street at Maple Ave." ;71 + "Third-Maple intersection" + ) + ( +"You are at the intersection of Third Street and Oaktree Ave." ;72 + "Third-Oaktree intersection" + ) + ( +"You are at the intersection of Third Street and Vermont Ave." ;73 + "Third-Vermont intersection" + ) + ( +"You are at the north end of Third Street at Sycamore Ave." ;74 + "Third-Sycamore intersection" + ) + ( +"You are at the south end of Fourth Street at Maple Ave." ;75 + "Fourth-Maple intersection" + ) + ( +"You are at the intersection of Fourth Street and Oaktree Ave." ;76 + "Fourth-Oaktree intersection" + ) + ( +"You are at the intersection of Fourth Street and Vermont Ave." ;77 + "Fourth-Vermont intersection" + ) + ( +"You are at the north end of Fourth Street at Sycamore Ave." ;78 + "Fourth-Sycamore intersection" + ) + ( +"You are at the south end of Fifth Street at the east end of Maple Ave." ;79 + "Fifth-Maple intersection" + ) + ( +"You are at the intersection of Fifth Street and the east end of Oaktree Ave. +There is a cliff off to the east." + "Fifth-Oaktree intersection" ;80 + ) + ( +"You are at the intersection of Fifth Street and the east end of Vermont Ave." + "Fifth-Vermont intersection" ;81 + ) + ( +"You are at the north end of Fifth Street and the east end of Sycamore Ave." + "Fifth-Sycamore intersection" ;82 + ) + ( +"You are in front of the Museum of Natural History. A door leads into +the building to the north, and a road leads to the southeast." + "Museum entrance" ;83 + ) + ( +"You are in the main lobby for the Museum of Natural History. In the center +of the room is the huge skeleton of a dinosaur. Doors lead out to the +south and east." + "Museum lobby" ;84 + ) + ( +"You are in the geological display. All of the objects that used to +be on display are missing. There are rooms to the east, west, and +north." + "Geological display" ;85 + ) + ( +"You are in the marine life area. The room is filled with fish tanks, +which are filled with dead fish that have apparently died due to +starvation. Doors lead out to the south and east." + "Marine life area" ;86 + ) + ( +"You are in some sort of maintenance room for the museum. There is a +switch on the wall labeled 'BL'. There are doors to the west and north." + "Maintenance room" ;87 + ) + ( +"You are in a classroom where school children were taught about natural +history. On the blackboard is written, 'No children allowed downstairs.' +There is a door to the east with an 'exit' sign on it. There is another +door to the west." + "Classroom" ;88 + ) + ( +"You are at the Vermont St. subway station. A train is sitting here waiting." + "Vermont station" ;89 + ) + ( +"You are at the Museum subway stop. A passage leads off to the north." + "Museum station" ;90 + ) + ( +"You are in a north/south tunnel." + "N/S tunnel" ;91 + ) + ( +"You are at the north end of a north/south tunnel. Stairs lead up and +down from here. There is a garbage disposal here." + "North end of N/S tunnel" ;92 + ) + ( +"You are at the top of some stairs near the subway station. There is +a door to the west." + "Top of subway stairs" ;93 + ) + ( +"You are at the bottom of some stairs near the subway station. There is +a room to the northeast." + "Bottom of subway stairs" ;94 + ) + ( +"You are in another computer room. There is a computer in here larger +than you have ever seen. It has no manufacturers name on it, but it +does have a sign that says: This machine's name is 'endgame'. The +exit is to the southwest. There is no console here on which you could +type." + "Endgame computer room" ;95 + ) + ( +"You are in a north/south hallway." + "Endgame N/S hallway" ;96 + ) + ( +"You have reached a question room. You must answer a question correctly in +order to get by. Use the 'answer' command to answer the question." + "Question room 1" ;97 + ) + ( +"You are in a north/south hallway." + "Endgame N/S hallway" ;98 + ) + ( +"You are in a second question room." + "Question room 2" ;99 + ) + ( +"You are in a north/south hallway." + "Endgame N/S hallway" ;100 + ) + ( +"You are in a third question room." + "Question room 3" ;101 + ) + ( +"You are in the endgame treasure room. A door leads out to the north, and +a hallway leads to the south." + "Endgame treasure room" ;102 + ) + ( +"You are in the winner's room. A door leads back to the south." + "Winner's room" ;103 + ) + ( +"You have reached a dead end. There is a PC on the floor here. Above +it is a sign that reads: + Type the 'reset' command to type on the PC. +A hole leads north." + "PC area" ;104 + ) +)) + +(setq erbp-light-rooms '(0 1 2 3 4 5 6 7 8 9 10 11 12 13 24 25 26 27 28 58 59 + 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 + 77 78 79 80 81 82 83)) + +(setq erbp-verblist '((die . erbp-die) (ne . erbp-ne) (north . erbp-n) + (south . erbp-s) (east . erbp-e) (west . erbp-w) + (u . erbp-up) (d . erbp-down) (i . erbp-inven) + (inventory . erbp-inven) (look . erbp-examine) (n . erbp-n) + (s . erbp-s) (e . erbp-e) (w . erbp-w) (se . erbp-se) + (nw . erbp-nw) (sw . erbp-sw) (up . erbp-up) + (down . erbp-down) (in . erbp-in) (out . erbp-out) + (go . erbp-go) (drop . erbp-drop) (southeast . erbp-se) + (southwest . erbp-sw) (northeast . erbp-ne) + (northwest . erbp-nw) (save . erbp-save-game) + (restore . erbp-restore) (long . erbp-long) (dig . erbp-dig) + (shake . erbp-shake) (wave . erbp-shake) + (examine . erbp-examine) (describe . erbp-examine) + (climb . erbp-climb) (eat . erbp-eat) (put . erbp-put) + (type . erbp-type) (insert . erbp-put) + (score . erbp-score) (help . erbp-help) (quit . erbp-quit) + (read . erbp-examine) (verbose . erbp-long) + (urinate . erbp-piss) (piss . erbp-piss) + (flush . erbp-flush) (sleep . erbp-sleep) (lie . erbp-sleep) + (x . erbp-examine) (break . erbp-break) (drive . erbp-drive) + (board . erbp-in) (enter . erbp-in) (turn . erbp-turn) + (press . erbp-press) (push . erbp-press) (swim . erbp-swim) + (on . erbp-in) (off . erbp-out) (chop . erbp-break) + (switch . erbp-press) (cut . erbp-break) (exit . erbp-out) + (leave . erbp-out) (reset . erbp-power) (flick . erbp-press) + (superb . erbp-superb) (answer . erbp-answer) + (throw . erbp-drop) (l . erbp-examine) (take . erbp-take) + (get . erbp-take) (feed . erbp-feed))) + +(setq erbp-inbus nil) +(setq erbp-nomail nil) +(setq erbp-ignore '(the to at)) +(setq erbp-mode 'moby) +(setq erbp-sauna-level 0) + +(defconst north 0) +(defconst south 1) +(defconst east 2) +(defconst west 3) +(defconst northeast 4) +(defconst southeast 5) +(defconst northwest 6) +(defconst southwest 7) +(defconst up 8) +(defconst down 9) +(defconst in 10) +(defconst out 11) + +(setq erbpeon-map '( +; no so ea we ne se nw sw up do in ot + ( 96 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;0 + ( -1 -1 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;1 + ( -1 -1 3 1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;2 + ( -1 -1 -1 2 4 6 -1 -1 -1 -1 -1 -1 ) ;3 + ( -1 -1 -1 -1 5 -1 -1 3 -1 -1 -1 -1 ) ;4 + ( -1 -1 -1 -1 255 -1 -1 4 -1 -1 255 -1 ) ;5 + ( -1 -1 -1 -1 -1 7 3 -1 -1 -1 -1 -1 ) ;6 + ( -1 -1 -1 -1 -1 255 6 27 -1 -1 -1 -1 ) ;7 + ( 255 5 9 10 -1 -1 -1 5 -1 -1 -1 5 ) ;8 + ( -1 -1 -1 8 -1 -1 -1 -1 -1 -1 -1 -1 ) ;9 + ( -1 -1 8 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;10 + ( -1 8 -1 58 -1 -1 -1 -1 -1 -1 -1 -1 ) ;11 + ( -1 -1 13 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;12 + ( 15 -1 14 12 -1 -1 -1 -1 -1 -1 -1 -1 ) ;13 + ( -1 -1 -1 13 -1 -1 -1 -1 -1 -1 -1 -1 ) ;14 + ( -1 13 16 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;15 + ( -1 -1 -1 15 -1 -1 -1 -1 -1 17 16 -1 ) ;16 + ( -1 -1 17 17 17 17 255 17 255 17 -1 -1 ) ;17 + ( 18 18 18 18 18 -1 18 18 19 18 -1 -1 ) ;18 + ( -1 18 18 19 19 20 19 19 -1 18 -1 -1 ) ;19 + ( -1 -1 -1 18 -1 -1 -1 -1 -1 21 -1 -1 ) ;20 + ( -1 -1 -1 -1 -1 20 22 -1 -1 -1 -1 -1 ) ;21 + ( 18 18 18 18 16 18 23 18 18 18 18 18 ) ;22 + ( -1 255 -1 -1 -1 19 -1 -1 -1 -1 -1 -1 ) ;23 + ( 23 25 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;24 + ( 24 255 -1 -1 -1 -1 -1 -1 -1 -1 255 -1 ) ;25 + (255 28 -1 -1 -1 -1 -1 -1 -1 -1 255 -1 ) ;26 + ( -1 -1 -1 -1 7 -1 -1 -1 -1 -1 -1 -1 ) ;27 + ( 26 255 -1 -1 -1 -1 -1 -1 -1 -1 255 -1 ) ;28 + ( -1 -1 30 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;29 + ( -1 -1 31 29 -1 -1 -1 -1 -1 -1 -1 -1 ) ;30 + ( 32 33 -1 30 -1 -1 -1 -1 -1 -1 -1 -1 ) ;31 + ( -1 31 -1 255 -1 -1 -1 -1 -1 34 -1 -1 ) ;32 + ( 31 -1 -1 -1 -1 -1 -1 -1 -1 35 -1 -1 ) ;33 + ( -1 35 -1 -1 -1 -1 -1 -1 32 37 -1 -1 ) ;34 + ( 34 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;35 + ( -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;36 + ( -1 -1 -1 -1 -1 -1 -1 38 34 -1 -1 -1 ) ;37 + ( -1 -1 40 41 37 -1 -1 39 -1 -1 -1 -1 ) ;38 + ( -1 -1 -1 -1 38 -1 -1 -1 -1 -1 -1 -1 ) ;39 + ( -1 -1 -1 38 -1 -1 -1 -1 42 -1 -1 -1 ) ;40 + ( -1 -1 38 -1 -1 -1 -1 -1 -1 43 -1 -1 ) ;41 + ( -1 -1 -1 -1 -1 -1 -1 -1 -1 40 -1 -1 ) ;42 + ( 44 -1 46 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;43 + ( -1 43 45 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;44 + ( -1 46 -1 44 -1 -1 -1 -1 -1 -1 -1 -1 ) ;45 + ( 45 -1 -1 43 -1 -1 -1 -1 -1 255 -1 -1 ) ;46 + ( 48 50 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;47 + ( 49 47 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;48 + ( -1 48 -1 -1 -1 -1 -1 -1 52 -1 -1 -1 ) ;49 + ( 47 51 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;50 + ( 50 104 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;51 + ( -1 -1 -1 -1 -1 -1 -1 -1 53 49 -1 -1 ) ;52 + ( -1 -1 -1 -1 -1 -1 -1 -1 54 52 -1 -1 ) ;53 + ( -1 -1 -1 -1 55 -1 -1 -1 -1 53 -1 -1 ) ;54 + ( -1 -1 -1 -1 56 -1 -1 54 -1 -1 -1 54 ) ;55 + ( -1 -1 -1 -1 -1 -1 -1 55 -1 31 -1 -1 ) ;56 + ( -1 -1 32 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;57 + ( 59 -1 11 -1 -1 -1 -1 -1 -1 -1 255 255) ;58 + ( 60 58 63 -1 -1 -1 255 -1 -1 -1 255 255) ;59 + ( 61 59 64 -1 -1 -1 -1 -1 -1 -1 255 255) ;60 + ( 62 60 65 -1 -1 -1 -1 -1 -1 -1 255 255) ;61 + ( -1 61 66 -1 -1 -1 -1 -1 -1 -1 255 255) ;62 + ( 64 -1 67 59 -1 -1 -1 -1 -1 -1 255 255) ;63 + ( 65 63 68 60 -1 -1 -1 -1 -1 -1 255 255) ;64 + ( 66 64 69 61 -1 -1 -1 -1 -1 -1 255 255) ;65 + ( -1 65 70 62 -1 -1 -1 -1 -1 -1 255 255) ;66 + ( 68 -1 71 63 -1 -1 -1 -1 -1 -1 255 255) ;67 + ( 69 67 72 64 -1 -1 -1 -1 -1 -1 255 255) ;68 + ( 70 68 73 65 -1 -1 -1 -1 -1 -1 255 255) ;69 + ( -1 69 74 66 -1 -1 -1 -1 -1 -1 255 255) ;70 + ( 72 -1 75 67 -1 -1 -1 -1 -1 -1 255 255) ;71 + ( 73 71 76 68 -1 -1 -1 -1 -1 -1 255 255) ;72 + ( 74 72 77 69 -1 -1 -1 -1 -1 -1 255 255) ;73 + ( -1 73 78 70 -1 -1 -1 -1 -1 -1 255 255) ;74 + ( 76 -1 79 71 -1 -1 -1 -1 -1 -1 255 255) ;75 + ( 77 75 80 72 -1 -1 -1 -1 -1 -1 255 255) ;76 + ( 78 76 81 73 -1 -1 -1 -1 -1 -1 255 255) ;77 + ( -1 77 82 74 -1 -1 -1 -1 -1 -1 255 255) ;78 + ( 80 -1 -1 75 -1 -1 -1 -1 -1 -1 255 255) ;79 + ( 81 79 255 76 -1 -1 -1 -1 -1 -1 255 255) ;80 + ( 82 80 -1 77 -1 -1 -1 -1 -1 -1 255 255) ;81 + ( -1 81 -1 78 -1 -1 -1 -1 -1 -1 255 255) ;82 + ( 84 -1 -1 -1 -1 59 -1 -1 -1 -1 255 255) ;83 + ( -1 83 85 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;84 + ( 86 -1 87 84 -1 -1 -1 -1 -1 -1 -1 -1 ) ;85 + ( -1 85 88 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;86 + ( 88 -1 -1 85 -1 -1 -1 -1 -1 -1 -1 -1 ) ;87 + ( -1 87 255 86 -1 -1 -1 -1 -1 -1 -1 -1 ) ;88 + ( -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 255 -1 ) ;89 + ( 91 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;90 + ( 92 90 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;91 + ( -1 91 -1 -1 -1 -1 -1 -1 93 94 -1 -1 ) ;92 + ( -1 -1 -1 88 -1 -1 -1 -1 -1 92 -1 -1 ) ;93 + ( -1 -1 -1 -1 95 -1 -1 -1 92 -1 -1 -1 ) ;94 + ( -1 -1 -1 -1 -1 -1 -1 94 -1 -1 -1 -1 ) ;95 + ( 97 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;96 + ( -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;97 + ( 99 97 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;98 + ( -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;99 + ( 101 99 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;100 + ( -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;101 + ( 103 101 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;102 + ( -1 102 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;103 + ( 51 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ) ;104 + ) +; no so ea we ne se nw sw up do in ot +) + + +;;; How the user references *all* objects, permanent and regular. +(setq erbp-objnames '( + (shovel . 0) + (lamp . 1) + (cpu . 2) (board . 2) (card . 2) (chip . 2) + (food . 3) + (key . 4) + (paper . 5) (slip . 5) + (rms . 6) (statue . 6) (statuette . 6) (stallman . 6) + (diamond . 7) + (weight . 8) + (life . 9) (preserver . 9) + (bracelet . 10) (emerald . 10) + (gold . 11) + (platinum . 12) + (towel . 13) (beach . 13) + (axe . 14) + (silver . 15) + (license . 16) + (coins . 17) + (egg . 18) + (jar . 19) + (bone . 20) + (acid . 21) (nitric . 21) + (glycerine . 22) + (ruby . 23) + (amethyst . 24) + (mona . 25) + (bill . 26) + (floppy . 27) (disk . 27) + + (boulder . -1) + (tree . -2) (trees . -2) (palm . -2) + (bear . -3) + (bin . -4) (bins . -4) + (cabinet . -5) (computer . -5) (vax . -5) (ibm . -5) + (protoplasm . -6) + (dial . -7) + (button . -8) + (chute . -9) + (painting . -10) + (bed . -11) + (urinal . -12) + (URINE . -13) + (pipes . -14) (pipe . -14) + (box . -15) (slit . -15) + (cable . -16) (ethernet . -16) + (mail . -17) (drop . -17) + (bus . -18) + (gate . -19) + (cliff . -20) + (skeleton . -21) (dinosaur . -21) + (fish . -22) + (tanks . -23) (tank . -23) + (switch . -24) + (blackboard . -25) + (disposal . -26) (garbage . -26) + (ladder . -27) + (subway . -28) (train . -28) + (pc . -29) (drive . -29) (coconut . -30) (coconuts . -30) + (lake . -32) (water . -32) +)) + +(dolist (x erbp-objnames) + (let (name) + (setq name (concat "obj-" (prin1-to-string (car x)))) + (eval (list 'defconst (intern name) (cdr x))))) + +(defconst obj-special 255) + +;;; The initial setup of what objects are in each room. +;;; Regular objects have whole numbers lower than 255. +;;; Objects that cannot be taken but might move and are +;;; described during room description are negative. +;;; Stuff that is described and might change are 255, and are +;;; handled specially by 'erbp-describe-room. + +(setq erbp-room-objects (list nil + + (list obj-shovel) ;; treasure-room + (list obj-boulder) ;; dead-end + nil nil nil + (list obj-food) ;; se-nw-road + (list obj-bear) ;; bear-hangout + nil nil + (list obj-special) ;; computer-room + (list obj-lamp obj-license obj-silver);; meadow + nil nil + (list obj-special) ;; sauna + nil + (list obj-weight obj-life) ;; weight-room + nil nil + (list obj-rms obj-floppy) ;; thirsty-maze + nil nil nil nil nil nil nil + (list obj-emerald) ;; hidden-area + nil + (list obj-gold) ;; misty-room + nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil + (list obj-towel obj-special) ;; red-room + nil nil nil nil nil + (list obj-box) ;; stair-landing + nil nil nil + (list obj-axe) ;; smal-crawlspace + nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil + nil nil nil nil nil + (list obj-special) ;; fourth-vermont-intersection + nil nil + (list obj-coins) ;; fifth-oaktree-intersection + nil + (list obj-bus) ;; fifth-sycamore-intersection + nil + (list obj-bone) ;; museum-lobby + nil + (list obj-jar obj-special obj-ruby) ;; marine-life-area + (list obj-nitric) ;; maintenance-room + (list obj-glycerine) ;; classroom + nil nil nil nil nil + (list obj-amethyst) ;; bottom-of-subway-stairs + nil nil + (list obj-special) ;; question-room-1 + nil + (list obj-special) ;; question-room-2 + nil + (list obj-special) ;; question-room-three + nil + (list obj-mona) ;; winner's-room +nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil +nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil +nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil +nil)) + +;;; These are objects in a room that are only described in the +;;; room description. They are permanent. + +(setq erbp-room-silents (list nil + (list obj-tree obj-coconut) ;; dead-end + (list obj-tree obj-coconut) ;; e-w-dirt-road + nil nil nil nil nil nil + (list obj-bin) ;; mailroom + (list obj-computer) ;; computer-room + nil nil nil + (list obj-dial) ;; sauna + nil + (list obj-ladder) ;; weight-room + (list obj-button obj-ladder) ;; maze-button-room + nil nil nil + nil nil nil nil + (list obj-lake) ;; lakefront-north + (list obj-lake) ;; lakefront-south + nil + (list obj-chute) ;; cave-entrance + nil nil nil nil nil + (list obj-painting obj-bed) ;; bedroom + (list obj-urinal obj-pipes) ;; bathroom + nil nil nil nil nil nil + (list obj-boulder) ;; horseshoe-boulder-room + nil nil nil nil nil nil nil nil nil nil nil nil nil nil + (list obj-computer obj-cable) ;; gamma-computing-center + (list obj-mail) ;; post-office + (list obj-gate) ;; main-maple-intersection + nil nil nil nil nil nil nil nil nil nil nil nil nil + nil nil nil nil nil nil nil + (list obj-cliff) ;; fifth-oaktree-intersection + nil nil nil + (list obj-dinosaur) ;; museum-lobby + nil + (list obj-fish obj-tanks) ;; marine-life-area + (list obj-switch) ;; maintenance-room + (list obj-blackboard) ;; classroom + (list obj-train) ;; vermont-station + nil nil + (list obj-disposal) ;; north-end-of-n-s-tunnel + nil nil + (list obj-computer) ;; endgame-computer-room + nil nil nil nil nil nil nil nil + (list obj-pc) ;; pc-area + nil nil nil nil nil nil +)) +(setq erbp-inventory '(1)) + +;;; Descriptions of objects, as they appear in the room description, and +;;; the inventory. + +(setq erbp-objects '( + ("There is a shovel here." "A shovel") ;0 + ("There is a lamp nearby." "A lamp") ;1 + ("There is a CPU card here." "A computer board") ;2 + ("There is some food here." "Some food") ;3 + ("There is a shiny brass key here." "A brass key") ;4 + ("There is a slip of paper here." "A slip of paper") ;5 + ("There is a wax statuette of Richard Stallman here." ;6 + "An RMS statuette") + ("There is a shimmering diamond here." "A diamond") ;7 + ("There is a 10 pound weight here." "A weight") ;8 + ("There is a life preserver here." "A life preserver");9 + ("There is an emerald bracelet here." "A bracelet") ;10 + ("There is a gold bar here." "A gold bar") ;11 + ("There is a platinum bar here." "A platinum bar") ;12 + ("There is a beach towel on the ground here." "A beach towel") + ("There is an axe here." "An axe") ;14 + ("There is a silver bar here." "A silver bar") ;15 + ("There is a bus driver's license here." "A license") ;16 + ("There are some valuable coins here." "Some valuable coins") + ("There is a jewel-encrusted egg here." "A valuable egg") ;18 + ("There is a glass jar here." "A glass jar") ;19 + ("There is a dinosaur bone here." "A bone") ;20 + ("There is a packet of nitric acid here." "Some nitric acid") + ("There is a packet of glycerine here." "Some glycerine") ;22 + ("There is a valuable ruby here." "A ruby") ;23 + ("There is a valuable amethyst here." "An amethyst") ;24 + ("The Mona Lisa is here." "The Mona Lisa") ;25 + ("There is a 100 dollar bill here." "A $100 bill") ;26 + ("There is a floppy disk here." "A floppy disk") ;27 + ) +) + +;;; Weight of objects + +(setq erbp-object-lbs + '(2 1 1 1 1 0 2 2 10 3 1 1 1 0 1 1 0 1 1 1 1 0 0 2 2 1 0 0)) +(setq erbp-object-pts + '(0 0 0 0 0 0 0 10 0 0 10 10 10 0 0 10 0 10 10 0 0 0 0 10 10 10 10 0)) + + +;;; Unix representation of objects. +(setq erbp-objfiles '( + "shovel.o" "lamp.o" "cpu.o" "food.o" "key.o" "paper.o" + "rms.o" "diamond.o" "weight.o" "preserver.o" "bracelet.o" + "gold.o" "platinum.o" "towel.o" "axe.o" "silver.o" "license.o" + "coins.o" "egg.o" "jar.o" "bone.o" "nitric.o" "glycerine.o" + "ruby.o" "amethyst.o" + )) + +;;; These are the descriptions for the negative numbered objects from +;;; erbp-room-objects + +(setq erbp-perm-objects '( + nil + ("There is a large boulder here.") + nil + ("There is a ferocious bear here!") + nil + nil + ("There is a worthless pile of protoplasm here.") + nil + nil + nil + nil + nil + nil + ("There is a strange smell in this room.") + nil + ( +"There is a box with a slit in it, bolted to the wall here." + ) + nil + nil + ("There is a bus here.") + nil + nil + nil +)) + + +;;; These are the descriptions the user gets when regular objects are +;;; examined. + +(setq erbp-physobj-desc '( +"It is a normal shovel with a price tag attached that says $19.99." +"The lamp is hand-crafted by Geppetto." +"The CPU board has a VAX chip on it. It seems to have +2 Megabytes of RAM onboard." +"It looks like some kind of meat. Smells pretty bad." +nil +"The paper says: Don't forget to type 'help' for help. Also, remember +this word: 'worms'" +"The statuette is of the likeness of Richard Stallman, the author of the +famous EMACS editor. You notice that he is not wearing any shoes." +nil +"You observe that the weight is heavy." +"It says S. S. Minnow." +nil +nil +nil +"It has a picture of snoopy on it." +nil +nil +"It has your picture on it!" +"They are old coins from the 19th century." +"It is a valuable Fabrege egg." +"It is a a plain glass jar." +nil +nil +nil +nil +nil + ) +) + +;;; These are the descriptions the user gets when non-regular objects +;;; are examined. + +(setq erbp-permobj-desc '( + nil +"It is just a boulder. It cannot be moved." +"They are palm trees with a bountiful supply of coconuts in them." +"It looks like a grizzly to me." +"All of the bins are empty. Looking closely you can see that there +are names written at the bottom of each bin, but most of them are +faded away so that you cannot read them. You can only make out three +names: + Jeffrey Collier + Robert Toukmond + Thomas Stock +" + nil +"It is just a garbled mess." +"The dial points to a temperature scale which has long since faded away." +nil +nil +"It is a velvet painting of Elvis Presley. It seems to be nailed to the +wall, and you cannot move it." +"It is a queen sized bed, with a very firm mattress." +"The urinal is very clean compared with everything else in the cave. There +isn't even any rust. Upon close examination you realize that the drain at the +bottom is missing, and there is just a large hole leading down the +pipes into nowhere. The hole is too small for a person to fit in. The +flush handle is so clean that you can see your reflection in it." +nil +nil +"The box has a slit in the top of it, and on it, in sloppy handwriting, is +written: 'For key upgrade, put key in here.'" +nil +"It says 'express mail' on it." +"It is a 35 passenger bus with the company name 'mobytours' on it." +"It is a large metal gate that is too big to climb over." +"It is a HIGH cliff." +"Unfortunately you do not know enough about dinosaurs to tell very much about +it. It is very big, though." +"The fish look like they were once quite beautiful." +nil +nil +nil +nil +"It is a normal ladder that is permanently attached to the hole." +"It is a passenger train that is ready to go." +"It is a personal computer that has only one floppy disk drive." + ) +) + +(setq erbp-diggables + (list nil nil nil (list obj-cpu) nil nil nil nil nil nil nil + nil nil nil nil nil nil nil nil nil nil ;11-20 + nil nil nil nil nil nil nil nil nil nil ;21-30 + nil nil nil nil nil nil nil nil nil nil ;31-40 + nil (list obj-platinum) nil nil nil nil nil nil nil nil)) + +(setq erbp-room-shorts nil) +(dolist (x erbp-rooms) + (setq erbp-room-shorts + (append erbp-room-shorts (list (downcase + (erbp-space-to-hyphen + (cadr x))))))) + +(setq erbp-endgame-questions '( + ( +"What is your password on the machine called 'pokey'?" "robert") + ( +"What password did you use during anonymous ftp to gamma?" "foo") + ( +"Excluding the endgame, how many places are there where you can put +treasures for points?" "4" "four") + ( +"What is your login name on the 'endgame' machine?" "toukmond" +) + ( +"What is the nearest whole dollar to the price of the shovel?" "20" "twenty") + ( +"What is the name of the bus company serving the town?" "mobytours") + ( +"Give either of the two last names in the mailroom, other than your own." +"collier" "stock") + ( +"What cartoon character is on the towel?" "snoopy") + ( +"What is the last name of the author of EMACS?" "stallman") + ( +"How many megabytes of memory is on the CPU board for the Vax?" "2") + ( +"Which street in town is named after a U.S. state?" "vermont") + ( +"How many pounds did the weight weigh?" "ten" "10") + ( +"Name the STREET which runs right over the subway stop." "fourth" "4" "4th") + ( +"How many corners are there in town (excluding the one with the Post Office)?" + "24" "twentyfour" "twenty-four") + ( +"What type of bear was hiding your key?" "grizzly") + ( +"Name either of the two objects you found by digging." "cpu" "card" "vax" +"board" "platinum") + ( +"What network protocol is used between pokey and gamma?" "tcp/ip" "ip" "tcp") +)) + +(let (a) + (setq a 0) + (dolist (x erbp-room-shorts) + (eval (list 'defconst (intern x) a)) + (setq a (+ a 1)))) + + + +;;;; +;;;; This section defines the UNIX emulation functions for erbpnet. +;;;; + +(defun erbp-unix-parse (args) + (interactive "*p") + (beginning-of-line) + (let (beg esign) + (setq beg (+ (point) 2)) + (end-of-line) + (if (and (not (= beg (point))) + (string= "$" (buffer-substring (- beg 2) (- beg 1)))) + (progn + (setq line (downcase (buffer-substring beg (point)))) + (princ line) + (if (eq (erbp-parse2 nil erbp-unix-verbs line) -1) + (progn + (if (setq esign (string-match "=" line)) + (erbp-doassign line esign) + (erbp-mprinc (car line-list)) + (erbp-mprincl ": not found."))))) + (goto-char (point-max)) + (erbp-mprinc "\n")) + (if (eq erbpeon-mode 'unix) + (progn + (erbp-fix-screen) + (erbp-mprinc "$ "))))) + +(defun erbp-doassign (line esign) + (if (not erbp-wizard) + (let (passwd) + (erbp-mprinc "Enter wizard password: ") + (setq passwd (erbp-read-line)) + (if (not erbp-batch-mode) + (erbp-mprinc "\n")) + (if (string= passwd "moby") + (progn + (setq erbp-wizard t) + (erbp-doassign line esign)) + (erbp-mprincl "Incorrect."))) + + (let (varname epoint afterq i value) + (setq varname (substring line 0 esign)) + (if (not (setq epoint (string-match ")" line))) + (if (string= (substring line (1+ esign) (+ esign 2)) + "\"") + (progn + (setq afterq (substring line (+ esign 2))) + (setq epoint (+ + (string-match "\"" afterq) + (+ esign 3)))) + + (if (not (setq epoint (string-match " " line))) + (setq epoint (length line)))) + (setq epoint (1+ epoint)) + (while (and + (not (= epoint (length line))) + (setq i (string-match ")" (substring line epoint)))) + (setq epoint (+ epoint i 1)))) + (setq value (substring line (1+ esign) epoint)) + (erbp-eval varname value)))) + +(defun erbp-eval (varname value) + (let (eval-error) + (switch-to-buffer (get-buffer-create "*erbpeon-eval*")) + (erase-buffer) + (insert "(setq ") + (insert varname) + (insert " ") + (insert value) + (insert ")") + (setq eval-error nil) + (condition-case nil + (eval-current-buffer) + (error (setq eval-error t))) + (kill-buffer (current-buffer)) + (switch-to-buffer "*erbpeon*") + (if eval-error + (erbp-mprincl "Invalid syntax.")))) + + +(defun erbp-unix-interface () + (erbp-login) + (if erbp-logged-in + (progn + (setq erbpeon-mode 'unix) + (define-key erbpeon-mode-map "\r" 'erbp-unix-parse) + (erbp-mprinc "$ ")))) + +(defun erbp-login () + (let (tries username password) + (setq tries 4) + (while (and (not erbp-logged-in) (> (setq tries (- tries 1)) 0)) + (erbp-mprinc "\n\nUNIX System V, Release 2.2 (pokey)\n\nlogin: ") + (setq username (erbp-read-line)) + (if (not erbp-batch-mode) + (erbp-mprinc "\n")) + (erbp-mprinc "password: ") + (setq password (erbp-read-line)) + (if (not erbp-batch-mode) + (erbp-mprinc "\n")) + (if (or (not (string= username "toukmond")) + (not (string= password "robert"))) + (erbp-mprincl "login incorrect") + (setq erbp-logged-in t) + (erbp-mprincl " +Welcome to Unix\n +Please clean up your directories. The filesystem is getting full. +Our tcp/ip link to gamma is a little flaky, but seems to work. +The current version of ftp can only send files from your home +directory, and deletes them after they are sent! Be careful. + +Note: Restricted bourne shell in use.\n"))) + (setq erbpeon-mode 'erbpeon))) + +(defun erbp-ls (args) + (if (car args) + (let (ocdpath ocdroom) + (setq ocdpath erbp-cdpath) + (setq ocdroom erbp-cdroom) + (if (not (eq (erbp-cd args) -2)) + (erbp-ls nil)) + (setq erbp-cdpath ocdpath) + (setq erbp-cdroom ocdroom)) + (if (= erbp-cdroom -10) + (erbp-ls-inven)) + (if (= erbp-cdroom -2) + (erbp-ls-rooms)) + (if (= erbp-cdroom -3) + (erbp-ls-root)) + (if (= erbp-cdroom -4) + (erbp-ls-usr)) + (if (> erbp-cdroom 0) + (erbp-ls-room)))) + +(defun erbp-ls-root () + (erbp-mprincl "total 4 +drwxr-xr-x 3 root staff 512 Jan 1 1970 . +drwxr-xr-x 3 root staff 2048 Jan 1 1970 .. +drwxr-xr-x 3 root staff 2048 Jan 1 1970 usr +drwxr-xr-x 3 root staff 2048 Jan 1 1970 rooms")) + +(defun erbp-ls-usr () + (erbp-mprincl "total 4 +drwxr-xr-x 3 root staff 512 Jan 1 1970 . +drwxr-xr-x 3 root staff 2048 Jan 1 1970 .. +drwxr-xr-x 3 toukmond restricted 512 Jan 1 1970 toukmond")) + +(defun erbp-ls-rooms () + (erbp-mprincl "total 16 +drwxr-xr-x 3 root staff 512 Jan 1 1970 . +drwxr-xr-x 3 root staff 2048 Jan 1 1970 ..") + (dolist (x erbp-visited) + (erbp-mprinc +"drwxr-xr-x 3 root staff 512 Jan 1 1970 ") + (erbp-mprincl (nth x erbp-room-shorts)))) + +(defun erbp-ls-room () + (erbp-mprincl "total 4 +drwxr-xr-x 3 root staff 512 Jan 1 1970 . +drwxr-xr-x 3 root staff 2048 Jan 1 1970 .. +-rwxr-xr-x 3 root staff 2048 Jan 1 1970 description") + (dolist (x (nth erbp-cdroom erbp-room-objects)) + (if (and (>= x 0) (not (= x 255))) + (progn + (erbp-mprinc "-rwxr-xr-x 1 toukmond restricted 0 Jan 1 1970 ") + (erbp-mprincl (nth x erbp-objfiles)))))) + +(defun erbp-ls-inven () + (erbp-mprinc "total 467 +drwxr-xr-x 3 toukmond restricted 512 Jan 1 1970 . +drwxr-xr-x 3 root staff 2048 Jan 1 1970 ..") + (dolist (x erbp-unix-verbs) + (if (not (eq (car x) 'IMPOSSIBLE)) + (progn + (erbp-mprinc" +-rwxr-xr-x 1 toukmond restricted 10423 Jan 1 1970 ") + (erbp-mprinc (car x))))) + (erbp-mprinc "\n") + (if (not erbp-uncompressed) + (erbp-mprincl +"-rwxr-xr-x 1 toukmond restricted 0 Jan 1 1970 paper.o.Z")) + (dolist (x erbp-inventory) + (erbp-mprinc +"-rwxr-xr-x 1 toukmond restricted 0 Jan 1 1970 ") + (erbp-mprincl (nth x erbp-objfiles)))) + +(defun erbp-echo (args) + (let (nomore var) + (setq nomore nil) + (dolist (x args) + (if (not nomore) + (progn + (if (not (string= (substring x 0 1) "$")) + (progn + (erbp-mprinc x) + (erbp-mprinc " ")) + (setq var (intern (substring x 1))) + (if (not (boundp var)) + (erbp-mprinc " ") + (if (member var erbp-restricted) + (progn + (erbp-mprinc var) + (erbp-mprinc ": Permission denied") + (setq nomore t)) + (eval (list 'erbp-mprinc var)) + (erbp-mprinc " "))))))) + (erbp-mprinc "\n"))) + + +(defun erbp-ftp (args) + (let (host username passwd ident newlist) + (if (not (car args)) + (erbp-mprincl "ftp: hostname required on command line.") + (setq host (intern (car args))) + (if (not (member host '(gamma erbp-endgame))) + (erbp-mprincl "ftp: Unknown host.") + (if (eq host 'erbp-endgame) + (erbp-mprincl "ftp: connection to endgame not allowed") + (if (not erbp-ethernet) + (erbp-mprincl "ftp: host not responding.") + (erbp-mprincl "Connected to gamma. FTP ver 0.9 00:00:00 01/01/70") + (erbp-mprinc "Username: ") + (setq username (erbp-read-line)) + (if (string= username "toukmond") + (if erbp-batch-mode + (erbp-mprincl "toukmond ftp access not allowed.") + (erbp-mprincl "\ntoukmond ftp access not allowed.")) + (if (string= username "anonymous") + (if erbp-batch-mode + (erbp-mprincl + "Guest login okay, send your user ident as password.") + (erbp-mprincl + "\nGuest login okay, send your user ident as password.")) + (if erbp-batch-mode + (erbp-mprinc "Password required for ") + (erbp-mprinc "\nPassword required for ")) + (erbp-mprincl username)) + (erbp-mprinc "Password: ") + (setq ident (erbp-read-line)) + (if (not (string= username "anonymous")) + (if erbp-batch-mode + (erbp-mprincl "Login failed.") + (erbp-mprincl "\nLogin failed.")) + (if erbp-batch-mode + (erbp-mprincl + "Guest login okay, user access restrictions apply.") + (erbp-mprincl + "\nGuest login okay, user access restrictions apply.")) + (erbp-ftp-commands) + (setq newlist +'("What password did you use during anonymous ftp to gamma?")) + (setq newlist (append newlist (list ident))) + (rplaca (nthcdr 1 erbp-endgame-questions) newlist))))))))) + +(defun erbp-ftp-commands () + (setq erbp-exitf nil) + (let (line) + (while (not erbp-exitf) + (erbp-mprinc "ftp> ") + (setq line (erbp-read-line)) + (if + (eq + (erbp-parse2 nil + '((type . erbp-ftptype) (binary . erbp-bin) (bin . erbp-bin) + (send . erbp-send) (put . erbp-send) (quit . erbp-ftpquit) + (help . erbp-ftphelp)(ascii . erbp-fascii) + ) line) + -1) + (erbp-mprincl "No such command. Try help."))) + (setq erbp-ftptype 'ascii))) + +(defun erbp-ftptype (args) + (if (not (car args)) + (erbp-mprincl "Usage: type [binary | ascii]") + (setq args (intern (car args))) + (if (eq args 'binary) + (erbp-bin nil) + (if (eq args 'ascii) + (erbp-fascii 'nil) + (erbp-mprincl "Unknown type."))))) + +(defun erbp-bin (args) + (erbp-mprincl "Type set to binary.") + (setq erbp-ftptype 'binary)) + +(defun erbp-fascii (args) + (erbp-mprincl "Type set to ascii.") + (setq erbp-ftptype 'ascii)) + +(defun erbp-ftpquit (args) + (setq erbp-exitf t)) + +(defun erbp-send (args) + (if (not (car args)) + (erbp-mprincl "Usage: send ") + (setq args (car args)) + (let (counter foo) + (setq foo nil) + (setq counter 0) + +;;; User can send commands! Stupid user. + + + (if (assq (intern args) erbp-unix-verbs) + (progn + (rplaca (assq (intern args) erbp-unix-verbs) 'IMPOSSIBLE) + (erbp-mprinc "Sending ") + (erbp-mprinc erbp-ftptype) + (erbp-mprinc " file for ") + (erbp-mprincl args) + (erbp-mprincl "Transfer complete.")) + + (dolist (x erbp-objfiles) + (if (string= args x) + (progn + (if (not (member counter erbp-inventory)) + (progn + (erbp-mprincl "No such file.") + (setq foo t)) + (erbp-mprinc "Sending ") + (erbp-mprinc erbp-ftptype) + (erbp-mprinc " file for ") + (erbp-mprinc (downcase (cadr (nth counter erbp-objects)))) + (erbp-mprincl ", (0 bytes)") + (if (not (eq erbp-ftptype 'binary)) + (progn + (if (not (member obj-protoplasm + (nth receiving-room + erbp-room-objects))) + (erbp-replace erbp-room-objects receiving-room + (append (nth receiving-room + erbp-room-objects) + (list obj-protoplasm)))) + (erbp-remove-obj-from-inven counter)) + (erbp-remove-obj-from-inven counter) + (erbp-replace erbp-room-objects receiving-room + (append (nth receiving-room erbp-room-objects) + (list counter)))) + (setq foo t) + (erbp-mprincl "Transfer complete.")))) + (setq counter (+ 1 counter))) + (if (not foo) + (erbp-mprincl "No such file.")))))) + +(defun erbp-ftphelp (args) + (erbp-mprincl + "Possible commands are:\nsend quit type ascii binary help")) + +(defun erbp-uexit (args) + (setq erbpeon-mode 'erbpeon) + (erbp-mprincl "\nYou step back from the console.") + (define-key erbpeon-mode-map "\r" 'erbp-parse) + (if (not erbp-batch-mode) + (erbp-messages))) + +(defun erbp-pwd (args) + (erbp-mprincl erbp-cdpath)) + +(defun erbp-uncompress (args) + (if (not (car args)) + (erbp-mprincl "Usage: uncompress ") + (setq args (car args)) + (if (or erbp-uncompressed + (and (not (string= args "paper.o")) + (not (string= args "paper.o.z")))) + (erbp-mprincl "Uncompress command failed.") + (setq erbp-uncompressed t) + (setq erbp-inventory (append erbp-inventory (list obj-paper)))))) + +(defun erbp-rlogin (args) + (let (passwd) + (if (not (car args)) + (erbp-mprincl "Usage: rlogin ") + (setq args (car args)) + (if (string= args "endgame") + (erbp-rlogin-endgame) + (if (not (string= args "gamma")) + (if (string= args "pokey") + (erbp-mprincl "Can't rlogin back to localhost") + (erbp-mprincl "No such host.")) + (if (not erbp-ethernet) + (erbp-mprincl "Host not responding.") + (erbp-mprinc "Password: ") + (setq passwd (erbp-read-line)) + (if (not (string= passwd "worms")) + (erbp-mprincl "\nlogin incorrect") + (erbp-mprinc +"\nYou begin to feel strange for a moment, and you lose your items." +) + (erbp-replace erbp-room-objects computer-room + (append (nth computer-room erbp-room-objects) + erbp-inventory)) + (setq erbp-inventory nil) + (setq erbp-current-room receiving-room) + (erbp-uexit nil)))))))) + +(defun erbp-cd (args) + (let (tcdpath tcdroom path-elements room-check) + (if (not (car args)) + (erbp-mprincl "Usage: cd ") + (setq tcdpath erbp-cdpath) + (setq tcdroom erbp-cdroom) + (setq erbp-badcd nil) + (condition-case nil + (setq path-elements (erbp-get-path (car args) nil)) + (error (erbp-mprincl "Invalid path") + (setq erbp-badcd t))) + (dolist (pe path-elements) + (unless erbp-badcd + (if (not (string= pe ".")) + (if (string= pe "..") + (progn + (if (> tcdroom 0) ;In a room + (progn + (setq tcdpath "/rooms") + (setq tcdroom -2)) + ;In /rooms,/usr,root + (if (or + (= tcdroom -2) (= tcdroom -4) + (= tcdroom -3)) + (progn + (setq tcdpath "/") + (setq tcdroom -3)) + (if (= tcdroom -10) ;In /usr/toukmond + (progn + (setq tcdpath "/usr") + (setq tcdroom -4)))))) + (if (string= pe "/") + (progn + (setq tcdpath "/") + (setq tcdroom -3)) + (if (= tcdroom -4) + (if (string= pe "toukmond") + (progn + (setq tcdpath "/usr/toukmond") + (setq tcdroom -10)) + (erbp-nosuchdir)) + (if (= tcdroom -10) + (erbp-nosuchdir) + (if (> tcdroom 0) + (erbp-nosuchdir) + (if (= tcdroom -3) + (progn + (if (string= pe "rooms") + (progn + (setq tcdpath "/rooms") + (setq tcdroom -2)) + (if (string= pe "usr") + (progn + (setq tcdpath "/usr") + (setq tcdroom -4)) + (erbp-nosuchdir)))) + (if (= tcdroom -2) + (progn + (dolist (x erbp-visited) + (setq room-check + (nth x + erbp-room-shorts)) + (if (string= room-check pe) + (progn + (setq tcdpath + (concat "/rooms/" room-check)) + (setq tcdroom x)))) + (if (= tcdroom -2) + (erbp-nosuchdir))))))))))))) + (if (not erbp-badcd) + (progn + (setq erbp-cdpath tcdpath) + (setq erbp-cdroom tcdroom) + 0) + -2)))) + +(defun erbp-nosuchdir () + (erbp-mprincl "No such directory.") + (setq erbp-badcd t)) + +(defun erbp-cat (args) + (let (doto checklist) + (if (not (setq args (car args))) + (erbp-mprincl "Usage: cat ") + (if (string-match "/" args) + (erbp-mprincl "cat: only files in current directory allowed.") + (if (and (> erbp-cdroom 0) (string= args "description")) + (erbp-mprincl (car (nth erbp-cdroom erbp-rooms))) + (if (setq doto (string-match "\\.o" args)) + (progn + (if (= erbp-cdroom -10) + (setq checklist erbp-inventory) + (setq checklist (nth erbp-cdroom erbp-room-objects))) + (if (not (member (cdr + (assq (intern + (substring args 0 doto)) + erbp-objnames)) + checklist)) + (erbp-mprincl "File not found.") + (erbp-mprincl "Ascii files only."))) + (if (assq (intern args) erbp-unix-verbs) + (erbp-mprincl "Ascii files only.") + (erbp-mprincl "File not found.")))))))) + +(defun erbp-zippy (args) + (erbp-mprincl (yow))) + +(defun erbp-rlogin-endgame () + (if (not (= (erbp-score nil) 90)) + (erbp-mprincl + "You have not achieved enough points to connect to endgame.") + (erbp-mprincl"\nWelcome to the endgame. You are a truly noble adventurer.") + (setq erbp-current-room treasure-room) + (setq erbp-endgame t) + (erbp-replace erbp-room-objects endgame-treasure-room (list obj-bill)) + (erbp-uexit nil))) + + +(random t) +(setq tloc (+ 60 (random 18))) +(erbp-replace erbp-room-objects tloc + (append (nth tloc erbp-room-objects) (list 18))) + +(setq tcomb (+ 100 (random 899))) +(setq erbp-combination (prin1-to-string tcomb)) + +;;;; +;;;; This section defines the DOS emulation functions for erbpnet +;;;; + +(defun erbp-dos-parse (args) + (interactive "*p") + (beginning-of-line) + (let (beg) + (setq beg (+ (point) 3)) + (end-of-line) + (if (not (= beg (point))) + (let (line) + (setq line (downcase (buffer-substring beg (point)))) + (princ line) + (if (eq (erbp-parse2 nil erbp-dos-verbs line) -1) + (progn + (sleep-for 1) + (erbp-mprincl "Bad command or file name")))) + (goto-char (point-max)) + (erbp-mprinc "\n")) + (if (eq erbpeon-mode 'dos) + (progn + (erbp-fix-screen) + (erbp-dos-prompt))))) + +(defun erbp-dos-interface () + (erbp-dos-boot-msg) + (setq erbpeon-mode 'dos) + (define-key erbpeon-mode-map "\r" 'erbp-dos-parse) + (erbp-dos-prompt)) + +(defun erbp-dos-type (args) + (sleep-for 2) + (if (setq args (car args)) + (if (string= args "foo.txt") + (erbp-dos-show-combination) + (if (string= args "command.com") + (erbp-mprincl "Cannot type binary files") + (erbp-mprinc "File not found - ") + (erbp-mprincl (upcase args)))) + (erbp-mprincl "Must supply file name"))) + +(defun erbp-dos-invd (args) + (sleep-for 1) + (erbp-mprincl "Invalid drive specification")) + +(defun erbp-dos-dir (args) + (sleep-for 1) + (if (or (not (setq args (car args))) (string= args "\\")) + (erbp-mprincl " + Volume in drive A is FOO + Volume Serial Number is 1A16-08C9 + Directory of A:\\ + +COMMAND COM 47845 04-09-91 2:00a +FOO TXT 40 01-20-93 1:01a + 2 file(s) 47845 bytes + 1065280 bytes free +") + (erbp-mprincl " + Volume in drive A is FOO + Volume Serial Number is 1A16-08C9 + Directory of A:\\ + +File not found"))) + + +(defun erbp-dos-prompt () + (erbp-mprinc "A> ")) + +(defun erbp-dos-boot-msg () + (sleep-for 3) + (erbp-mprinc "Current time is ") + (erbp-mprincl (substring (current-time-string) 12 20)) + (erbp-mprinc "Enter new time: ") + (erbp-read-line) + (if (not erbp-batch-mode) + (erbp-mprinc "\n"))) + +(defun erbp-dos-spawn (args) + (sleep-for 1) + (erbp-mprincl "Cannot spawn subshell")) + +(defun erbp-dos-exit (args) + (setq erbpeon-mode 'erbpeon) + (erbp-mprincl "\nYou power down the machine and step back.") + (define-key erbpeon-mode-map "\r" 'erbp-parse) + (if (not erbp-batch-mode) + (erbp-messages))) + +(defun erbp-dos-no-disk () + (sleep-for 3) + (erbp-mprincl "Boot sector not found")) + + +(defun erbp-dos-show-combination () + (sleep-for 2) + (erbp-mprinc "\nThe combination is ") + (erbp-mprinc erbp-combination) + (erbp-mprinc ".\n")) + +(defun erbp-dos-nil (args)) + + +;;;; +;;;; This section defines the save and restore game functions for erbpnet. +;;;; + +(defun erbp-save-game (filename) + (if (not (setq filename (car filename))) + (erbp-mprincl "You must supply a filename for the save.") + (if (file-exists-p filename) + (delete-file filename)) + (setq erbp-numsaves (1+ erbp-numsaves)) + (erbp-make-save-buffer) + (erbp-save-val "erbp-current-room") + (erbp-save-val "erbp-computer") + (erbp-save-val "erbp-combination") + (erbp-save-val "erbp-visited") + (erbp-save-val "erbp-diggables") + (erbp-save-val "erbp-key-level") + (erbp-save-val "erbp-floppy") + (erbp-save-val "erbp-numsaves") + (erbp-save-val "erbp-numcmds") + (erbp-save-val "erbp-logged-in") + (erbp-save-val "erbpeon-mode") + (erbp-save-val "erbp-jar") + (erbp-save-val "erbp-lastdir") + (erbp-save-val "erbp-black") + (erbp-save-val "erbp-nomail") + (erbp-save-val "erbp-unix-verbs") + (erbp-save-val "erbp-hole") + (erbp-save-val "erbp-uncompressed") + (erbp-save-val "erbp-ethernet") + (erbp-save-val "erbp-sauna-level") + (erbp-save-val "erbp-room-objects") + (erbp-save-val "erbp-room-silents") + (erbp-save-val "erbp-inventory") + (erbp-save-val "erbp-endgame-questions") + (erbp-save-val "erbp-endgame") + (erbp-save-val "erbp-cdroom") + (erbp-save-val "erbp-cdpath") + (erbp-save-val "erbp-correct-answer") + (erbp-save-val "erbp-inbus") + (if (erbp-compile-save-out filename) + (erbp-mprincl "Error saving to file.") + (erbp-do-logfile 'save nil) + (switch-to-buffer "*erbpeon*") + (princ "") + (erbp-mprincl "Done.")))) + +(defun erbp-make-save-buffer () + (switch-to-buffer (get-buffer-create "*save-erbpeon*")) + (erase-buffer)) + +(defun erbp-compile-save-out (filename) + (let (ferror) + (setq ferror nil) + (condition-case nil + (erbp-rot13) + (error (setq ferror t))) + (if (not ferror) + (progn + (goto-char (point-min)))) + (condition-case nil + (write-region 1 (point-max) filename nil 1) + (error (setq ferror t))) + (kill-buffer (current-buffer)) + ferror)) + + +(defun erbp-save-val (varname) + (let (value) + (setq varname (intern varname)) + (setq value (eval varname)) + (erbp-minsert "(setq ") + (erbp-minsert varname) + (erbp-minsert " ") + (if (or (listp value) + (symbolp value)) + (erbp-minsert "'")) + (if (stringp value) + (erbp-minsert "\"")) + (erbp-minsert value) + (if (stringp value) + (erbp-minsert "\"")) + (erbp-minsertl ")"))) + + +(defun erbp-restore (args) + (let (file) + (if (not (setq file (car args))) + (erbp-mprincl "You must supply a filename.") + (if (not (erbp-load-d file)) + (erbp-mprincl "Could not load restore file.") + (erbp-mprincl "Done.") + (setq room 0))))) + + +(defun erbp-do-logfile (type how) + (let (ferror newscore) + (setq ferror nil) + (switch-to-buffer (get-buffer-create "*score*")) + (erase-buffer) + (condition-case nil + (insert-file-contents erbp-log-file) + (error (setq ferror t))) + (unless ferror + (goto-char (point-max)) + (erbp-minsert (current-time-string)) + (erbp-minsert " ") + (erbp-minsert (user-login-name)) + (erbp-minsert " ") + (if (eq type 'save) + (erbp-minsert "saved ") + (if (= (erbp-endgame-score) 110) + (erbp-minsert "won ") + (if (not how) + (erbp-minsert "quit ") + (erbp-minsert "killed by ") + (erbp-minsert how) + (erbp-minsert " ")))) + (erbp-minsert "at ") + (erbp-minsert (cadr (nth (abs room) erbp-rooms))) + (erbp-minsert ". score: ") + (if (> (erbp-endgame-score) 0) + (erbp-minsert (setq newscore (+ 90 (erbp-endgame-score)))) + (erbp-minsert (setq newscore (erbp-reg-score)))) + (erbp-minsert " saves: ") + (erbp-minsert erbp-numsaves) + (erbp-minsert " commands: ") + (erbp-minsert erbp-numcmds) + (erbp-minsert "\n") + (write-region 1 (point-max) erbp-log-file nil 1)) + (kill-buffer (current-buffer)))) + + +;;;; +;;;; These are functions, and function re-definitions so that erbpeon can +;;;; be run in batch mode. + + +(defun erbp-batch-mprinc (arg) + (if (stringp arg) + (send-string-to-terminal arg) + (send-string-to-terminal (prin1-to-string arg)))) + + +(defun erbp-batch-mprincl (arg) + (if (stringp arg) + (progn + (send-string-to-terminal arg) + (send-string-to-terminal "\n")) + (send-string-to-terminal (prin1-to-string arg)) + (send-string-to-terminal "\n"))) + +(defun erbp-batch-parse (erbp-ignore erbp-verblist line) + (setq line-list (erbp-listify-string (concat line " "))) + (erbp-doverb erbp-ignore erbp-verblist (car line-list) (cdr line-list))) + +(defun erbp-batch-parse2 (erbp-ignore erbp-verblist line) + (setq line-list (erbp-listify-string2 (concat line " "))) + (erbp-doverb erbp-ignore erbp-verblist (car line-list) (cdr line-list))) + +(defun erbp-batch-read-line () + (read-from-minibuffer "" nil erbpeon-batch-map)) + + +(defun erbp-batch-loop () + (setq erbp-dead nil) + (setq room 0) + (while (not erbp-dead) + (if (eq erbpeon-mode 'erbpeon) + (progn + (if (not (= room erbp-current-room)) + (progn + (erbp-describe-room erbp-current-room) + (setq room erbp-current-room))) + (erbp-mprinc ">") + (setq line (downcase (erbp-read-line))) + (if (eq (erbp-vparse erbp-ignore erbp-verblist line) -1) + (erbp-mprinc "I don't understand that.\n")))))) + +(defun erbp-batch-dos-interface () + (erbp-dos-boot-msg) + (setq erbpeon-mode 'dos) + (while (eq erbpeon-mode 'dos) + (erbp-dos-prompt) + (setq line (downcase (erbp-read-line))) + (if (eq (erbp-parse2 nil erbp-dos-verbs line) -1) + (progn + (sleep-for 1) + (erbp-mprincl "Bad command or file name")))) + (goto-char (point-max)) + (erbp-mprinc "\n")) + +(defun erbp-batch-unix-interface () + (erbp-login) + (if erbp-logged-in + (progn + (setq erbpeon-mode 'unix) + (while (eq erbpeon-mode 'unix) + (erbp-mprinc "$ ") + (setq line (downcase (erbp-read-line))) + (if (eq (erbp-parse2 nil erbp-unix-verbs line) -1) + (let (esign) + (if (setq esign (string-match "=" line)) + (erbp-doassign line esign) + (erbp-mprinc (car line-list)) + (erbp-mprincl ": not found."))))) + (goto-char (point-max)) + (erbp-mprinc "\n")))) + +(defun erbpeon-nil (arg) + "noop" + (interactive "*p") + nil) + +(defun erbp-batch-erbpeon () + (load "erbp-batch") + (setq erbp-visited '(27)) + (erbp-mprinc "\n") + (erbp-batch-loop)) + +(unless (not noninteractive) + (fset 'erbp-mprinc 'erbp-batch-mprinc) + (fset 'erbp-mprincl 'erbp-batch-mprincl) + (fset 'erbp-vparse 'erbp-batch-parse) + (fset 'erbp-parse2 'erbp-batch-parse2) + (fset 'erbp-read-line 'erbp-batch-read-line) + (fset 'erbp-dos-interface 'erbp-batch-dos-interface) + (fset 'erbp-unix-interface 'erbp-batch-unix-interface) + (erbp-mprinc "\n") + (setq erbp-batch-mode t) + (erbp-batch-loop)) + +(provide 'erbpnet) + +;;; erbpnet.el ends here diff --git a/elisp/erbot/erbrss.el b/elisp/erbot/erbrss.el new file mode 100644 index 0000000..5604026 --- /dev/null +++ b/elisp/erbot/erbrss.el @@ -0,0 +1,375 @@ +;;; erbrss.el --- Provide an RSS feed from your erbot. +;; Time-stamp: <2005-01-01 17:30:49 forcer> +;; Copyright (C) 2004 Jorgen Schaefer +;; Emacs Lisp Archive entry +;; Filename: erbrss.el +;; Package: erbrss +;; Author: Jorgen Schaefer +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + +;;; Commentary: + +;; This extension to erbot will provide an RSS feed for your database +;; changes. Customize the erbrss group and run (erbrss-install) to +;; use. + +;;; Code: + +(defgroup erbrss nil + "RSS feeds for the erbot." + :group 'erbot) + +(defcustom erbrss-file-name "/tmp/erbot.rss" + "The file name for the RSS feed. This should be in your web +directory." + :type 'file + :group 'erbrss) + +(defcustom erbrss-rc-file-name "/tmp/erbot-rc.txt" + "The file name to store recent changes info in." + :type 'file + :group 'erbrss) + +(defcustom erbrss-max-age 604800 ; 7 days + "The number of seconds an entry in the recent changes should +stay." + :type 'integer + :group 'erbrss) + +(defcustom erbrss-item-resource-prefix "prefix://" + "The prefix for your item resources. This should be somewhere +on your webserver." + :type 'string + :group 'erbrss) + +(defcustom erbrss-rdf:about "rss about" + "The contents of the rdf:about attribute in your RSS feed." + :type 'string + :group 'erbrss) + +(defcustom erbrss-title "title" + "The title of your RSS feed." + :type 'string + :group 'erbrss) + +(defcustom erbrss-link "link" + "The link to your bots homepage, or the RSS feed, or wherever." + :type 'string + :group 'erbrss) + +(defcustom erbrss-description "description" + "The description of your RSS feed." + :type 'string + :group 'erbrss) + +(defcustom erbrss-dc:rights "rights" + "The copyright notice for your RSS feed." + :type 'string + :group 'erbrss) + +(defcustom erbrss-dc:publisher "publisher" + "The publisher of your RSS feed, i.e. you." + :type 'string + :group 'erbrss) + +(defcustom erbrss-dc:contributor "contributor" + "The contributors to your RSS feed. The users of the bot." + :type 'string + :group 'erbrss) + +(defcustom erbrss-image "image" + "A link to an image for your RSS feed." + :type 'string + :group 'erbrss) + +(defcustom erbrss-image-title "image title" + "A title for your RSS feed image." + :type 'string + :group 'erbrss) + +(defcustom erbrss-image-link "image link" + "A link for your image. This should point to your bots home page or so." + :type 'string + :group 'erbrss) + + + +;;; The erbot interface + +(defun erbrss-install () + "Initializer the RSS module of erbot." + (add-hook 'erbot-notify-add-functions 'erbrss-add) + (add-hook 'erbot-notify-forget-functions 'erbrss-forget) + (add-hook 'erbot-notify-move-functions 'erbrss-move) + (add-hook 'erbot-notify-rearrange-functions 'erbrss-rearrange) + (add-hook 'erbot-notify-substitute-functions 'erbrss-substitute) + (add-hook 'erbot-notify-merge-functions 'erbrss-merge)) + +(defun erbrss-add (nick channel term entry-num entry) + "Note an addition to the erbot database. +This is suitable for `erbot-notify-add-functions'." + (erbrss-rc-add term + (format "Added entry %i of %s: %s" entry-num term entry) + (format "%s in %s" nick channel))) + +(defun erbrss-forget (nick channel term entry-num entry remaining-entries) + "Note a removal from the erbot database. +This is suitable for `erbot-notify-forget-functions'." + (erbrss-rc-add term + (if (not (eq entry-num 'all)) + (format "Forgot entry %i of %s: %s\n\nRemaining:\n%s" + entry-num + term + entry + (mapconcat #'identity remaining-entries "\n")) + (format "Forgot %s:\n\n%s" + term + (mapconcat #'identity entry "\n"))) + (format "%s in %s" nick channel))) + +(defun erbrss-move (nick channel old-term new-term) + "Note a move within the erbot database. +This is suitable for `erbot-notify-move-functions'." + (erbrss-rc-add old-term + (format "Moved %s to %s" old-term new-term) + (format "%s in %s" nick channel))) + +(defun erbrss-rearrange (nick channel term + from-num from-entry + to-num to-entry) + "Note a rearrangement in the erbot database. +This is suitable for `erbot-notify-rearrange-functions'." + (erbrss-rc-add term + (format "Swapped entries %i and %i in term %s. Now:\n%i: %s\n%i: %s" + from-num to-num term + to-num from-entry + from-num to-entry) + (format "%s in %s" nick channel))) + +(defun erbrss-substitute (nick channel term entry-num old-entry new-entry) + "Note a substitution in the erbot database. +This is suitable for `erbot-notify-substitue-functions'." + (erbrss-rc-add term + (format "Changed entry %i of %s:\nOld: %s\nNew: %s" + entry-num term old-entry new-entry) + (format "%s in %s" nick channel))) + +(defun erbrss-merge (nick channel from-term to-term + from-entries to-entries final-entries) + "Note a merge in the erbot database. +This is suitable for `erbot-notify-merge-functions'." + (erbrss-rc-add + term + (format (concat "Merged %s into %s. New contents:\n" + "(1 means from %s, 2 from %s and + from both)\n" + "%s") + old-term new-term + old-term new-term + (erbrss-merge-description from-entries + to-entries + final-entries)) + (format "%s in %s" nick channel))) + +(defun erbrss-merge-description (from-entries to-entries final-entries) + "Return a string describing the merge. The string contains a +line per entry in FINAL-ENTRIES, prefixed with a 1 if that +entry is from FROM-ENTRIES, 2 if it is from TO-ENTRIES, and + +if it is from both." + (mapconcat (lambda (entry) + (format "%s %s" + (let ((fromp (member entry from-entries)) + (top (member entry to-entries))) + (cond + ((and fromp top) "+") + (fromp "1") + (top "2") + (t "?"))) + entry)) + final-entries + "\n")) + + +;;; Recent Changes +(defun erbrss-rc-add (term description contributor) + "Add this item to the recent changes list. +The list is managed in `erbrss-rc-file-name'." + (with-current-buffer (find-file-noselect erbrss-rc-file-name t) + (goto-char (point-min)) + (when (= (point-min) (point-max)) + (insert "()")) + (let* ((olddata (read (current-buffer))) + (newdata (erbrss-rc-remove-old + (append olddata + (list + (erbrss-make-item term + description + (current-time) + contributor)))))) + (delete-region (point-min) (point-max)) + (prin1 newdata (current-buffer)) + (let ((require-final-newline t)) + (save-buffer)) + (erbrss-regenerate-rss newdata)))) + +(defun erbrss-rc-remove-old (items) + "Remove any items from ITEMS that are older then `erbrss-max-age'." + (let ((new '())) + (while items + (when (< (- (float-time) + (float-time (erbrss-item-time (car items)))) + erbrss-max-age) + (setq new (cons (car items) + new))) + (setq items (cdr items))) + (reverse new))) + + +;;; RSS +(defun erbrss-regenerate-rss (items) + "Regenerate the RSS feed from ITEMS. +The feed is put into `erbrss-file-name'." + (with-current-buffer (find-file-noselect erbrss-file-name t) + (delete-region (point-min) (point-max)) + (erbrss-insert-rss items) + (let ((require-final-newline t)) + (save-buffer)))) + +(defun erbrss-insert-rss (items) + "Insert an RSS feed with ITEMS in it. +ITEMS should be a list of vectors, each vector having four elements: + +- Title +- Description +- Contributor +- Timestamp in seconds since the epoch" + (erbrss-sxml-insert + `((rdf:RDF (@ (xmlns:rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#") + (xmlns "http://purl.org/rss/1.0/") + (xmlns:dc "http://purl.org/dc/elements/1.1/")) + (channel (@ (rdf:about ,erbrss-rdf:about)) + (title ,erbrss-title) + (link ,erbrss-link) + (description ,erbrss-description) + (dc:rights ,erbrss-dc:rights) + (dc:date ,(erbrss-date)) + (dc:publisher ,erbrss-dc:publisher) + (dc:contributor ,erbrss-dc:contributor) + (items + (rdf:Seq + ,@(mapcar (lambda (item) + `(rdf:li (@ (rdf:resource + ,(erbrss-item-resource item))))) + items))) + (image (@ (rdf:resource ,erbrss-image)))) + + (image (@ (rdf:resource ,erbrss-image)) + (title ,erbrss-image-title) + (url ,erbrss-image) + (link ,erbrss-image-link)) + + ,@(mapcar #'erbrss-item items))))) + +(defun erbrss-item (item) + "Insert the RSS description of ITEM." + `(item (@ (rdf:about ,(erbrss-item-resource item))) + (title ,(erbrss-item-title item)) + ;(link ,(erbrss-item-resource item)) + (description ,(erbrss-item-description item)) + (dc:date ,(erbrss-date (erbrss-item-time item))) + (dc:contributor ,(erbrss-item-contributor item)))) + +(defun erbrss-make-item (title description time contributor) + "Create a new rss item entry." + (vector title description time contributor)) + +(defun erbrss-item-title (item) + "Return the title of ITEM." + (aref item 0)) + +(defun erbrss-item-description (item) + "Return the description of ITEM." + (aref item 1)) + +(defun erbrss-item-time (item) + "Return the modification time of ITEM." + (aref item 2)) + +(defun erbrss-item-contributor (item) + "Return the contributor of ITEM." + (aref item 3)) + +(defun erbrss-item-resource (item) + "Return the resource of ITEM. +This uses `erbrss-item-resource-prefix'." + (concat erbrss-item-resource-prefix + (erbrss-item-title item) + "?" (erbrss-date (erbrss-item-time item)))) + +(defun erbrss-date (&optional time) + "Return a string describing TIME, or the current time if nil." + (format-time-string "%Y-%m-%dT%H:%M:%S+00:00" + (or time + (current-time)) + t)) + + +;;; SXML + +(defun erbrss-sxml-insert (data) + "Insert an SXML data structure DATA." + (set-buffer-file-coding-system 'utf-8) + (insert "\n") + (erbrss-sxml-insert-data data)) + +(defun erbrss-sxml-insert-data (data) + "Insert a list of tags DATA as SXML." + (cond + ((stringp data) + (insert (erbrss-sxml-quote data))) + ((symbolp (car data)) + (erbrss-sxml-insert-tag data)) + (t + (mapcar #'erbrss-sxml-insert-data data)))) + +(defun erbrss-sxml-insert-tag (tag) + (let ((name (symbol-name (car tag))) + (attributes (if (and (consp (cdr tag)) + (consp (cadr tag)) + (eq '@ (caadr tag))) + (cdadr tag) + '())) + (body (if (and (consp (cdr tag)) + (consp (cadr tag)) + (eq '@ (caadr tag))) + (cddr tag) + (cdr tag)))) + (insert "<" name) + (mapcar (lambda (entry) + (insert " " + (erbrss-sxml-quote (symbol-name (car entry))) + "=\"" + (erbrss-sxml-quote (cadr entry)) + "\"")) + attributes) + (if (null body) + (insert "/>") + (insert ">") + (mapcar #'erbrss-sxml-insert-data body) + (insert "")))) + +(defun erbrss-sxml-quote (string) + "Quote <, > and & in STRING." + (with-temp-buffer + (mapcar (lambda (char) + (cond + ((char-equal char ?&) (insert "&")) + ((char-equal char ?<) (insert "<")) + ((char-equal char ?>) (insert ">")) + (t (insert char)))) + string) + (buffer-substring (point-min) (point-max)))) + +(provide 'erbrss) +;;; erbrss.el ends here diff --git a/elisp/erbot/erbtrain.el b/elisp/erbot/erbtrain.el new file mode 100644 index 0000000..d8f063e --- /dev/null +++ b/elisp/erbot/erbtrain.el @@ -0,0 +1,315 @@ +;;; erbtrain.el --- Train erbot (erbot).. +;; Time-stamp: <2007-11-23 11:30:00 deego> +;; Copyright (C) 2002 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbtrain.el +;; Package: erbtrain +;; Author: D. Goel +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; Thanks: Michael Olson + + +(defconst erbtrain-home-page + "http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot") + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + + +;; Quick start: +(defconst erbtrain-quick-start + "Install idledo.el (tested with 0.2) and start idledo, join IRC as +yourself through ERC (tested with CVS). + +Customize erbtrain-buffer to the buffer of the channel in which you want +to train a bot. + +Create bot-parsable strings in a file. + +Then, M-x erbtrain to set up erbtrain which will then feed the strings +to the bot in that channel slowly. +" +) +(defun erbtrain-quick-start () + "Provides electric help from variable `erbtrain-quick-start'." + (interactive) + (with-electric-help + '(lambda () (insert erbtrain-quick-start) nil) "*doc*")) +(defconst erbtrain-version "NA") + +;;========================================== +;;; Requires: +(eval-when-compile (require 'cl)) +(ignore-errors (require 'idledo)) +;;; Code: + +(defgroup erbtrain nil + "The group erbtrain." + :group 'applications) +(defcustom erbtrain-before-load-hooks nil + "Hooks to run before loading erbtrain." + :group 'erbtrain) +(defcustom erbtrain-after-load-hooks nil + "Hooks to run after loading erbtrain." + :group 'erbtrain) +(run-hooks 'erbtrain-before-load-hooks) + + +;;; Real Code: + +(defcustom erbtrain-buffer "#fsbot" + "" + :group 'erbtrain) + +(defvar erbtrain-list nil) + +(defvar erbtrain-idledo-interval-small 2) +(defvar erbtrain-idledo-interval 120) +(defvar erbtrain-idledo-interval-subsequent 10) + +;;;###autoload +(defun erbtrain-file-through-irc (file) + (interactive "f") + (setq idledo-interval-small erbtrain-idledo-interval-small) + (setq idledo-interval erbtrain-idledo-interval) + (setq idledo-interval-subsequent erbtrain-idledo-interval-subsequent) + (save-window-excursion + (find-file file) + (let ((allstrings (buffer-substring-no-properties + (point-min) (point-max)))) + (setq allstrings (split-string allstrings "\n")) + (setq erbtrain-list allstrings) + (erbtrain-resume)))) + +;;;###autoload +(defalias 'erbtrain-file 'erbtrain-file-through-irc) + + +(defvar erbtrain-local-buffer "*erbtrain-log*") + +(defun erbtrain-file-locally (file) + "EXPERIMENTAL. Can use this when you ARE su'ed so that you are in the bot's account. + +su to your bot's account and then use this... This has the minor +advantage of being much faster. " + (interactive "f") + (unless + (yes-or-no-p + (concat "Are you really logged in as the bot? ")) + (error "Please use M-x erbtrain-file instead. ")) + (save-window-excursion + (find-file file) + (let ((allstrings (buffer-substring-no-properties + (point-min) (point-max)))) + (setq allstrings (split-string allstrings "\n")) + (mapcar 'erbtrain-local allstrings))) + (display-buffer erbtrain-local-buffer)) + + +(defun erbtrain-local (str) + "See the doc for erbtrain-file-locally. " + ;;(require 'erball) + (let* ((strlisp1 (ignore-errors (fs-parse str))) + (strlisp (ignore-errors + (if (stringp strlisp1) + (erbn-read strlisp1) nil))) + (result (ignore-errors (fs-eval strlisp)))) + (erbtrain-local-log str strlisp result))) + +(defun erbtrain-local-log (str expr result) + (save-excursion + (set-buffer (get-buffer-create erbtrain-local-buffer)) + (goto-char (point-max)) + (insert "\n") + (let ((msg (concat str "\n" "=> " (format "%S" expr) "\n" "==> " + (format "%S" result) "\n\n"))) + (message "%s" msg) + (insert msg)))) + + + + +(defun erbtrain-resume () + (interactive) + (let* ((len (length erbtrain-list)) + (toolongp (> len 3000)) + ls) + (if toolongp + (progn + (setq ls (subseq erbtrain-list 0 3001)) + (setq erbtrain-list (subseq erbtrain-list 3001))) + (setq ls erbtrain-list) + (setq erbtrain-list nil) + ) + (when toolongp + (y-or-n-p + (format "Too LOONG list (%S). Type M-x erbtrain-resume later. ok?" + len))) + (mapcar + 'erbtrain-idle + (cons + ;; so that we prevent duplicate entries. + ;; this should already be the default, but just to ensure.. + ", (fs-set-add-all-disable)" + ls + ;;(list ", (fs-set-add-all-disable)") + )) + (message "Added %S idledo's" (length ls)))) + + +(defun erbtrain-idle (str) + "sets up a string to idly fed to the bot.." + (idledo-add-action-at-end + `(erbtrain ,str))) + +(defun erbtrain-idle-now (str) + "sets up a string to idly fed to the bot.." + (idledo-add-action + `(erbtrain ,str))) + + +(defun erbtrain-buggy (str) + (delete-other-windows) + (let ((buf ;;(buffer-name) + (window-buffer))) + (display-buffer erbtrain-buffer) + (let ((win (get-buffer-window erbtrain-buffer))) + (if win (select-window win) + (switch-to-buffer erbtrain-buffer))) + (goto-char (point-max)) + (insert str) + (erc-send-current-line) + (let ((bufwindow (get-buffer-window buf))) + (if bufwindow + (select-window bufwindow) + (switch-to-buffer buf))))) + + + +;;; 2003-01-13 T17:26:24-0500 (Monday) D. Goel +;;;###autoload +(defun erbtrain (str) + (delete-other-windows) + (let ((buf (get-buffer erbtrain-buffer))) + (cond + (buf + (switch-to-buffer buf) + (goto-char (point-max)) + (insert str) + (erc-send-current-line)) + (t + (beep) + (message "No buffer! Trying to recreate the idledo. ") + (sit-for 0.3) + (idledo-add-action + `(erbtrain ,str)))))) + + +;;;==================================================== +;; OT: the foll. has nothing to do with training the bot, but is a way to +;; keep ERC connection alive: + +;(defvar erbtrain-keep-alive-string +; "/ping #fsbot") + +;;;###autoload +(defcustom erbtrain-keep-alive-p t + "" + :group 'erbtrain) + + +;;; (defun erbtrain-keep-alive-kick-once-old () +;;; (interactive) +;;; (let ((erc-flood-protect nil)) +;;; (save-window-excursion +;;; (when erbtrain-keep-alive-p +;;; (erbtrain erbtrain-keep-alive-string))))) + +(defvar erbtrain-keep-alive-buffer "#somechannel") + + + +;;; 2003-02-05 T13:22:11-0500 (Wednesday) D. Goel +;; should do it like this: +;; (erc-with-all-buffers-of-server nil #'erc-server-buffer-p +;; (lambda () \...)) + +(defun erbtrain-keep-alive-kick-once () + (interactive) + (let ((erc-flood-protect nil)) + (mapcar + (lambda (arg) + (save-window-excursion + (let ((bufname (buffer-name-p-my arg))) + (when bufname + (switch-to-buffer arg) + ;;(erc-cmd-PING "nickserv") + (when (erc-process-alive) (erc-send-command "PING")))))) + (if (listp erbtrain-keep-alive-buffer) erbtrain-keep-alive-buffer + (list erbtrain-keep-alive-buffer))))) + +(defvar erbtrain-keep-alive-timer nil) + +;;;###autoload +(defun erbtrain-keep-alive () + (interactive) + ;;(idledo-nullify) + (setq erbtrain-keep-alive-timer + (run-with-timer 30 + 10 + 'erbtrain-keep-alive-kick-once)) + ;;(setq erbtrain-keep-alive-active-p + ;;t) + + (message "Started erbtrain-keep-alive. ")) + + +;;;==================================================== + +(defun erbtrain-utils-teach-acronyms (&optional botstring) + "Teach the the bot from BOTSTRING some acronyms. +You will need wtf.el (from the contrib directory) for this +function to work. +See also the new function fs-wtf. +Don't forget to connect to irc before running this function." + (interactive) + (idledo-nullify) + (require 'wtf) + (unless botstring (setq botstring ", ")) + (setq erbtrain-list + (mapcar #'(lambda (ref) + (concat botstring (car ref) + " is short for " + (upcase-initials (cdr ref)))) + wtf-alist)) + (erbtrain-resume) + (ignore-errors (idledo-start))) + + +(provide 'erbtrain) +(run-hooks 'erbtrain-after-load-hooks) + + + +;;; erbtrain.el ends here diff --git a/elisp/erbot/erbtranslate.el b/elisp/erbot/erbtranslate.el new file mode 100644 index 0000000..a12dcd7 --- /dev/null +++ b/elisp/erbot/erbtranslate.el @@ -0,0 +1,139 @@ +;;; erbtranslate.el --- Natural Language translation functions. +;; Time-stamp: <2009-09-26 22:33:14 fledermaus> +;; Copyright © 2002 Alejandro Benitez +;; Emacs Lisp Archive entry +;; Filename: erbtranslate.el +;; Package: erbot +;; Authors: Alejandro Benitez , +;; Vivek Dasmohapatra +;; Deepak Goel +;; Maintainer: Vivek Dasmohapatra +;; Version: 0.1DEV +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;; You need to install libtranslate for this to work. The binary, +;; translate-bin, is provided, for example in Ubuntu Dapper: +;; http://packages.ubuntu.com/dapper/libs/libtranslate-bin +;; See also: + +(defvar erbtranslate-version "0.1dev") + +(require 'translate) + +(defun erbtranslate-enabled-check () + (erbutils-enabled-check erbn-translate-p)) + +(defalias 'fsi-t8 'fsi-translate) + +(defcustom erbn-translate-p nil + "Enabling this should be completely safe. We do use call-process +here whenever passing any arguments to external commands.") + +(defun fsi-translate (&optional from to &rest text) + (erbtranslate-enabled-check) + (if (not (and from to text)) + (let ((frame (backtrace-frame 3)) (caller nil)) + (setq caller (symbol-name (cadr frame)) + caller (replace-regexp-in-string "^\\w+-" "" caller)) + (format "Usage: ,%s FROM TO TEXT" caller)) + (setq text (mapconcat #'(lambda (arg) (format "%s" arg)) text " ") + from (format "%s" from) + to (format "%s" to )) + (condition-case caught + (translate from to text) + (error (concat "libtranslate error:" (cdr caught)) )) )) + +(defalias 'fsi-t8-l 'fsi-translate-list-pairs) + +(defun fsi-translate-list-pairs (&optional from to &rest args) + "Allow the user to search for translation pairs. Only gives counts +unless both from and to are specified. *, any, - are allowed as wildcards." + (erbtranslate-enabled-check) + (let ((pair-data)) + (setq from (format "%s" (or from "*")) + to (format "%s" (or to "*")) + pair-data (translate-list-pairs from to)) + (if (string-match "^\\(?:\*\\|any\\|-\\|\\)$" from) (setq from nil)) + (if (string-match "^\\(?:\*\\|any\\|-\\|\\)$" to ) (setq to nil)) + (cond + ( (and (not from) (not to)) ;; neither end point specified + (concat + (format "%d language pair(s) available.\n" (length pair-data)) + "Specify an origin and/or destination language to see a list:\n" + " translate-list-pairs es ja\n" + " translate-list-pairs castilian\n" + " translate-list-pairs * zh-TW\n") ) + ( (or (not to) (not from)) ;; one end point specified + (let ( (dir (if from "From" "To")) + (op (if from 'cadr 'car)) + (s nil) + (x (length pair-data)) + (fl (format "%s" (or from to))) ) + (setq s (mapcar (lambda (p) (car (funcall op p))) pair-data) + fl (or (translate-full-name fl) fl)) + (apply 'concat + (format "%s %s: %d language(s) available.\n" dir fl x) + (if (<= (length s) 100) + (list + (mapconcat + (lambda (x) (translate-full-name x)) s ", ")) ))) ) + (t ;; fully spec'd translation + (let ( (x (length pair-data)) ) + (setq from (or (translate-full-name from) from) + to (or (translate-full-name to ) to )) + (apply 'concat + (format "%s -> %s: %d pair(s) available.\n" from to x) + (mapcar (lambda (x) + (format "%s -> %s\n" + (princ (car x)) + (princ (cadr x)))) pair-data)) )) ) )) + +(defalias 'fsi-t8-s 'fsi-translate-list-services) + +(defun fsi-translate-list-services (&rest args) + (erbtranslate-enabled-check) + (erbn-shell-command-to-string + (concat translate-program " --list-services") + '(t))) + +(defun fsi-kks (&rest nihongo) + (let ( (coding-system-for-read 'euc-jp) + (coding-system-for-write 'euc-jp) + (text (mapconcat #'(lambda (x) (format "%s" x)) nihongo " ")) ) + (with-temp-buffer + (insert text) + (shell-command-on-region + (point-min) (point-max) + "kakasi -i euc -Ha -Ka -Ja -Ea -ka -s | sed 's/ESC<2E>.//g'" nil t) + (buffer-string)) )) +;; temporarily disabled till clean support is provided by translate.el + +;; (defun fsi-translate-web-page (from to url &rest args) +;; (erbtranslate-enabled-check) +;; (shsp (list erbn-translate-program +;; "-f" +;; (format "%s" from) "-t" +;; (format "%s" to) +;; (format "%s" url)))) + +;; (defalias 'fsi-t8-w 'fsi-translate-web-page) + +(provide 'erbtranslate) +;;; erbtranslate.el ends here diff --git a/elisp/erbot/erbunlisp.el b/elisp/erbot/erbunlisp.el new file mode 100644 index 0000000..9ad196a --- /dev/null +++ b/elisp/erbot/erbunlisp.el @@ -0,0 +1,90 @@ +;;; erbunlisp.el --- Help Simplify functions for nonlisp channels. +;; Time-stamp: <2007-11-23 11:29:47 deego> +;; Copyright (C) 2003 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbunlisp.el +;; Package: erbunlisp +;; Author: D. Goel +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + + +(defconst erbunlisp-home-page + "http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot") + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +(defconst erbunlisp-version "0.0dev") + +;;========================================== +;;; Requires: +(eval-when-compile (require 'cl)) + +;;; Code: + +(defgroup erbunlisp nil + "The group erbunlisp." + :group 'applications) +(defcustom erbunlisp-before-load-hooks nil + "Hooks to run before loading erbunlisp." + :group 'erbunlisp) +(defcustom erbunlisp-after-load-hooks nil + "Hooks to run after loading erbunlisp." + :group 'erbunlisp) +(run-hooks 'erbunlisp-before-load-hooks) + + + +;;; Real Code: + +(defcustom erbunlisp-list + '((fs-remove fs-forget remove)) + "When you type erbunlisp-install, the first entries will get aliased +to second one. +When you type erbunlisp-uninstall, the first entries will get aliased +to the third one. " + :group 'erbunlisp) + + + +(defun erbunlisp-install () + (interactive) + (mapcar + (lambda (arg) + (defalias (first arg) + (second arg))) + erbunlisp-list)) + +(defun erbunlisp-uninstall () + (interactive) + (mapcar + (lambda (arg) + (defalias (first arg) (third arg))) + erbunlisp-list)) + + +(provide 'erbunlisp) +(run-hooks 'erbunlisp-after-load-hooks) + + + +;;; erbunlisp.el ends here diff --git a/elisp/erbot/erburl.el b/elisp/erbot/erburl.el new file mode 100644 index 0000000..4995b45 --- /dev/null +++ b/elisp/erbot/erburl.el @@ -0,0 +1,219 @@ +;;; erburl.el --- Learn terms from a url. +;; Time-stamp: +;; Copyright (C) 2004 Pete Kazmier +;; Emacs Lisp Archive entry +;; Filename: erburl.el +;; Package: erburl +;; Author: Pete Kazmier +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + +(defconst erbtrain-home-page + "http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot") + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + + +;; Quick start: +(defconst erburl-quick-start + "This library enables one to add and remove entries to your bot's +bbdb that have been \"scraped\" from sources on the web. When using +this library, you must be running under the uid of your bot. In +addition, (although I'm not positive), you should make sure that only +one instance of your bot is running to avoid clobbering the bbdb. I +use this library in the emacs session of my running bot. Although the +main function of this library is asynchronous, when adding a lot of +terms, the local session is not really useable (you see the progress +though), however the bot still responds to requests from its channels. + +With that all said, lets add the terms from a wiki using the wiki page +name as the term. The note attached to the term will be a string in +the form of \"at URL\" where URL is the URL to the page: + + (erburl-scrape-terms + \"http://www.emacswiki.org/cgi-bin/wiki?action=index\") + +This library can be used to add terms from any web page because you +can pass your own parser to ERBURL-SCRAPE-TERMS (see the doc string +for the full details). This includes parsing pages and adding notes +that contain information other than a simple link back to the original +page. + +The library also includes a function to remove all entries that +contain a specific URL in the notes of an entry. It will only remove +the term in its entirety if it does not contain other notes for the +same term. It should be noted that this function is not asynchronous +and will cause your bot to stop responding on channels if it is +deleting a large number of records. + +Finally, for an additional reference to using this library, please see +erbjavadoc which uses this library to provide a command that will +permit users to add javadoc entries from a set of javadoc pages. +" + ) + +(defun erburl-quick-start () + "Provides electric help from variable `erburl-quick-start'." + (interactive) + (with-electric-help + '(lambda () (insert erburl-quick-start) nil) "*doc*")) + +(defconst erburl-version "0.0dev") + +;;========================================== +;;; Requires: +(require 'cl) +(require 'url) + +;;; Code: + +(defgroup erburl nil + "The group erburl." + :group 'applications) + +(defcustom erburl-before-load-hooks nil + "Hooks to run before loading erburl." + :group 'erburl) + +(defcustom erburl-after-load-hooks nil + "Hooks to run after loading erburl." + :group 'erburl) + +(run-hooks 'erburl-before-load-hooks) + +;;; Real Code: + + +(defun erburl-scrape-terms (url &optional entry-parser-fn progress-callback cbargs) + "Scrape terms from URL using the ENTRY-PARSER-FN and add them to the +erbot's botbbdb. Due to the asynchronous nature of this call, messages +are sent to PROGRESS-CALLBACK to report process. + +ENTRY-PARSER-FN is called when the contents of the URL have finished +downloading into a buffer. The contents of the buffer include any +headers that were sent followed by a blank line and then followed by +the actual contents of the URL. When ENTRY-PARSER-FN is called, this +buffer has already been selected. ENTRY-PARSER-FN is passed CBARGS as +arguments, and must return a list of entries to be added to the bbdb. +Each entry should be a list of two elements with the term as the first +element and the definition as the second. The default parser used if +one is not specified is ERBURL-HREF-PARSER (which parses href links). + +PROGRESS-CALLBACK is called once after the entries have been added to +the bbdb with a descriptive message indicating how many terms were +added. It may also be called after the entries have been parsed with +a message indicating that it will take a significant amount of time to +add the entries to the bbdb. When PROGRESS-CALLBACK is called, it is +passed a message as the first argument and then CBARGS are passed as +additional arguments. The default callback used if one is not +specified is MESSAGE. + +CBARGS are passed as additional argements to both of the callback +functions. +" + (let ((parser (or entry-parser-fn 'erburl-href-parser)) + (progress (or progress-callback 'message))) + (url-retrieve url + 'erburl-scrape-callback + (list url parser progress cbargs)))) + +(defun erburl-scrape-callback (url entry-parser-fn progress-callback cbargs) + "Callback invoked by url-retrieve. It is invoked in the buffer with +the contents of the retrieved URL. In addition, this method is passed +two additional callbacks to assist during processing (please refer to +erburl-scrape-terms doc). Finally, CBARGS is a list of arguments that +will be passed as additional arguments to the callback functions (I +wish elisp supported lexical closures!)" + (goto-char (point-min)) + (let* ((buffer (current-buffer)) + (count 0) + (entries (apply entry-parser-fn cbargs)) + (delay 0.1) + (total (length entries)) + (eta (* total delay))) + (when (> eta 10) + (apply progress-callback + (format "Processing %d entries from %s will take at least %.1f minutes ..." + total url (/ eta 60)) + cbargs)) + (erbot-working + (dolist (entry entries) + (message "Adding entry for %s" (first entry)) + (sleep-for 0.1) + ;; I need to find a way to speed this up. As the bbdb gets + ;; larger things really start to slow down significantly. + (when (or (ignore-errors (apply 'fs-set-also entry)) + (ignore-errors (apply 'fs-set-term entry))) + (incf count)))) + (erbbdb-save) + (apply progress-callback + (format "Added %d entries from %s." count url) + cbargs) + (kill-buffer buffer))) + +;; This needs to be asynchronous if we are to make an fsi-* version +;; for IRC users to execute because this function is very slow when +;; removing a large number of entries from the bbdb. +(defun erburl-forget-terms (url) + "Remove all terms and entries for the specified URL. This will +remove terms from the bbdb entirely unless a particular term has more +than one entry, in which case, only the relevant entry is removed. +Note: this function is not asynchronous and will cause your bot to +stop responding on channels if it is removing a large number of +entries that match the specified URL." + (unless (string-match "^https?://[^/]+/" url) + (error "The specified URL is not well-formed")) + (let ((count 0) + (regexp (regexp-quote url)) + (erbforget-interactivity -100)) + (erbot-working + (setq count (erbforget-sw regexp nil t))) + (erbbdb-save) + count)) + +(defun erburl-href-parser (&optional base terms-with-spaces-p) + "Returns a list of lists representing the HTML links in the current +buffer. Each list is composed of a term and a string indicating the +link which is prefixed with BASE if supplied. If TERMS-WITH-SPACES-P +is non-nil, only links with single word text will be included." + (let ((entries '()) + (case-fold-search t)) + (while (re-search-forward + (if terms-with-spaces-p + "
    \\(?:<[^>]+>\\)*\\([^ <]+\\)\\(?:<[^>]+>\\)*" + "\\(?:<[^>]+>\\)*\\([^<]+\\)\\(?:<[^>]+>\\)*") + nil t) + (push (list (match-string 2) + (concat "at " + (when base (concat base "/")) + (match-string 1))) + entries)) + entries)) + +(defun erburl-safe-url (url) + ) + +(provide 'erburl) +(run-hooks 'erburl-after-load-hooks) + +;;; erburl.el ends here diff --git a/elisp/erbot/erbutils.el b/elisp/erbot/erbutils.el new file mode 100644 index 0000000..72682b8 --- /dev/null +++ b/elisp/erbot/erbutils.el @@ -0,0 +1,660 @@ +;;; erbutils.el --- +;; Time-stamp: <2007-11-23 11:29:44 deego> +;; Copyright (C) 2002,2003,2004,2005 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbutils.el +;; Package: erbutils +;; Author: D. Goel +;; Version: 0.0dev +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot + + +(defvar erbutils-home-page + "http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot") + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +(defvar erbutils-version "0.0dev") + +;;========================================== +;;; Code: +(require 'rot13) + +(defgroup erbutils nil + "The group erbutils" + :group 'applications) +(defcustom erbutils-before-load-hooks nil "" :group 'erbutils) +(defcustom erbutils-after-load-hooks nil "" :group 'erbutils) +(run-hooks 'erbutils-before-load-hooks) + + +(defalias 'erbutils-stringize 'erbutils-stringify) +;; should please not eval anyting... since called by erbc.. + +(defun erbutils-stringify (msg-list) + (if (stringp msg-list) + msg-list + (mapconcat + '(lambda (arg) + (if (stringp arg) arg + (format "%s" arg))) + msg-list " " ))) + + +(defun erbutils-string= (foo bar &optional ignore-case) + (and foo bar + (if ignore-case + (string= (downcase foo) (downcase bar)) + (string= foo bar)))) + + +(defun erbutils-errors-toggle () + (interactive) + (setq erbutils-ignore-errors-p + (not erbutils-ignore-errors-p)) + (message "erbutils-ignore-errors-p set to %s" + erbutils-ignore-errors-p)) + + +(defvar erbutils-ignore-errors-p t) +(defmacro erbutils-ignore-errors (&rest body) + "DOES NOT return nil, unlike ignore-errors.." + (let ((err (gensym))) + `(condition-case ,err (progn ,@body) + (error + (progn + ;(ding t) + ;(ding t) + ;;(message "ERROR: %s" (error-message-string ,err)) + ;;(sit-for 1) + (ding t) + (unless erbutils-ignore-errors-p + (error (error-message-string ,err))) + (unless fs-found-query-p + (erbutils-error + "%s" + (fs-limit-lines + (error-message-string ,err))))))))) + +(defvar erbutils-error-debug-p nil + "Turn on for debugging.." + ) +(defun erbutils-error (&rest args) + (cond + (erbutils-error-debug-p (apply 'error args)) + (t + (unless args (error + (format "Syntax: , (fs-error msg &rest format-args)"))) + (let* ((main + (erbutils-random + '("oops, error. %s" + ;;"Blue Screen: %s" + "BEEEP: %s" + "ERROR: %s" + "err..%s" + ":( %s" + "Doh! %s" + "Oh sh**! %s" + "Nooo! %s" + "oops, %s" + "Uh oh, %s" + "whoops, %s" + ))) + (result + (format main + (apply 'format args)))) + (or + (ignore-errors + (fs-h4x0r-maybe + (fs-studlify-maybe + result))) + result))))) + + + +(defun erbutils-matching-functions (string) + "returns all functions that start with string" + (apropos-internal (concat "^" (regexp-quote string)) + 'fboundp) + + ;; (let* ((results nil) +;;; (len (- (length obarray) 1)) +;;; (ctr 0)) +;;; (while (< ctr len) +;;; (incf ctr) +;;; (if (and +;;; (equal (string-match string (format "%s" (aref obarray +;;; ctr))) +;;; 0) +;;; (fboundp (aref obarray ctr)) +;;; ) +;;; (push (aref obarray ctr) results))) +;;; results) +) + + + + + + (defun erbutils-quote-list (ls) + "ls is, in general, a tree... + + We will make sure here that each element of the tree that is a symbol gets + quoted... + + + " + (mapcar '(lambda (arg) + (list 'quote arg)) + ls)) + +(defun erbutils-random (list &optional weights) + "Return a random element from list. +Optional WEIGHTS are relative. They should be integers. +example: (erbutils-random '(a b c) '(1 1 2)) should return c twice +as many times as it returns a... +" + (cond + ((null weights) + (nth (random (length list)) list)) + (t + (let* ((len (length list)) + (revw (reverse weights)) + (fir (car revw)) + ) + ;; If weights are partially specified, fill in missing entries. + (while (< (length revw) len) + (setq revw (cons fir revw))) + (setq weights (reverse revw)) + (let* ((total (apply '+ weights)) + (choice (random total)) + (curw weights) + (ctr 0) + (num 0)) + + (while (>= choice (+ ctr (car curw))) + (setq ctr (+ ctr (car curw))) + (incf num) + (setq curw (cdr curw))) + (nth num list)))))) + + + +(defun erbutils-describe-variable (&optional variable buffer) + "Like describe-variable, but doesn't print the actual value.." + (unless (bufferp buffer) (setq buffer (current-buffer))) + (if (not (symbolp variable)) + (message "Unknown variable or You did not specify a variable") + (let (valvoid) + (with-current-buffer buffer + (with-output-to-temp-buffer "*Help*" + (terpri) + (if (erbcompat-local-variable-p variable) + (progn + (princ (format "Local in buffer %s; " (buffer-name))) + + (terpri))) + (terpri) + (let ((doc + (documentation-property variable 'variable-documentation))) + (princ (or doc "not documented as a variable."))) + (help-setup-xref (list #'describe-variable variable (current-buffer)) + (interactive-p)) + + ;; Make a link to customize if this variable can be customized. + ;; Note, it is not reliable to test only for a custom-type property + ;; because those are only present after the var's definition + ;; has been loaded. + (if (or (get variable 'custom-type) ; after defcustom + (get variable 'custom-loads) ; from loaddefs.el + (get variable 'standard-value)) ; from cus-start.el + (let ((customize-label "customize")) + (terpri) + (terpri) + (princ (concat "You can " customize-label " this variable.")) + (with-current-buffer "*Help*" + (save-excursion + (re-search-backward + (concat "\\(" customize-label "\\)") nil t) + (if (> 22 emacs-major-version) + (help-xref-button 1 (lambda (v) + (if help-xref-stack + (pop help-xref-stack)) + (customize-variable v)) + variable + "mouse-2, RET: customize variable") + (help-xref-button 1 'help-customize-variable variable)) + )))) + ;; Make a hyperlink to the library if appropriate. (Don't + ;; change the format of the buffer's initial line in case + ;; anything expects the current format.) + (let ((file-name (symbol-file variable))) + (when file-name + (princ "\n\nDefined in `") + (princ file-name) + (princ "'.") + (with-current-buffer "*Help*" + (save-excursion + (re-search-backward "`\\([^`']+\\)'" nil t) + (if (> 22 emacs-major-version) + (help-xref-button + 1 (lambda (arg) + (let ((location + (find-variable-noselect arg))) + (pop-to-buffer (car location)) + (goto-char (cdr location)))) + variable "mouse-2, RET: find variable's definition") + (help-xref-button 1 'help-variable-def variable file-name)) + )))) + + (print-help-return-message) + (save-excursion + (set-buffer standard-output) + ;; Return the text we displayed. + (buffer-substring-no-properties (point-min) (point-max)))))))) + + +(defvar erbutils-itemize-style + (list "[%s] %s\n\n" "[%s] %s\n\n" "[%s] %s,\n\n") + + "Another good choice, for example, and used by petekaz's petebot, is + \(list \"[%s] %s,\n\n\" \"and also [%s] %s\n\n\" \"and [%s] %s,\n\n\") +") + +(defun erbutils-itemize (result &optional N shortenedp style) + (unless style (setq style erbutils-itemize-style)) + (unless (integerp N) (setq N 0)) + (let + ((st1 (first style)) + (st2 (second style)) + (st3 (third style)) + (ctr N) + (rem result) + (sofar "")) + (if (equal (length result) 1) + (setq sofar (format "%s" (car result))) + (while rem + (setq sofar + (concat + sofar + (format + (cond + ((= ctr 0) + st1) + ((null (rest rem)) + st2) + (t st3)) + ctr + (car rem)))) + (setq ctr (+ ctr 1)) + (setq rem (cdr rem)))) + (when shortenedp + (setq sofar (concat sofar " .. + other entries"))) + sofar)) + + + +(defun erbutils-function-minus-doc (fstr &rest ignore) + "fstr is the string containing the function" + (let* ((fdoc (if (stringp fstr) fstr (format "%s" fstr))) + newdoc) + (setq newdoc + (with-temp-buffer + (insert fdoc) + (goto-char (point-min)) + (search-forward "(" nil t) + (forward-sexp 4) + (if (stringp (sexp-at-point)) + ;; this sets mark.. bad programming, i know.. + (backward-kill-sexp 1)) + (erbutils-buffer-string))) + (erbutils-single-lines newdoc))) + +(defun erbutils-single-lines (str) + "Eliminates all \n or lines comprising entirely of whitespace" + (mapconcat + 'identity + (delete-if + (lambda (str) + (string-match "^[ \t]*$" str)) + (split-string str + "\n")) + "\n")) + +(defun erbutils-cleanup-whitespace (str) + "Strip all leading whitespace and replace one or more tabs, newlines, +or spaces with a single space." + (let ((result (replace-regexp-in-string "[\t\n ]+" " " str))) + (subseq result (or (position ? result :test-not 'eq) 0)))) + +(defun erbutils-downcase (str) + (if (stringp str) + (downcase str) + str)) + + + + + + +(defun erbutils-add-nick (msg) + (if + (and (not fs-found-query-p) + (not fs-internal-directed) + (> (random 100) 30) + (stringp msg)) + (eval + (erbutils-random + '( + ;;(concat msg ", " fs-nick) + (concat fs-nick ": " msg) + (concat fs-nick ", " msg) + ) + '(1 1 ))) + msg)) + + +(defun erbutils-add-nick-maybe (msg) + (eval + (erbutils-random + '((erbutils-add-nick msg) + msg) + fs-internal-add-nick-weights + ))) + + +(defun erbutils-convert-sequence (arg) + (if (sequencep arg) + arg + (format "%s" arg))) + + +(defvar erbutils-eval-until-limited-length 70) +(defun erbutils-eval-until-limited (expr) + (let + ((ans nil) (donep nil)) + (while (not donep) + (setq ans + (eval expr)) + (setq donep (<= (length (format "%s" ans)) + erbutils-eval-until-limited-length))) + ans)) + + + +(defun erbutils-replace-strings-in-string (froms tos str &rest + args) + (let ((st str)) + (mapcar* + (lambda (a b) + (setq st (apply 'erbutils-replace-string-in-string + a b st args))) + froms tos) + st)) + +;;;###autoload +(if (featurep 'xemacs) + (defun erbutils-replace-string-in-string (from to string &optional + delimited start end) + (save-excursion + (with-temp-buffer + (insert string) + (save-restriction + (narrow-to-region (or start (point-min)) (or end (point-max))) + (goto-char (point-min)) + (replace-string from to delimited)) + (buffer-substring-no-properties (point-min) (point-max))))) + (defun erbutils-replace-string-in-string (from to string &optional + delimited start end) + (save-excursion + (with-temp-buffer + (insert string) + (goto-char (point-min)) + (replace-string from to delimited start end) + (buffer-substring-no-properties (point-min) (point-max)))))) + +(defun erbutils-sublist-p (a b &optional start) + "tells if list a is a member of list b. If start is true, the match +should start at the beginning of b." + (cond + ((null a) t) + ((null b) nil) + (start (and + (equal (car a) (car b)) + (erbutils-sublist-p (cdr a) (cdr b) t))) + (t + (let ((foo (member (car a) b))) + (and foo + (or + (erbutils-sublist-p (cdr a) (cdr foo) t) + (erbutils-sublist-p a (cdr foo)))))))) + +;;;###autoload +(defun erbutils-flatten (tree) + (cond + ((null tree) nil) + ((listp tree) (apply 'append + (mapcar 'erbutils-flatten tree))) + (t (list tree)))) + +(provide 'erbutils) +(run-hooks 'erbutils-after-load-hooks) + + +(defun erbutils-remove-text-properties (str1) +;;; (with-temp-buffer +;;; (insert text) +;;; (buffer-substring-no-properties (point-min) (point-max)))) + ;; fledermaus' code: avoid with-temp-buffer becuse of i8n problems. + (let ((str (copy-sequence str1))) + (set-text-properties 0 (length str) nil str) + str)) + + + +(defun erbutils-defalias-i (ls &optional prefix prefix-rm + functionpref) + "Similar to erbutils-defalias, except that for functions, it +defaliases a 'fsi-" + (unless functionpref (setq functionpref "fsi-")) + (erbutils-defalias ls prefix prefix-rm functionpref)) + + +(defun erbutils-defalias (ls &optional prefix prefix-rm functionpref) + "Define new fs- aliases from ls. + +If the entry in the ls is a function, it is defaliased. If it is a +variable, we define a new function, that will return the value of the +variable. + +When prefix and prefix-rm is provided, we assume that the entry is of +the form prefix-rmENTRY. And we then (defalias fs-prefixENTRY +prefix-rmENTRY. + +functionpref should usually be fs-. If you want fsi- instead, you +might prefer calling erbutils-defalias-i instead. +" + (unless functionpref (setq functionpref "fs-")) + (let* ((pref (if prefix (format "%s" prefix) "")) + (pref-rm (if prefix-rm (format "%s" prefix-rm) "")) + (lenrm (length pref-rm)) + (reg (concat "^" (regexp-quote pref-rm)))) + (mapcar + (lambda (arg) + (let* ( + (argst (format "%s" arg)) + (gop (string-match reg argst)) + (arg2 (and gop (substring argst lenrm))) + (foo (and gop (intern (format (concat functionpref "%s%s") + pref arg2))))) + + (when gop + (if (functionp arg) + (defalias foo arg) + (erbutils-defalias-vars (list arg prefix prefix-rm)) + ;;`(defun ,foo () + ;; ,(concat "Pseudo function that returns the value of `" + ;; argst "'. ") + ;;,arg) + )))) + ls))) + +(defun erbutils-defalias-vars (ls &optional prefix prefix-rm) + (let* ((pref (if prefix (format "%s" prefix) "")) + (pref-rm (if prefix-rm (format "%s" prefix-rm) "")) + (lenrm (length pref-rm)) + (reg (concat "^" (regexp-quote pref-rm)))) + (mapcar + (lambda (arg) + (let* ( + (argst (format "%s" arg)) + (gop (string-match reg argst)) + (arg2 (and gop (substring argst lenrm))) + (foo (and gop (intern (format "fs-%s%s" pref arg2))))) + + (when gop + (eval + `(defun ,foo () + ,(concat "Pseudo function that returns the value of `" + argst "'. ") + ,arg))))) + ls))) + + +(defun erbutils-region-to-string (fcn &rest str) + (with-temp-buffer + (while str + (let ((aa (car str))) + (when aa + (insert (format "%s " aa)))) + (pop str)) + (goto-char (point-min)) + (funcall fcn (point-min) (point-max)) + (buffer-substring-no-properties (point-min) (point-max)))) + + +(defun erbutils-rot13 (str) + (apply + 'string + (mapcar + (lambda (i) + (let ((foo (aref rot13-display-table i))) + (if foo (aref foo 0) i))) + str))) + +(defun erbutils-file-contents (file) + (cond + ((not (file-exists-p file)) + "") + (t + (with-temp-buffer + (insert-file-contents file) + (buffer-substring-no-properties (point-min) (point-max)))))) + + +(defun erbutils-file-sexps (file) + (let ((str (erbutils-file-contents file)) + expr) + (and + (stringp str) + (not (string= str "")) + (setq expr (erbn-read (concat " ( " str " )")))))) + + +(defun erbutils-functions-in-file (file) + "Returns the list of functions in the file. File should be a valid +lisp file, else error. " + (let ((str (erbutils-file-contents file)) + expr) + (and + (stringp str) + (not (string= str "")) + (setq expr (erbn-read (concat " ( " str " )"))) + (ignore-errors (mapcar 'second expr))))) + + + +(defun erbutils-mkback-maybe (file) + (ignore-errors (require 'mkback)) + (ignore-errors + (let ((mkback-interactivity -100)) + (mkback file)))) + + +(defun erbutils-listp-proper (l) + "from " + (or (null l) (and (consp l) + (erbutils-listp-proper (cdr l))))) + + +(defun erbutils-html-url-p (str) + "Guesses if the string is a url that will yield HTML content. +Basically, look for any url that doesn't have any extension or +one that has .html, .shtml, or .htm. Returns the str if it is +a valid url that might generate HTML." + (when (string-match "^http://[^/]+/?\\(.*\\)?$" str) + (let* ((path (match-string 1 str)) + (pos (position ?. path :from-end))) + (when (or (null pos) + (string-match "html?" (subseq path pos))) + str)))) + + +;;;###autoload +(defun erbutils-concat-symbols (&rest args) + "Like `concat' but applies to symbols, and returns an interned +concatted symbol. Also see fsbot's +`erbn-command-list-from-prefix'. + +Thanks to edrx on #emacs for suggesting 'symbol-name.." + (let* ((strings (mapcar 'symbol-name args)) + (str (apply 'concat strings))) + (intern str))) + + + + +(defun erbutils-remove-text--properties (str) + (let (str2) + (cond + ((stringp str) + (setq str2 (copy-sequence str)) + (set-text-properties 0 (length str2) nil str2) + str2) + (t (error "Not a string."))))) + + + + +(defun erbutils-remove-text-properties-maybe (str) + (if (stringp str) + (erbutils-remove-text-properties str) + str)) + + +(defun erbutils-buffer-string () + (buffer-substring-no-properties (point-min) (point-max))) + + +(defmacro erbutils-enabled-check (var) + `(when (or erbot-paranoid-p (not ,var)) + (error "Variable %s is disabled, or erbot-paranoid-p is t. " ',var))) + +;;; erbutils.el ends here diff --git a/elisp/erbot/erbwiki.el b/elisp/erbot/erbwiki.el new file mode 100644 index 0000000..4448a90 --- /dev/null +++ b/elisp/erbot/erbwiki.el @@ -0,0 +1,646 @@ +;;; erbwiki.el --- SECURITY RISK, READ BELOW. +;; Time-stamp: <2007-11-23 11:27:02 deego> +;; Copyright (C) 2002, 2003 D. Goel +;; Emacs Lisp Archive entry +;; Filename: erbwiki.el +;; Package: erbwiki +;; Author: D. Goel +;; Keywords: +;; Version: +;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot +;; Thanks: Alex Schroeder + +;; USING ERBWIKI.EL TO TRAIN YOUR BOTS ON WIKIS WITH LINES VERSION < +;; 0.3 IS A SECURITY RISK!! EARLIER LINES.EL CAN BE MADE TO EVAL AN +;; ARBITRARY LISP EXPRESSION, INCLUDING (SHELL-COMMAND "RM -RF"), WE +;; THINK, THOUGH WE HAVEN'T FIGURED OUT HOW. ANYHOW, USE LINES.EL > +;; 0.3 ONLY. + + +(defconst erbwiki-home-page + "http://www.emacswiki.org/cgi-bin/wiki.pl?ErBot") + + + +;; This file is NOT (yet) part of GNU Emacs. + +;; This 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 3, or (at your option) +;; any later version. + +;; This 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;; See also: + +(defconst erbwiki-version "0.0dev") + + +;;========================================== +;;; Requires: +(eval-when-compile (require 'cl)) + +;;; Code: + +(defgroup erbwiki nil + "The group erbwiki." + :group 'applications) +(defcustom erbwiki-before-load-hooks nil + "Hooks to run before loading erbwiki." + :group 'erbwiki) +(defcustom erbwiki-after-load-hooks nil + "Hooks to run after loading erbwiki." + :group 'erbwiki) +(run-hooks 'erbwiki-before-load-hooks) + +;;; Real Code: + +;; It's like 2 lines of code to pull down the names of all the +;;pages. + +;; import xmlrpclib +;; srcwiki =xmlrpclib.ServerProxy("http://mywiki.org/?action=xmlrpc2") +;; allpages = srcwiki.getAllPages() +;; The wiki has to support the xml-rpc interface. +;; But for MoinMoin, +;; it's pretty much ubiquitous +;; http://twistedmatrix.com/wiki/moin/WikiRpc +;; Bayle Shanks has written a thing called the "InterWiki Gateway." +;; It's not quite mature yet, +;; but it's goal is to make it so that the XML-RPC API will work +;; with any wiki. +;; It'll just handle the back-end stuff of figuring out "what type +;; of wiki +;; is it" and "how do I scrape the information out." +;; But it's not quite there yet. + + +;;TODO: add this wiki: +;;http://www.nanoaging.com/wiki/index.php/Main_Page" +(defcustom erbwiki-index-pages + + '( + + + ("si" + "http://www.gnufans.net/cgi-bin/singularity.pl?" + "\"http://localhost/cgi-bin/singularity.pl?action=index\"" + nil + "singbot: " + ) + + ("ai2" + "http://www.ifi.unizh.ch/ailab/aiwiki/aiw.cgi?" + "\"http://www.ifi.unizh.ch/ailab/aiwiki/aiw.cgi?action=index\"" + nil + "singbot: " + ) + + + + ("sl" + "http://www.sl4.org/bin/wiki.pl?" + "\"http://www.sl4.org/bin/wiki.pl?action=index\"" + nil + "singbot: " + ) + + + + + ("fu" + "http://futures.wiki.taoriver.net/moin.cgi/" + "\"http://futures.wiki.taoriver.net/moin.cgi/TitleIndex?action=titleindex&mimetype=text/xml\"" + nil + "singbot: " + erbwiki-fetch-wiki-remove-tags + + ) + + + + ("ew" + "http://www.emacswiki.org/cgi-bin/wiki.pl?" + "\"http://www.emacswiki.org/cgi-bin/wiki.pl?action=index\"" + nil + "fsbot: " + ) + + + ("cw" + "http://www.emacswiki.org/cgi-bin/community/" + + "\"http://www.emacswiki.org/cgi-bin/community?action=index;raw=1\"" + nil + "fsbot: " + ) + + + + ("fw" + "http://www.etrumeus.com/ferment/" + "\"http://www.etrumeus.com/ferment/TitleIndex?action=titleindex\"" + nil + "wikibot: ") + + + ("fskdfhukdfhjkdfjk" + "http://www.gnufans.net/fsedu.pl?" + "\"http://www.gnufans.net/cgi-bin/fsedu.pl?action=index\"" + nil + "nobot: " + ) + + + ("ipfoobar" + + "http://imminst.org/pedia/PageIndex" + "\"http://new.imminst.org/pedia/\"" + nil + "singbot: " + ) + + + + + ("hwh" + "http://hurd.gnufans.org/bin/view/Hurd/" + "\"http://hurd.gnufans.org/bin/view/Hurd/WebTopicList?skin=plain\"" + erbwiki-get-fields-spaced + "hbot: " + ) + + + ("hwd" + "http://hurd.gnufans.org/bin/view/Distrib/" + "\"http://hurd.gnufans.org/bin/view/Distrib/WebTopicList?skin=plain\"" + erbwiki-get-fields-spaced + "hbot: " + ) + + + ("hwmain" + "http://hurd.gnufans.org/bin/view/Main/" + "\"http://hurd.gnufans.org/bin/view/Main/WebTopicList?skin=plain\"" + erbwiki-get-fields-spaced + "hbot: " + ) + + ("hwmach" + "http://hurd.gnufans.org/bin/view/Mach/" + "\"http://hurd.gnufans.org/bin/view/Mach/WebTopicList?skin=plain\"" + erbwiki-get-fields-spaced + "hbot: " + ) + + + ("hwmig" + "http://hurd.gnufans.org/bin/view/Mig/" + "\"http://hurd.gnufans.org/bin/view/Mig/WebTopicList?skin=plain\"" + erbwiki-get-fields-spaced + "hbot: " + ) + + + + ("hwg" + "http://hurd.gnufans.org/bin/view/GNU/" + "\"http://hurd.gnufans.org/bin/view/GNU/WebTopicList?skin=plain\"" + erbwiki-get-fields-spaced + "hbot: " + ) + + + ("hwt" + "http://hurd.gnufans.org/bin/view/TWiki/" + "\"http://hurd.gnufans.org/bin/view/TWiki/WebTopicList?skin=plain\"" + erbwiki-get-fields-spaced + "hbot: " + ) + + + + ;;("sm" + ;;"http://www.scarymath.org/math.pl?" + ;;"http://www.scarymath.org/math.pl?action=index" + ;;nil + ;;"ScBot: " + ;;) + + ("so" + "http://wiki.octave.org/wiki.pl?" + "\"http://wiki.octave.org/wiki.pl?action=index\"" + nil + "ScBot: " + ) + + ;;("sp" + ;; "http://www.scarymath.org/physics.pl?" + ;; "http://www.scarymath.org/physics.pl?action=index" + ;; nil + ;; "ScBot: " + ;;) + + + ;; towniebot + ("tbm" + "http://www.nevadamissouri.net/bin/view/Main/" + "\"http://www.nevadamissouri.net/bin/view/Main/WebTopicList?skin=plain\"" + nil + "towniebot: ") + + ;; now the big ones: + + + + ("twt" + "http://twiki.org/cgi-bin/view/TWiki/" + "\"http://twiki.org/cgi-bin/view/TWiki/WebTopicList?skin=plain\"" + nil + "TWikiBot: " + ) + + + ("twp" + "http://twiki.org/cgi-bin/view/Plugins/" + "\"http://twiki.org/cgi-bin/view/Plugins/WebTopicList?skin=plain\"" + nil + "TWikiBot: " + ) + + + ("twm" + "http://twiki.org/cgi-bin/view/Main/" + "\"http://twiki.org/cgi-bin/view/Main/WebTopicList?skin=plain\"" + nil + "TwikiBot: " + ) + + ("twc" + "http://twiki.org/cgi-bin/view/Codev/" + "\"http://twiki.org/cgi-bin/view/Codev/WebTopicList?skin=plain\"" + nil + "TWikiBot: " + ) + + ("twsupport" + "http://twiki.org/cgi-bin/view/Support/" + "\"http://twiki.org/cgi-bin/view/Support/WebTopicList?skin=plain\"" + nil + "TWikiBot: " + ) + + ("twsandbox" + "http://twiki.org/cgi-bin/view/Sandbox/" + "\"http://twiki.org/cgi-bin/view/Sandbox/WebTopicList?skin=plain\"" + nil + "TWikiBot: " + ) + + + ) + +"Page storing names of all pages. +As an example, consider this entry: + + (\"ew\" + \"http://www.emacswiki.org/cgi-bin/wiki.pl?\" + \"http://www.emacswiki.org/cgi-bin/wiki.pl?action=index\" + nil + \"fsbot: \" + nil + ) + +Most entries are obvious. ew refers to the nick name of the wiki used +when you run the function M-x erbwiki-do-it-all-one-wiki. + +Let's explain the 2 nils above. The first nil corresponds to the +default function erbwiki-get-fields. You replace it by another +function, example, erbwiki-get-fields-spaced if you want to use that +instead. +The second nil corresponds to the function used to dump the wiki, +which by default is erbwiki-fetch-wiki --- that function uses w3m. + + +" + + :group 'erbwiki) + +(defcustom erbwiki-this-wiki "NONE" + "Choose this as one of the cars of erbwiki-index-pages +and do your thing :) Should mostly be done for you by erbwiki-main +functions. " + :group 'erbwiki) + + +(defcustom erbwiki-file-name "~/pub/pub/fsbot-train/wiki-index" + "Please customize this. + +This filename, appropriately suffixed, stores the wiki's current or +last index. " + :group 'erbwiki) + + +(defcustom erbwiki-train-string + (concat + "%s%s is also at %s%s\n" + "%s%s is at %s%s\n" + ) + "Don't forget the \n at the end!" + :group 'erbwiki + ) + +(defcustom erbwiki-train-file-name "~/pub/pub/fsbot-train/wiki-train" + "Please customize this. + +With appropriate extension, this file stores the commands to be used to +train the bot. " + :group 'erbwiki) + +(defcustom erbwiki-fetch-wiki-function 'erbwiki-fetch-wiki + "This function should take a file as argument, and write into the file, +a single lisp object. The lisp object is a list of new pages in the +wiki. " + :group 'erbwiki) + + +(defcustom erbwiki-before-train-hooks nil + "Hooks to run before training.. + +Users might want to use these hooks to connect if they are not already +connected." + :group 'erbwiki) +;;;###autoload +(defun erbwiki-doit () + ;; not intetractive anymore. + (erbwiki-update) + (erbwiki-train)) + +;;;###autoload +(defun erbwiki-main-doit-all-one-wiki (wikiname &rest morewikies) + "CAUTION: nullifies idledo list. " + (interactive "sWhich Wiki? ") + (let* ((wikilists (cons wikiname morewikies)) + ctr) + (setq ctr wikilists) + (while ctr + (setq erbwiki-this-wiki (pop ctr)) + (erbwiki-update)) + (idledo-nullify) + (setq ctr wikilists) + (while ctr + (setq erbwiki-this-wiki (pop ctr)) + (erbwiki-train))) + (ignore-errors (idledo-start))) + +;;;###autoload +(defun erbwiki-main-main-ew () + (interactive) + (erbwiki-main-doit-all-one-wiki "ew")) + +;;;###autoload +(defun erbwiki-main-main-tbm () + (interactive) + (erbwiki-main-doit-all-one-wiki "tbm")) + +;;;###autoload +(defun erbwiki-main-main-tw () + (interactive) + (erbwiki-main-doit-all-one-wiki "twt" + ;;"twm" + "twc" + "twp" + "twsandbox" + "twsupport" + + )) + + +;;;###autoload +(defun erbwiki-main-main-mb () + (interactive) + (erbwiki-main-doit-all-one-wiki "mb")) + + +;;;###autoload +(defun erbwiki-main-main-hw () + (interactive) + (erbwiki-main-doit-all-one-wiki "hwh" "hwd" "hwmain" "hwmach" + "hwmig" "hwg" + "hwt" + )) + +;;;###autoload +(defun erbwiki-main-main-all-wikis () + (interactive) + (erbwiki-main-doit-all-one-wiki + "ew" "hwh" "hwd" "hwmain" "hwmach" "hwmig" "hwg" "hwt" "mb")) + + +;;;###autoload +(defun erbwiki-train () + (interactive) + (run-hooks 'erbwiki-before-train-hooks) + (erbtrain-file + (concat erbwiki-train-file-name + "-" erbwiki-this-wiki))) +;;;###autoload +(defun erbwiki-update () + ;;(interactive) + (require 'erball) + (save-window-excursion + (let + ((newfile (concat erbwiki-file-name + ".current-" + erbwiki-this-wiki + )) + (lastfile (concat erbwiki-file-name ".previous-" + erbwiki-this-wiki + )) + oldfields currentfields newfields + (train-name + (concat erbwiki-train-file-name "-" erbwiki-this-wiki)) + (wiki-string + (cadr (assoc erbwiki-this-wiki erbwiki-index-pages))) + (botname + (fifth (assoc erbwiki-this-wiki erbwiki-index-pages))) + (fetchfunction + (sixth (assoc erbwiki-this-wiki erbwiki-index-pages))) + ) + (unless botname (setq botname ", ")) + (when (file-exists-p lastfile) (mkback lastfile)) + (when (file-exists-p newfile) (copy-file newfile lastfile t)) + (funcall (or fetchfunction erbwiki-fetch-wiki-function) newfile) + (ignore-errors + (find-file lastfile) + (goto-char (point-min)) + (setq oldfields (ignore-errors (read (get-file-buffer lastfile))))) + (find-file newfile) + (goto-char (point-min)) + (setq currentfields (ignore-errors + (read (get-file-buffer newfile)))) + (setq newfields + (set-difference currentfields oldfields + :test 'equal + )) + (setq newfields (funcall erbwiki-filter-fields-function newfields)) + (kill-buffer (get-file-buffer newfile)) + (kill-buffer (get-file-buffer lastfile)) + (when (file-exists-p train-name) + (mkback train-name)) + (with-temp-file train-name + (while newfields + (insert (format erbwiki-train-string + botname + (car newfields) + wiki-string + (car + newfields) + botname + (car newfields) + wiki-string + (car newfields) + )) + (pop newfields))))) + (erbwiki-display) + ) + + +(defcustom erbwiki-filter-fields-function + 'erbwiki-filter-fields-default "") + +(defun erbwiki-filter-fields-default (fields) + ;; remove non-ascii characters + (delete-if + (lambda (arg) (string-match "[\200-\377]" (format "%s" arg))) + (copy-list fields))) + +;;;###autoload +(defun erbwiki-display () + (interactive) + (dired (file-name-directory erbwiki-train-file-name)) + (revert-buffer)) + + + +(defcustom erbwiki-dump-program "w3m -dump" + "Also try lynx -dump, curl. ") + +(defun erbwiki-fetch-wiki-lynx (filename) + (let ((erbwiki-dump-program "lynx -dump")) + (erbwiki-fetch-wiki filename))) + +(defcustom erbwiki-fetch-wiki-remove-tags-p nil "") + +(defun erbwiki-fetch-wiki-remove-tags (f) + (let ((erbwiki-fetch-wiki-remove-tags-p t)) + (erbwiki-fetch-wiki f))) + +(defun erbwiki-fetch-wiki (filename) + (require 'lines) + (let* + ((wiki-dump-name (expand-file-name "tmp-wiki-dump" + temporary-file-directory)) + (thisassoc + (assoc erbwiki-this-wiki + erbwiki-index-pages)) + (wiki-page + (cadr thisassoc)) + (index-page + (caddr thisassoc)) + (get-fields-fn (cadddr thisassoc)) + fields fieldslist) + (unless get-fields-fn + (setq get-fields-fn 'erbwiki-get-fields)) + (unless (stringp wiki-page) + (error "index page is not a stringp??")) + + (unless (stringp index-page) + (error "index page is not a stringp??")) + + ;;(setq index-page (concat wiki-page "action=index")) + ;; We will NOT add " " around the URL before calling ther + ;; shell-comnd, since the behavior of w3m -dump and lynx -dump + ;; differs in that case. Wehn the user wants a quote, she can + ;; supply it in the name of te url herself.. + + (shell-command (concat erbwiki-dump-program " " + index-page + ;;erbwiki-index-page + "" + " > " wiki-dump-name)) + (when erbwiki-fetch-wiki-remove-tags-p + (erbwiki-remove-tags-from-file wiki-dump-name)) + (setq fields (lines-get-fields-file wiki-dump-name)) + (kill-buffer (get-file-buffer wiki-dump-name)) + (setq fieldslist + (funcall get-fields-fn + fields)) + (with-temp-file filename + (insert (format "%S" fieldslist))))) + + + +(defun erbwiki-get-fields (fields) + "Given the fields as parsed by lines-get-fields, return a list of +the actual wiki fields." + (let (field) + (remove-if + (lambda (arg) (member arg (list '* + '[] + 'Search: + ))) + (erbutils-flatten + (remove-if + (lambda (field) + (or + (not (erbutils-listp-proper field)) + (not (< (length field) 3)) + (string-match "--" + (format "%s" + (first field))))) + fields))))) + + +(defun erbwiki-get-fields-spaced (fields) + "Given the fields as parsed by lines-get-fields, return a list of +the actual wiki fields." + (erbutils-flatten + (mapcar (lambda (field) + (if (equal (first field) '*) + (mapconcat + '(lambda (arg) (format "%s" arg)) + (cdr field) + "" + ))) + fields))) + + + +(defun erbwiki-remove-tags-from-file (file) + (interactive "fFile: ") + (find-file file) + (goto-char (point-min)) + (while + ;; accept any regexp greedily containing only tags with no + ;; spaces, or one starting with ?xml, in which case, allow + ;; spaces. but still be greedy. + (search-forward-regexp "<\\(?:\\?xml.*?\\|[^ \t\n]*?\\)>" nil t) + (replace-match "\n" nil t)) + (save-buffer)) + +(provide 'erbwiki) +(run-hooks 'erbwiki-after-load-hooks) + + + +;;; erbwiki.el ends here diff --git a/elisp/erbot/examples/CVS/Entries b/elisp/erbot/examples/CVS/Entries new file mode 100644 index 0000000..00ebe84 --- /dev/null +++ b/elisp/erbot/examples/CVS/Entries @@ -0,0 +1,2 @@ +/dotemacs-mybot/1.1/Sun Jul 22 23:26:03 2007// +D diff --git a/elisp/erbot/examples/CVS/Repository b/elisp/erbot/examples/CVS/Repository new file mode 100644 index 0000000..2dbfc3d --- /dev/null +++ b/elisp/erbot/examples/CVS/Repository @@ -0,0 +1 @@ +erbot/examples diff --git a/elisp/erbot/examples/CVS/Root b/elisp/erbot/examples/CVS/Root new file mode 100644 index 0000000..efd54f4 --- /dev/null +++ b/elisp/erbot/examples/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.savannah.nongnu.org:/sources/erbot diff --git a/elisp/erbot/examples/CVS/Template b/elisp/erbot/examples/CVS/Template new file mode 100644 index 0000000..e69de29 diff --git a/elisp/erbot/examples/dotemacs-mybot b/elisp/erbot/examples/dotemacs-mybot new file mode 100644 index 0000000..0b8633a --- /dev/null +++ b/elisp/erbot/examples/dotemacs-mybot @@ -0,0 +1,238 @@ +;; -*- emacs-lisp -*- + + +(setq erbot-nickserv-p t) + +(setq erc-prompt-for-nickserv-password nil) + +(setq erc-nickserv-passwords + '((freenode (("mybot" . "mypasswd"))))) + +(setq h4x0r-sometimes-replace + '(("ea" "33") ("er" "0r") ("a" "4") + ;;("b" "8") + ;;("d" "|>") + ("e" "3" "E") ;;("f" "|=") ("h" "|-|") + ;;("i" "1" "|") ;;("k" "|<" "x") + ;;("l" "1" "|_") ("m" "|\\/|") ("n" "|\\|") + ("o" "0") ;;("q" "@") + ("s" + "5" "Z" "$") + ;;("t" "+" "7") + ("ck" "x") ("u" "U") ;;("v" "\\/") + + ;("x" + ;X" "><") ("y" "j" + )) + +(add-to-list 'load-path "~/elisp") +(add-to-list 'load-path "~/elisp/erbot") +(add-to-list 'load-path "~/elisp/erbot/erbot") + +(setq erc-keywords '("mybot" "ownersname")) + +(setq fs-internal-english-weights + + '( + 30 ; doctor --- + 30 ; yow + 30 ; fortune + 2 ;; flame + )) + +(setq fs-internal-botito-mode nil) + +;; this optional step +;; helps the bot get the locations of the .el files in emacs +(let ((aa default-directory)) + (cd "/usr/share/emacs/site-lisp") + (normal-top-level-add-subdirs-to-load-path) + (cd aa)) + +(require 'cl) +;;(setq erc-port 6667) +(require 'erc) +(require 'erc-match) +(require 'erc-track) +(require 'erball) +(add-hook 'erc-mode-hook + '(lambda () (interactive) + (require 'erc-match) + (erc-match-mode 1) + ;;(erc-match-enable) + (require 'erc-button) + (erc-button-enable) + nil + )) + + +(setq bbdb-file "~/pub/data/botbbdb") + +(setq erbot-servers-channels-test + '(("irc.freenode.net" + ("#mychannel" + + "#mybot" + ) + 6667 ;; this is the port, optional, can be omitted. + ) + ("irc.gnome.org" + ( + "#mychannel2" + ) + ;; omitting the port here 6667 + ) + + )) + + + + + + +(erbot-install) + + + +(add-hook 'erc-server-376-hook + '(lambda (&rest args) + (interactive) + (erc-track-modified-channels-mode 1) + nil)) + +;;(global-unset-key "\C-cs") + +(global-set-key "\C-cj " 'erbot-join-servers) +(global-set-key [f9 f1] 'erbot-join-servers) + +(global-unset-key [f6]) +(global-set-key [f6 f6] 'erblog-show-targets) +(global-set-key [f6 f7] 'erblog-reset-targets) +(global-set-key "\C-c\C-c" 'erc-send-current-line) + + +;(global-set-key "\C-cr" 'erblog-reset-targets) + + + + + + + +;;(setq fs-limit-line-length 125) + + +;;(setq fs-limit-length + ;; 410) + +;;(setq fs-limit-lines 5 ) + +(setq bbdb-case-fold-search t) +(setq erc-auto-query t) + +;; Don't send more than 5 messages in 10 seconds. This prevents the +;; bot from getting kicked. +(setq erc-server-flood-penalty 2) +(setq erc-server-flood-margin 10) + +;; To restrict "automated" replies, change the "" below to your +;; favorite channels, example: +;;"\\(mychannel1\\|mychannel2\\)" +(setq fs-internal-query-target-regexp "") + +(setq fs-internal-google-level 60) + +(setq erbkarma-file "~/public_html/karma/karma") +(setq fs-internal-google-time 4) +(setq fs-internal-dictionary-time 4) + +(load "~/.emacs.private") + + +(setq erbkarma-tgt-check-string + "^\\(#mychannel\\)$") + +;; .emacs ends here.. + + + + + + +(setq erbot-nick "mybot") +(setq erc-user-full-name "My Bot") + +(setq erbot-servers-channels-main + '(("irc.freenode.net" + ("#mybot" + "#mychannel" + "#mychannel2" + )) + ("irc.gnome.org" + ( + "#mychannel" + + ) + + ))) + +(setq erbot-servers-channels erbot-servers-channels-main) + + +(setq fs-google-level 60) + + + +(setq erbot-servers-channels-test + '(("irc.freenode.net" + (;;"#fsbot" + "#mybot" + )) + ("irc.gnome.org" + (;;"#fsbotgnome" + ;;"#gnome" + ) + ) + + )) + +(setq bbdb-file-coding-system 'raw-text) +(require 'erball) +(erbunlisp-install) + +;; this delysid's server containing many dictionaries, if you prefer +;; the default server dict.org, just comment out this line. +(setq dictionary-server "dict.tu-graz.ac.at") + + +(fs-pf-load) +(fs-pv-load) + +(ignore-errors + (fs-user-init)) + +(require 'idledo) +(idledo-add-periodic-action-crude + '(fs-pv-save)) + +(add-hook 'kill-emacs-hook + 'fs-pv-save) + +;; consider uncommenting these +;;(add-to-list 'erblisp-allowed-words '&optional) +;;(add-to-list 'erblisp-allowed-words '&rest) + + +;;uncomment this only for a channel full of emacs hackers... see C-h v +;;(setq fs-internal-parse-error-p t) + +(setq units-dat-file "/usr/share/misc/units.dat") + +(add-to-list 'load-path "~/public_html/data") + + + + +;; .emacs ends here.. + + -- cgit v1.2.2