summaryrefslogtreecommitdiff
path: root/elisp/erbot/erbc.el
diff options
context:
space:
mode:
Diffstat (limited to 'elisp/erbot/erbc.el')
-rw-r--r--elisp/erbot/erbc.el5141
1 files changed, 5141 insertions, 0 deletions
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 <deego@gnufans.org>
+;; 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 \", <english-message>\" 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..."
+ "<LOUD ERROR MSG >.."
+ "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 <nick> 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))
+ "..<more>")))
+ (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)) "...<more>")
+ 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
+ ) " <break>")
+ 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 <key>)"))
+ (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 "<title>" nil t))
+ (end (search-forward "</title>" 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 \"<home>\"), (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
+