From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Thien-Thi Nguyen Newsgroups: gmane.emacs.devel Subject: Re: Idea for determining what users use Date: 27 May 2003 10:39:23 -0400 Sender: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Message-ID: References: NNTP-Posting-Host: main.gmane.org X-Trace: main.gmane.org 1054046816 14435 80.91.224.249 (27 May 2003 14:46:56 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Tue, 27 May 2003 14:46:56 +0000 (UTC) Cc: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Tue May 27 16:46:54 2003 Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 19Kfhg-0003dY-00 for ; Tue, 27 May 2003 16:45:28 +0200 Original-Received: from monty-python.gnu.org ([199.232.76.173]) by quimby.gnus.org with esmtp (Exim 3.12 #1 (Debian)) id 19KfvP-0001kc-00 for ; Tue, 27 May 2003 16:59:39 +0200 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.20) id 19Kfic-0005ti-Bo for emacs-devel@quimby.gnus.org; Tue, 27 May 2003 10:46:26 -0400 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.20) id 19Kfhp-0005nq-AV for emacs-devel@gnu.org; Tue, 27 May 2003 10:45:37 -0400 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.20) id 19KfcN-0004eJ-5f for emacs-devel@gnu.org; Tue, 27 May 2003 10:40:00 -0400 Original-Received: from colo.agora-net.com ([207.245.84.69]) by monty-python.gnu.org with esmtp (Exim 4.20) id 19Kfbp-0004PN-JJ; Tue, 27 May 2003 10:39:25 -0400 Original-Received: from ttn by colo.agora-net.com with local (Exim 3.34 #1) id 19Kfbn-0005S6-00; Tue, 27 May 2003 10:39:23 -0400 Original-To: rms@gnu.org In-Reply-To: Richard Stallman's message of "Tue, 27 May 2003 08:45:20 -0400" Original-Lines: 173 X-Mailer: Gnus v5.7/Emacs 20.7 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1b5 Precedence: list List-Id: Emacs development discussions. List-Help: List-Post: List-Subscribe: , List-Archive: List-Unsubscribe: , Errors-To: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:14324 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:14324 Richard Stallman 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 emacs-features-used@gnu.org 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: http://www.glug.org/people/ttn/software/minor-mode-survey/ 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. thi ______________________________________________ ;;; minor-mode-survey.el ;;; author: ttn@gnu.org ;;; 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 gnu-emacs-help@gnu.org (defun buffer-modes-usage (buffer) (with-current-buffer buffer (cons major-mode (let ((acc nil) (mma minor-mode-alist)) (while mma ; avoid cl :-P (ignore-errors (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))) acc)))) (defun compose-mode-usage-mail () (interactive) (let ((forms (mapcar 'buffer-modes-usage (buffer-list))) (mail-self-blind nil)) (compose-mail "ttn@gnu.org" "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))) forms))) (setq fill-prefix ";;; ") (insert "\n;;; additional comments (fill-prefix set to \"" fill-prefix "\")\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 (insert "FOO-MINOR-MODE: CONCURRENT:COUNT CONCURRENT:COUNT ...\n" "- MOST CONCURRENT MINOR MODE\n" "- NEXT MOST CONCURRENT MINOR MODE\n" "- ...\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*") (erase-buffer) (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