[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

snitch.el 1.0

From: Thien-Thi Nguyen
Subject: snitch.el 1.0
Date: Sun, 01 Jun 2003 20:21:35 -0400

greetings earthlings,

please find below snitch.el 1.0.
feedback and patches welcome.


;;; snitch.el --- record runtime info to send to the busybody

;; Copyright (C) 2003 Thien-Thi Nguyen
;; This file is part of ttn's personal elisp library, released under GNU
;; GPL with ABSOLUTELY NO WARRANTY.  See the file COPYING for details.

;;; Version: 1.0
;;; Keywords: emacs-lisp, convenience
;;; X-Author-Seeking-Band: to-jam, to-gig, to-write-songs, to-learn-italian

;;; Commentary:

;; * Overview
;;   This file provides functions to save information collected during
;;   an emacs session and, at a later time, to email that information to
;;   some busybody on the Net.  Information collected can range from
;;   simple (whether or not some feature/function is used) to complex
;;   (filtered aggregate data).  See `snitch-stash', `snitch-report',
;;   and `global-snitch-mode' (both var and func).
;; * Why you should think very carefully about using this code
;;   It is fair to call the snitch facility "spyware"; the name should
;;   in fact alert you that something weird is afoot.  To be precise,
;;   however, no spying is done unless you, the elisp programmer, use
;;   snitch functions in your code.  When you take that step, you have
;;   become an author of spyware.  Please be careful and take pains to
;;   inform your users in turn of what they're getting into, lest your
;;   (possibly) well-intentioned information collection efforts be
;;   misinterpreted to the detriment of you and your program.
;; * Restoring balance
;;   Consider yourself invited to write an anti-snitch.el which would
;;   search code (loaded or not) for snitch functions, rewrite programs
;;   omitting the potential for snitching, etc.
;; * Thanks
;;   This code arose from discussion on the emacs-devel list, where
;;   many interesting points regarding how to find out what users
;;   actually use were brought up in mid 2003.  Thanks go to the
;;   discussion participants.
;; * TODO
;;   - in snitch-report, handle key lookup failure
;;   - add support for kill-emacs-hook
;;   - add persistence (write to ~/.emacs or ~/.emacs.snitch)
;;   - figure out if this should go into emacs, and if so, where?

;;; Code:

(defvar global-snitch-mode nil
  "*Enable `snitch-stash' if non-nil.")

(defun snitch-var ()
  "Return a variable name (symbol) where snitch stores information."
  (let ((rv (intern (concat (getenv "USER") "-snitch-data"))))
    (unless (boundp rv)
      (set rv nil))

(defun snitch-stash (key func)
  "Look up KEY in the assoc list and set/replace the value there.
If FUNC is a function, pass the old value to it and store the new value.
Otherwise, store FUNC there.  Actually, all of these things are done
only if variable `global-snitch-mode' is non-nil."
  (when global-snitch-mode
    (let* ((stash (symbol-value (snitch-var)))
           (so-far (assoc key stash))
           (new (if (functionp func)
                    (funcall func (cdr so-far))
      (if so-far
          (setcdr so-far new)
        (set (snitch-var)
             (cons (cons key new) stash)))

(defun snitch-forget (key)
  "Remove KEY and its value from the assoc list maintained by snitch."
  (interactive "xKey: ")
  (let* ((stash (symbol-value (snitch-var)))
         (so-far (assoc key stash)))
    (when so-far
      (put (snitch-var) (delete so-far stash)))))

(defun snitch-forget-everything ()
  "Clear the variable named by `snitch-var' and unbind it."
  (let ((var (snitch-var)))
    (set var nil)
    (makunbound var)
    (message "Cleared variable: %s" var)))

(defun global-snitch-mode ()
  "Toggle ability of `snitch-stash' to record information."
  (setq global-snitch-mode (not global-snitch-mode))
  (message "Global snitch mode now %s"
           (if global-snitch-mode
               "ON (data collection enabled)"
             "OFF (data collection disabled)")))

(defun snitch-report (busybody subject selection &optional zonkp)
  "Set up a mail buffer to BUSYBODY with SUBJECT composed of SELECTION.
SELECTION is either a list of keys to be looked up in the asooc list
maintained by snitch, or a key predicate in which case a non-nil value
means to select the key and its associated data.  Optional arg ZONKP
non-nil means to delete the data from the assoc list after composing
the mail buffer.

When `snitch-report' returns the cursor is left at the beginning
of the mail body (immediately below \"text follows this line\").
To actually send the mail, the user must type `C-c C-c'."
  (compose-mail busybody subject)
  (goto-char (point-max))
  (let* ((so-far (symbol-value (snitch-var)))
         (all (if (functionp selection)
                  (let ((all nil) (ls so-far))
                    (while ls
                      (when (funcall selection (caar ls))
                        (setq all (cons (car ls) all)))
                      (setq ls (cdr ls)))
                (mapcar (lambda (key)
                          (assoc key so-far))
    (when zonkp
      (add-to-list 'mail-send-actions
                   (list '(lambda (v all)
                            (let ((so-far (symbol-value v)))
                              (while all
                                (set v (delete (car all) so-far))
                                (setq all (cdr all)))))
      (while all
        (insert "\n\n;; key\n" (format "%S" (caar all))
                "\n;; value\n" (format "%S" (cdar all)))
        (setq all (cdr all))))))

;;; snitch.el ends here

reply via email to

[Prev in Thread] Current Thread [Next in Thread]