[Top][All Lists]

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

Re: Idea for determining what users use

From: Thien-Thi Nguyen
Subject: Re: Idea for determining what users use
Date: 27 May 2003 10:39:23 -0400

Richard Stallman <address@hidden> writes:

   Imagine a function called note-feature-used.
   You call it like this:  (note-feature-used 'foo "Foo").
   The first time you call it, it sends mail to
   address@hidden with subject Foo,
   asking you for permission to send it,
   and it records (setq foo t) in your .emacs file.
   If you call it again, it does nothing.

knowing how ego-driven programmers are, i fear this would lead to lots
of spam as every little (sub-)feature is instrumented so.  perhaps this
can be ameliorated somewhat by batching up the samples into one var, say
`*$USER-features-used*' and providing `M-x report-used-features'.  this
allows any externalizable object to be reported (not just symbols), and
sidesteps the possibility of clobbering useful variables due to the ever
odious single-namespace problem.  we use $USER because a single ~/.emacs
can be used by many people.

some aspects of this two-phase approach are demonstrated by the poll at:


the relevant elisp is below for those w/o www access.

   We could put these calls into various files and functions 
   in order to find out (after the next release) whether anyone uses them.

IMHO, it is better not to tie such a poll to any specific release, since
a release is just a snapshot of various disparate albeit concurrent
activities.  release info could be included in `*$USER-features-used*',
however (along w/ extra commentary, etc).

another thing to keep in mind: at some installations there is a local
emacs guru who sets up the site-lisp dir, etc.  if a two-phase approach
is taken, it should allow the sampled data to be vetted through this
person as they usually have additional insight into the local emacs
situation apart from the end user.  in fact, whatever mechanism we
settle on could be a good tool for these people as well as for emacs
programmers w/ savannah write privs.


;;; minor-mode-survey.el
;;; author: address@hidden
;;; created: 2001/03/09 03:28:44
;;; modified: 2001/03/16 02:33:06 -- ignore errors in `buffer-modes-usage'
;;; public domain

;; these were mailed to address@hidden

(defun buffer-modes-usage (buffer)
  (with-current-buffer buffer
    (cons major-mode
          (let ((acc nil) (mma minor-mode-alist))
            (while mma                  ; avoid cl :-P
                (let ((minor-mode (caar mma)))
                  ;; use `describe-mode' inclusion method -- see help.el
                  (when (and (symbol-value minor-mode)
                             (fboundp minor-mode))
                    (setq acc (cons minor-mode acc)))))
              (setq mma (cdr mma)))

(defun compose-mode-usage-mail ()
  (let ((forms (mapcar 'buffer-modes-usage (buffer-list)))
        (mail-self-blind nil))
    (compose-mail "address@hidden" "minor mode survey response")
    (goto-char (point-max))
    (let ((standard-output (current-buffer)))
      (mapcar '(lambda (form)
                 (unless (= 1 (length form)) ; ignorance is bliss
                   (print form)))
  (setq fill-prefix ";;; ")
  (insert "\n;;; additional comments (fill-prefix set to \""
          "\")\n;;; "))

;; new stuff

(require 'cl)                           ; use the source luke!

(defun sort-freq-hash (hash)
  (let (unsorted)
    (maphash (lambda (x count) (push (cons count x) unsorted)) hash)
    (sort unsorted (lambda (a b) (> (car a) (car b))))))

(defun insert-compressed-freq-list (ls)
  (let ((last-seen 0))
    (dolist (x ls)
      (insert (if (= (car x) last-seen)
                  (format " %s" (cdr x))
                (setq last-seen (car x))
                (format "\n- %d %s" (car x) (cdr x))))))
  (insert "\n\n"))

(defun analyze-mode-usage-response (data)
  (insert (format "%d buffers scanned" (length data)))
  (dolist (x data) (setcdr x (remove-duplicates (sort (cdr x) 'string<))))
  (setq data (delete-duplicates data :test 'equal))
  (insert (format " (%d w/ unique mode signatures)\n" (length data)))
  (dolist (x data) (insert (format "- %s\n" x)))
  (insert "\n")
  ;; major mode summary
  (let ((majs (make-hash-table)))
    (dolist (x data) (incf (gethash (car x) majs 0)))
    (insert (format "%d unique major modes, sorted by instances in unique sig"
                    (hash-table-count majs)))
    (insert-compressed-freq-list (sort-freq-hash majs)))
  ;; minor mode
  (let ((mins (make-hash-table)) sorted)
    ;; summary
    (dolist (x (apply 'append (mapcar 'cdr data))) (incf (gethash x mins 0)))
    (insert (format "%d unique minor modes, sorted by instances in unique sig"
                    (hash-table-count mins)))
    (setq sorted (sort-freq-hash mins))
    (insert-compressed-freq-list sorted)
    ;; details: clumps and bros
            "- ...\n\n")
    (dolist (m (mapcar 'cdr sorted))
      (insert (format "%s:" m))
      (let* ((mdata (mapcar 'cdr data))
             (hood (remove-if-not (lambda (sig) (memq m (cdr sig))) mdata))
             (clumps (make-hash-table))
             (bros (make-hash-table)))
        (dolist (h hood) (incf (gethash (1- (length h)) clumps 0)))
        (dolist (b (remove m (apply 'append hood))) (incf (gethash b bros 0)))
        (dolist (x (sort (sort-freq-hash clumps)
                         (lambda (a b) (< (cdr a) (cdr b)))))
          (insert (format " %d:%d" (cdr x) (car x))))
        (insert-compressed-freq-list (sort-freq-hash bros))))))

(defun summarize-mode-usage-responses (file)
  (interactive "fMail file: ")
  (find-file file)
  (unless (eq 'rmail-mode major-mode)
    (error "wrong file, dude"))
  (let (data comments)
    (do ((i 1 (1+ i)))
        ((> i rmail-total-messages))
      (rmail-show-message i)
      (goto-char (point-min))
      (search-forward "\n\n")
      ;; pass twice to handle interspersed comments
      (let ((beg (point)))
        (goto-char beg)
        (ignore-errors (while t (push (read (current-buffer)) data)))
        (goto-char beg)
        (while (re-search-forward "^;;;\\(.+\n\\)" (point-max) t)
          (push (match-string 1) comments)))
      (push "----------------------------\n" comments))
    (kill-buffer (current-buffer))
    (switch-to-buffer "*Mode Usage Response Summary*")
    (analyze-mode-usage-response data)
    (insert "\n")
    (dolist (comment (reverse comments)) (insert comment))
    ;; gratuitous prettiness
    (while (re-search-backward "^---+\n\\s-*\n" (point-min) t)
      (replace-match ""))
    (re-search-backward "^---+\n" (point-min) t)
    (while (search-backward "-mode" (point-min) 1)
      (replace-match ""))))

;;; minor-mode-survey.el ends here

reply via email to

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