From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Dan Nicolaescu Newsgroups: gmane.emacs.devel Subject: Re: vc-*-root finctions Date: Wed, 20 Feb 2008 10:50:41 -0800 Message-ID: <200802201850.m1KIofIk000198@sallyv1.ics.uci.edu> References: <87skzn3mq9.fsf@ambire.localdomain> <87mypvxzd2.fsf@ambire.localdomain> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1203533568 22833 80.91.229.12 (20 Feb 2008 18:52:48 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 20 Feb 2008 18:52:48 +0000 (UTC) Cc: Stefan Monnier , emacs-devel@gnu.org To: Thien-Thi Nguyen Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Feb 20 19:53:11 2008 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1JRu42-0005Jz-Sk for ged-emacs-devel@m.gmane.org; Wed, 20 Feb 2008 19:53:07 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JRu3Y-0007Jn-0f for ged-emacs-devel@m.gmane.org; Wed, 20 Feb 2008 13:52:36 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JRu3M-000790-Pf for emacs-devel@gnu.org; Wed, 20 Feb 2008 13:52:24 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JRu3L-00076v-FP for emacs-devel@gnu.org; Wed, 20 Feb 2008 13:52:24 -0500 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JRu3L-00076k-6g for emacs-devel@gnu.org; Wed, 20 Feb 2008 13:52:23 -0500 Original-Received: from sallyv1.ics.uci.edu ([128.195.1.109]) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_3DES_EDE_CBC_SHA1:24) (Exim 4.60) (envelope-from ) id 1JRu3K-0006pu-Hs for emacs-devel@gnu.org; Wed, 20 Feb 2008 13:52:22 -0500 X-ICS-MailScanner-Watermark: 1204138244.01848@a126AaCgAm8AsSDOIv2acg Original-Received: from mothra.ics.uci.edu (mothra.ics.uci.edu [128.195.6.93]) by sallyv1.ics.uci.edu (8.13.7+Sun/8.13.7) with ESMTP id m1KIofIk000198; Wed, 20 Feb 2008 10:50:42 -0800 (PST) In-Reply-To: <87mypvxzd2.fsf@ambire.localdomain> (Thien-Thi Nguyen's message of "Wed, 20 Feb 2008 19:21:45 +0100") Original-Lines: 240 X-ICS-MailScanner: Found to be clean X-ICS-MailScanner-SpamCheck: not spam, SpamAssassin (score=0.36, required 5, autolearn=disabled, ALL_TRUSTED -1.44, FM_MULTI_ODD2 1.10, FM_MULTI_ODD3 0.70) X-ICS-MailScanner-From: dann@mothra.ics.uci.edu X-detected-kernel: by monty-python.gnu.org: Solaris 10 (beta) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:89725 Archived-At: Thien-Thi Nguyen writes: > () Stefan Monnier > Please see the `vc-status-mode' docstring in the updated code below. > This time i include a full patch for anyone interested in trying > it out. In terms of user experience, this means that doing: > M-x vc-status RET ~/build/MISC/ferm/examples RET > > shows a buffer where the first line reads: > Directory: ~/build/MISC/ferm/examples/ > > and "ferm" (the project's "root" directory) is a button, which > means (for me) underlined and clickable, whose action is to do > `(vc-status "~/build/MISC/ferm")'. > > If this explanation makes sense to you and the docstring doesn't, > could you suggest another wording? Allowing the user to look at the status from the root of the VC tree seems like a good idea. But is this the right UI for it? It does not seem very intuitive to me... > --- 167,186 ---- > ;; in older versions this method was not required to recurse into > ;; subdirectories.) > ;; > ! ;; - dir-status (&optional kickp) > ;; > ;; This function is used by vc-status, a replacement for vc-dired. > ;; vc-status is still under development, and is NOT feature > ;; complete. As such, the requirements for this function might > ! ;; change. This is a replacement for dir-state. > ! ;; > ! ;; Produce RESULT: a list of conses of the form (file . vc-state) > ! ;; for the files in DIR. This function is called twice, the first ^^^^^^^^^^^^^^^^ Can you please explain why? > ! ;; time with KICKP t, the second time, with KICKP nil. In both calls, What's the meaning of KICKP ? > ! ;; the current buffer is a scratch buffer with `default-directory' > ! ;; set appropriately. If the backend workings are asynchronous, it > ! ;; must use the current buffer as its process buffer. The return > ! ;; value of the second call is RESULT. Why bother making the backend synchronous? The current API can be used by a synchronous backend too. It just needs to call the UPDATE-FUNCTION when done processing. - (defun vc-status-headers (backend dir) - (concat - (format "VC backend : %s\n" backend) - "Repository : The repository goes here\n" - (format "Working dir: %s\n" dir))) - Why remove this? > ;;;###autoload > (defun vc-status (dir) > ! "Show the VC status for DIR in its own buffer. > ! Reuse an existing buffer if possible, otherwise create a new one > ! and place it in `vc-status-mode'. Lastly, run `vc-status-refresh'." > (interactive "DVC status for directory: ") > ! (setq dir (file-name-as-directory dir)) > ! (let ((ls (buffer-list)) > ! buf) > ! (while (and ls (not buf)) > ! (with-current-buffer (car ls) > ! (when (and vc-status (string= dir default-directory)) > ! (setq buf (car ls))) > ! (setq ls (cdr ls)))) > ! (unless buf > ! (set-buffer (setq buf (get-buffer-create > ! (generate-new-buffer-name > ! (file-name-nondirectory > ! (directory-file-name dir)))))) > ! (setq default-directory dir) > ! (vc-status-mode)) > ! (switch-to-buffer buf)) > ! (vc-status-refresh)) > > (defvar vc-status-mode-map > (let ((map (make-keymap))) > *************** > *** 2777,2818 **** > > (defun vc-status-mode () > "Major mode for VC status. > \\{vc-status-mode-map}" > ! (setq mode-name "*VC Status*") > ! (setq major-mode 'vc-status-mode) > ! (setq buffer-read-only t) > ! (use-local-map vc-status-mode-map) > ! (let ((buffer-read-only nil) > ! (backend (vc-responsible-backend default-directory)) > ! entries) > ! (erase-buffer) > (set (make-local-variable 'vc-status) > ! (ewoc-create #'vc-status-printer > ! (vc-status-headers backend default-directory))) > ! (vc-status-refresh))) > > (put 'vc-status-mode 'mode-class 'special) > > - (defun vc-update-vc-status-buffer (entries buffer) > - (with-current-buffer buffer > - (dolist (entry entries) > - (ewoc-enter-last vc-status > - (vc-status-create-fileinfo (cdr entry) (car entry)))) > - (ewoc-goto-node vc-status (ewoc-nth vc-status 0)))) > - > (defun vc-status-refresh () > ! "Refresh the contents of the VC status buffer." > (interactive) > ! ;; This is not very efficient; ewoc could use a new function here. > ! (ewoc-filter vc-status (lambda (node) nil)) > ! (let ((backend (vc-responsible-backend default-directory))) > ! ;; Call the dir-status backend function. dir-status is supposed to > ! ;; be asynchronous. It should compute the results and call the > ! ;; function passed as a an arg to update the vc-status buffer with > ! ;; the results. > ! (vc-call-backend > ! backend 'dir-status default-directory > ! #'vc-update-vc-status-buffer (current-buffer)))) > > (defun vc-status-next-line (arg) > "Go to the next line. > --- 2790,2887 ---- > > (defun vc-status-mode () > "Major mode for VC status. > + Prepare the buffer to begin with the lines: > + > + Directory: DEFAULT-DIRECTORY > + Updated: YYYY-MM-DD HH:MM:SS > + > + If the `default-directory' is under the project's \"root\" > + directory, make its root component a button whose action is > + to run command `vc-status' there. > + > + Keys do not self-insert; instead they do different things: > \\{vc-status-mode-map}" > ! (buffer-disable-undo) > ! (erase-buffer) > ! (let* ((backend (vc-responsible-backend default-directory)) > ! (find-root (vc-find-backend-function backend 'root)) > ! (root (if find-root > ! (funcall find-root default-directory) > ! default-directory))) > ! (setq major-mode 'vc-status-mode) > ! (setq mode-name (format "VC-%s Status" backend)) > ! (insert "Directory: ") > ! (if (or (not root) (string= root default-directory)) > ! (insert root) > ! (let* ((root-fn (directory-file-name root)) > ! (parent (file-name-directory root-fn)) > ! (leaf (file-name-nondirectory root-fn))) > ! (insert parent) > ! ;; As of 2007-08-21, loadup.el includes button, so this > ! ;; check is just future-proofing; not strictly necessary. > ! (if (featurep 'button) > ! (insert-text-button > ! leaf > ! 'root root > ! 'action (lambda (button) > ! (vc-status (button-get button 'root))) > ! 'follow-link t) > ! (insert leaf)) > ! (insert (substring default-directory (1- (length root)))))) > ! (insert "\n") > (set (make-local-variable 'vc-status) > ! (ewoc-create #'vc-status-printer > ! (format-time-string " Updated: %F %T\n"))) > ! (use-local-map vc-status-mode-map) > ! (setq buffer-read-only t))) > > (put 'vc-status-mode 'mode-class 'special) > > (defun vc-status-refresh () > ! "Refresh the contents of the VC Status buffer." > (interactive) > ! (unless vc-status > ! (error "Not in a VC Status buffer")) > ! (ewoc-filter vc-status 'ignore) > ! (let* ((backend (vc-responsible-backend default-directory)) > ! (get-status (cond ((vc-find-backend-function backend 'dir-status)) > ! (t (kill-buffer nil) > ! (error "No vc-status support for %s" > ! backend)))) > ! (here (current-buffer)) > ! (scratch (get-buffer-create (format " vc status: %s" > ! default-directory))) > ! notice) > ! ;; Call the backend function in two-phase style. First, kick... > ! (with-current-buffer scratch > ! (erase-buffer) > ! (funcall get-status t)) > ! ;; Clue in the user if things are working asynchronously. > ! (when (setq notice (buffer-local-value 'mode-line-process scratch)) > ! (setq mode-line-process notice) > ! (ewoc-set-hf vc-status > ! (format " Updated: %s -- %s working...\n" Is this the time when vc-status was last run? That might be confusing for the user, he might think that "Updated:" means the last time he updated the his sources from the VC system. > ! (format-time-string "%F %T") > ! backend) > ! "")) > ! (with-current-buffer scratch > ! (vc-exec-after > ! ;; ... then collect. > ! `(let ((entries (,get-status))) > ! (when (buffer-live-p ,here) > ! (with-current-buffer ,here > ! (dolist (entry entries) > ! (ewoc-enter-last vc-status (vc-status-create-fileinfo > ! (cdr entry) (car entry)))) > ! (let ((first (ewoc-nth vc-status 0))) > ! (when first > ! (ewoc-goto-node vc-status first) > ! (vc-status-move-to-goal-column)) > ! (ewoc-set-hf vc-status > ! (format-time-string " Updated: %F %T\n") > ! (if first "" "(no entries)")) > ! (setq mode-line-process nil)))) > ! (kill-buffer nil)))))) This function is much more complicated now, it's not obvious why. Can you please explain?