From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Lennart Borgman Newsgroups: gmane.emacs.devel Subject: File name completion in *Shell* on w32 Date: Wed, 27 Dec 2006 01:16:42 +0100 Message-ID: <4591BB6A.1070402@student.lu.se> NNTP-Posting-Host: dough.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------060808000904070800010906" X-Trace: sea.gmane.org 1167228482 20726 80.91.229.10 (27 Dec 2006 14:08:02 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Wed, 27 Dec 2006 14:08:02 +0000 (UTC) Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Dec 27 15:08:01 2006 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by dough.gmane.org with esmtp (Exim 4.50) id 1GzZRn-00069f-I7 for ged-emacs-devel@m.gmane.org; Wed, 27 Dec 2006 15:08:00 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1GzZRn-000399-01 for ged-emacs-devel@m.gmane.org; Wed, 27 Dec 2006 09:07:59 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1GzY1B-0000ZV-C7 for emacs-devel@gnu.org; Wed, 27 Dec 2006 07:36:25 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1GzY1A-0000YR-2d for emacs-devel@gnu.org; Wed, 27 Dec 2006 07:36:24 -0500 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1GzY19-0000Y9-Ex for emacs-devel@gnu.org; Wed, 27 Dec 2006 07:36:23 -0500 Original-Received: from [80.76.149.212] (helo=ch-smtp01.sth.basefarm.net) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA:32) (Exim 4.52) id 1GzY18-0004Pt-Oe for emacs-devel@gnu.org; Wed, 27 Dec 2006 07:36:23 -0500 Original-Received: from c83-254-145-24.bredband.comhem.se ([83.254.145.24]:63423 helo=[127.0.0.1]) by ch-smtp01.sth.basefarm.net with esmtp (Exim 4.63) (envelope-from ) id 1GzMTH-00055D-3o for emacs-devel@gnu.org; Wed, 27 Dec 2006 01:16:40 +0100 User-Agent: Thunderbird 1.5.0.9 (Windows/20061207) Original-To: Emacs Devel X-Antivirus: avast! (VPS 0662-2, 2006-12-26), Outbound message X-Antivirus-Status: Clean X-Scan-Result: No virus found in message 1GzMTH-00055D-3o. X-Scan-Signature: ch-smtp01.sth.basefarm.net 1GzMTH-00055D-3o 46c751566f34b3e59fd61b228c61abea X-Mailman-Approved-At: Wed, 27 Dec 2006 09:07:31 -0500 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:64346 Archived-At: This is a multi-part message in MIME format. --------------060808000904070800010906 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit File name completion in a *Shell* on w32 using cmd.exe for the shell process currently does not work. The attached file contains code that can be used to fix this bug. It does not use the Emacs completion style but instead the completion style used by cmd.exe. Maybe it should do both? I proposed before to sync the directory of the shell process with default-directory. This code also adds such a sync. --------------060808000904070800010906 Content-Type: text/plain; name="w32compl-temp.el" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="w32compl-temp.el" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun w32-dynamic-complete-filename-like-cmd-fw () "Tab style file name completion like cmd.exe. Tries to do Tab style file name completion like cmd.exe on w32 does it. See also `w32-dynamic-complete-filename-like-cmd-bw'." (interactive) (w32-dynamic-complete-filename-like-cmd t)) (defun w32-dynamic-complete-filename-like-cmd-bw () "Shift-Tab style file name completion like cmd.exe. Tries to do Shift-Tab style file name completion like cmd.exe on w32 does it. See also `w32-dynamic-complete-filename-like-cmd-fw'." (interactive) (w32-dynamic-complete-filename-like-cmd nil)) (defconst w32-dynamic-complete-state nil) (defcustom w32-dynamic-complete-sync-dirs t "Synchronize process directory and `default-directory' if non-nil. If non-nil then `w32-dynamic-complete-filename-like-cmd-fw' (and dito -bw) will send an invisible \"cd\" to the process running cmd.exe to find out what directory the cmd.exe process uses. `default-directory' is then set to this directory." :type 'boolean :group 'w32) (defcustom w32-dynamic-complete-only-dirs '("cd" "pushd") "Commands for which only directories should be shown. When doing file name completion the commands in this list will only get directory names. This is used in `w32-dynamic-complete-filename-like-cmd-fw' (and dito -bw)." :type '(repeat string) :group 'w32) (defun w32-dynamic-complete-filename-like-cmd (forward) (let* ((proc (get-buffer-process (current-buffer))) (pmark (process-mark proc)) (point (point)) (cmdstr (buffer-substring-no-properties pmark point)) (argv (w32-get-argv cmdstr)) (first-arg (car argv)) (last-arg (car (reverse argv))) (only-dirs (member (car first-arg) w32-dynamic-complete-only-dirs)) (prev-cmdstr (nth 0 w32-dynamic-complete-state)) (prev-completion (nth 1 w32-dynamic-complete-state)) (prev-begin-filename (nth 2 w32-dynamic-complete-state)) (in-completion (string= cmdstr prev-cmdstr)) (begin-filename prev-begin-filename) new-completion new-full-completion completion-dir completion-dir-given dir-files pick-next beginning-last ) ;; Initialize (setq w32-dynamic-complete-state nil) (when last-arg (setq completion-dir-given (file-name-directory (car last-arg)))) (if completion-dir-given (setq completion-dir-given (file-name-as-directory completion-dir-given)) (setq completion-dir-given "")) ;; Not continuing completion set up for completion (unless in-completion (setq prev-completion nil) (if last-arg (setq begin-filename (concat "^" (file-name-nondirectory (car last-arg)))) (setq begin-filename nil)) ;; Sync process directory and default-directory (when w32-dynamic-complete-sync-dirs (let ((old-out-filter (process-filter proc))) (condition-case err (progn (set-process-filter proc (lambda(proc str) (let ((lstr (split-string str "[\r\n]+"))) (setq default-directory (file-name-as-directory (nth 1 lstr)))))) (process-send-string proc "cd\n") (accept-process-output proc)) (error (message "%s" (error-message-string err)))) (set-process-filter proc old-out-filter)))) ;; Find completion (setq completion-dir (expand-file-name completion-dir-given)) (setq dir-files (directory-files completion-dir nil begin-filename)) (unless forward (setq dir-files (reverse dir-files))) (dolist (f dir-files) (when (and (not (member f '("." ".."))) (or (not only-dirs) (file-directory-p (expand-file-name f completion-dir)))) (unless new-completion (setq new-completion f)) (if (string= f prev-completion) (setq pick-next t) (when pick-next (setq pick-next nil) (setq new-completion f))))) (setq new-full-completion (convert-standard-filename (concat completion-dir-given new-completion))) ;; Replase last argument (setq beginning-last (nth 1 last-arg)) (unless beginning-last (setq beginning-last 0)) (goto-char (+ pmark beginning-last)) (unless (eolp) (kill-line)) ;; The code below should probably use shell-quote-argument, but ;; because of trouble with this function I am using a more ;; w32 specific quoting here at the moment. (if (not (memq ?\ (append new-full-completion nil))) (insert new-full-completion) (insert ?\") (insert new-full-completion) (insert ?\")) ;; Save completion state ;; ;; return non-nil to show completion has been done! (setq w32-dynamic-complete-state (list (buffer-substring-no-properties pmark (point)) new-completion begin-filename)))) (defun w32-get-argv(cmdline) "Split CMDLINE into args. The splitting is done using the syntax used on MS Windows. Return a list where each element is a list in the form \(arg arg-begin arg-end) where ARG is the argument stripped from any \". ARG-BEGIN and ARG-END are the beginning and end of the argument in cmdline. If CMDLINE ends with a space or is \"\" a list consisting of \(\"\" LEN nil) is added. LEN is the length of CMDLINE." (let ((lcmd (append cmdline nil)) (len (length cmdline)) argv state arg arg-begin arg-end c ) (while lcmd (setq c (car lcmd)) (setq lcmd (cdr lcmd)) (cond ( (not state) (when arg (error "arg not nil")) (cond ( (= c ?\ )) ( (= c ?\") (setq arg-begin (- len 1 (length lcmd))) (setq state 'state-qarg)) ( t (setq arg-begin (- len 1 (length lcmd))) (setq state 'state-arg) (setq arg (cons c arg))))) ( (eq state 'state-arg) (cond ( (= c ?\ ) (setq state nil) (setq arg-end (- len 1 (length lcmd))) (setq argv (cons (list (concat (nreverse arg)) arg-begin arg-end) argv)) (setq arg nil)) ( (= c ?\") (setq state 'state-arg-q)) ( t (setq arg (cons c arg))))) ( (eq state 'state-arg-q) (cond ( (= c ?\") (setq state 'state-arg)) ( t (setq arg (cons c arg))))) ( (eq state 'state-qarg) (cond ( (= c ?\") (setq state 'state-qarg-q)) ( t (setq arg (cons c arg))))) ( (eq state 'state-qarg-q) (cond ( (= c ?\ ) (setq state nil) (setq arg-end (- len 1 (length lcmd))) (setq argv (cons (list (concat (nreverse arg)) arg-begin arg-end) argv)) (setq arg nil)) ( (= c ?\") (setq arg (cons c arg)) (setq state 'state-qarg)) ( t (setq arg (cons c arg))))) ( t (error "unknown state=%s" state)) )) (if arg (progn (setq arg-end (- len 0 (length lcmd))) (setq argv (cons (list (concat (nreverse arg)) arg-begin arg-end) argv))) (when (or (not c) (= c ?\ )) (setq argv (cons (list "" (length cmdstr) nil) argv)))) (reverse argv))) ;; For testing: (when nil (global-set-key [f9] 'w32-dynamic-complete-filename-like-cmd-fw) (global-set-key [(shift f9)] 'w32-dynamic-complete-filename-like-cmd-bw) ) --------------060808000904070800010906 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-devel mailing list Emacs-devel@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-devel --------------060808000904070800010906--