Skip to content

Instantly share code, notes, and snippets.

@johnfredcee
Created July 21, 2011 13:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johnfredcee/1097145 to your computer and use it in GitHub Desktop.
Save johnfredcee/1097145 to your computer and use it in GitHub Desktop.
Standalone w32shell.el (for vanilla windows emacs)
;;; w32shell.el --- Helpers for inferior shells on w32
;; Copyright (C) 2005, 2006, 2007 by Lennart Borgman
;;
;; Author: Lennart Borgman
;; Created: Tue Nov 22 01:07:13 2005
;; Version: 0.52
;; Last-Updated: Fri May 18 10:58:41 2007 (7200 +0200)
;; Keywords:
;; Compatibility: Emacs 22
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Commentary:
;;
;; On w32 you sometimes need an inferior shell like GNU bash for
;; installations and other purposes. (Note: An "inferior" process in
;; Emacs is a subprocess.) You may also need to have the Emacs bin
;; directory in path at the same time. The main purpose of this
;; package is to make this easier. There are however also some helper
;; functions for manipulating paths on w32.
;;
;; To choose shell customize group the `w32shell'.
;;
;; To run interactive shells you can use `cygwin-shell', `msys-shell'
;; and `cmd-shell'.
;;
;; Notice that you can get the paths to cygwin and MSYS automatically
;; if you use EmacsW32. From the menu bar choose Options - Customize
;; EmacsW32... and then let Emacs search for those paths.
;;
;; Put this in your .emacs:
;;
;; (require 'w32shell)
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Change log:
;;
;; 2005-12-15 More careful check of shell exec.
;; 2005-12-21 (w32shell-delayed-customize): No dialog box.
;; 2005-12-22 (w32shell-set-shell): Call cygwin-mount-activate later.
;; 2006-12-13 Added support for gnuwin32 progs that comes with EmacsW32
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Code:
(eval-when-compile (require 'cl))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Helpers
(defun w32shell-in-exec-path (path)
(let ((dc-exec-path (mapcar (lambda (elt)
(downcase elt))
exec-path)))
(member (downcase path) dc-exec-path)))
(defun w32shell-add-exec-path (path &optional append)
(unless (w32shell-in-exec-path path)
(add-to-list 'exec-path path append)))
(defun w32shell-remove-exec-path (path)
(unless (listp path) (setq path (list path)))
(let ((dcpath (mapcar (lambda (elt)
(downcase elt))
path)))
(dolist (dc dcpath)
(setq exec-path (mapcar (lambda (elt)
(unless (equal dc (downcase elt))
elt))
exec-path)))
(setq exec-path (delete nil exec-path))))
(defun w32shell-in-envpath (path)
(let ((envpath (replace-regexp-in-string "\\\\" "/" (getenv "PATH")))
(norpath (replace-regexp-in-string "\\\\" "/" path))
(case-fold-search t))
(string-match (concat "\\(?:^\\|;\\)" (regexp-quote norpath) "\\($\\|;\\)") envpath)))
(defun w32shell-add-envpath (path &optional append)
(unless (w32shell-in-envpath path)
(let ((bslash-path (replace-regexp-in-string "/" "\\\\" path)))
(if append
(setenv "PATH" (concat (getenv "PATH") ";" bslash-path))
(setenv "PATH" (concat bslash-path ";" (getenv "PATH")))))))
(defun w32shell-remove-envpath (path)
(let ((paths path))
(unless (listp paths) (setq paths (list paths)))
(dolist (path path)
(let ((envpath (replace-regexp-in-string "\\\\" "/" (getenv "PATH")))
(pos (w32shell-in-envpath path)))
(while pos
(let* (
(sub1 (if (= 0 pos) "" (substring envpath 0 pos)))
(sub2 (substring envpath (+ pos 1 (length path))))
(newenvpath (replace-regexp-in-string "/" "\\\\" (concat sub1 sub2))))
(setenv "PATH" newenvpath))
(setq envpath (replace-regexp-in-string "\\\\" "/" (getenv "PATH")))
(setq pos (w32shell-in-envpath path))
)))))
(defun w32shell-add-emacs (&optional append)
"Add Emacs itself to the path of inferior shells."
(interactive)
(w32shell-add-envpath exec-directory)
(w32shell-add-exec-path exec-directory))
(defun w32shell-remove-emacs ()
"Remove Emacs itself from the path of inferior shells."
(interactive)
(w32shell-remove-envpath exec-directory)
(w32shell-remove-exec-path exec-directory))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Choosing a w32 shell for Emacs
(defun w32shell-delayed-customize (msg symbol)
(let ((use-dialog-box nil)
(is-group (get symbol 'custom-group)))
(when (y-or-n-p (format "%s. Do you want to customize %s now? " msg symbol))
(if is-group
(customize-group symbol)
(customize-option symbol)))))
(defun w32shell-verify-bindir (bin-sym shexe)
"If BIN-SYM value is a sh bin directory name return it.
Otherwise offer the user at idle time to customize it.
Helper for `w32shell-set-shell'."
(let ((standard-value (car (get bin-sym 'standard-value)))
(bindir (symbol-value bin-sym))
errmsg exefile)
(if (equal bindir standard-value)
(setq errmsg (concat "You must set " (symbol-name bin-sym)))
(if (file-directory-p bindir)
(progn
;;(setq exefile (concat bindir "/" shexe))
(setq exefile (expand-file-name shexe (file-name-as-directory bindir)))
(unless (file-executable-p exefile)
(setq errmsg (concat "Can't find file " exefile))))
(setq errmsg (concat "Can't find directory " bindir))))
(if errmsg
(let ((use-dialog-box nil))
(lwarn '(w32shell) :warning errmsg)
(unless (eq major-mode 'custom-mode)
(with-timeout (6 (progn
(lwarn '(w32shell) :warning "Ok, please customize w32shell later!")
(message "Time out, continuing")))
(w32shell-delayed-customize errmsg 'w32shell)))
nil)
bindir)))
(defvar w32shell-current-shell-path nil)
(defcustom w32shell-wanted-progs
'("grep" "find" "xargs" "cmp" "diff" "diff3" "cmp" "patch" "locate")
"List of programs that are checked for availability.
This list of programs are searched for in your path by
`executable-find' when calling `w32shell-set-shell'. If any of
them is not found a warning is given."
:type '(repeat string)
:group 'w32shell)
;; Fix-me: write a function that checks consistency against this!
(defun w32shell-set-shell (shellname)
"Set shell to use for inferior shells.
This sets `shell-file-name' and the environment variable SHELL.
It also changes the environment variable PATH and `exec-path'.
Accepted values for SHELLNAME are \"cmd\", \"cygwin\" and
\"msys\".
If SHELLNAME is \"cygwin\" then it calls `cygwin-mount-activate'.
If SHELLNAME is \"cygwin\" or \"msys\" then the corresponding bin
directory is added to path.
This function checks if the programs in `w32shell-wanted-progs'
that may be used from the inferior shells are available. If they
are not a warning will be given. It also checks if 'find' is the
unix style find or not.
Returns non-nil if success."
(interactive
(list
(let* ( (history '("cmd" "msys" "cygwin"))
(history-length (length history)) )
(completing-read "Choose shell: " '("cmd" "msys" "cygwin") nil t "cygwin" 'history))))
;;(lwarn '(w32shell) :warning "Calling w32shell-set-shell %s" shellname)
(let (bin shell)
(cond ( (equal shellname "cygwin")
(setq bin (w32shell-verify-bindir 'w32shell-cygwin-bin "bash.exe"))
(when bin
(unless (file-directory-p bin) (error "Can't find directory %s" bin))
(let ((usr-bin (expand-file-name "../usr/bin" bin))
(usr-local-bin (expand-file-name "../usr/local/bin" bin)))
(setq bin (expand-file-name "../bin" bin))
(setq bin (list bin usr-bin usr-local-bin)))
;; in cygwin use "cygpath -a -w /bin" and "echo $PATH" to check.
;;
;; c:/cygwin/bin shows up in cygwin as /usr/bin,looks
;; like a cygwin bug. I have reported it, but cygwin
;; maintainers does not seem to think it is important
;; (and I can agree).
(setq shell "bash")
(setenv "PS1" "Cygwin \\w > "))
)
( (equal shellname "msys")
(setq bin (w32shell-verify-bindir 'w32shell-msys-bin "sh.exe"))
(when bin
(setq shell "sh")
(setenv "PS1" "MSYS \\w > "))
)
( (equal shellname "cmd")
(setq bin w32shell-emacsw32-gnuwin32-bindir)
;;(lwarn '(w32shell) :warning "cmd cond, bin=%s" bin)
(setq shell (expand-file-name "cmdproxy.exe" exec-directory))
)
( t
(error "Unrecognized shell name: %s" shellname)))
(when (or bin shell)
;; (when bin
;; (unless (listp bin) (setq bin (cons bin nil)))
;; (dolist (b bin)
;; (unless (file-directory-p b)
;; (error "Can't find directory %s" b))))
(when w32shell-current-shell-path
(w32shell-remove-exec-path w32shell-current-shell-path)
(w32shell-remove-envpath w32shell-current-shell-path)
(setq w32shell-current-shell-path nil))
(cond ( (equal shellname "cmd")
(setq process-coding-system-alist nil)
(setq w32-process-args nil)
(remove-hook 'comint-output-filter-functions
'comint-strip-ctrl-m)
)
( (or (equal shellname "cygwin") (equal shellname "msys"))
;;(setq process-coding-system-alist '((shell-file-name . undecided-unix)))
;;(setq process-coding-system-alist (list (cons shell-file-name 'undecided-unix)))
(setq w32-process-args ?\")
;; For Java?:
(add-hook 'comint-output-filter-functions 'comint-strip-ctrl-m)
)
)
(when shell
;;(lwarn '(w32shell) :warning "bin=%s, shell-name=%s" bin shellname)
(when bin
(unless (listp bin) (setq bin (list bin)))
(dolist (b bin)
(w32shell-add-exec-path b)
(w32shell-add-envpath b))
;;(message "exec-path=%s" exec-path)
;;(message "evn PATH=%s" (getenv "PATH"))
)
(setq w32shell-current-shell-path bin)
;; Call cygwin-mount. After an idea by Ismael Valladolid Torres:
(when (equal shellname "cygwin")
(when (require 'cygwin-mount nil t)
(cygwin-mount-activate)))
(setq shell-file-name shell) ; Single shell
;;(setenv "SHELL" shell-file-name) ; Single shell
;;(setq explicit-shell-file-name shell-file-name)
;; Some sanity checks:
(w32shell-check-wanted-progs)
))
bin))
(defun w32shell-get-missing-progs ()
(let ((missing))
(dolist (prog w32shell-wanted-progs)
(unless (executable-find prog)
(add-to-list 'missing prog)))
missing))
(defun w32shell-find-is-unix-find ()
(let ((find-prog (executable-find "find"))
(findstr-prog (executable-find "findstr")))
(not (string= (file-name-directory find-prog)
(file-name-directory findstr-prog)))))
(defun w32shell-check-wanted-progs ()
"Checks if `w32shell-wanted-progs' are available.
This depends on `w32shell'."
(interactive)
(dolist (prog (w32shell-get-missing-progs))
(lwarn '(w32shell) :warning
(concat "When using '" shellname "' program '" prog "' can't be found")))
(unless (w32shell-find-is-unix-find)
(lwarn '(w32shell) :warning
(concat "When using '" shellname "' program 'find'"
" will be Windows' find, should be unix' find"))))
(defun w32shell-quote-argument (argument)
"Like `shell-quote-argument' but knows about w32shell."
(unless (eq system-type 'windows-nt) (error "You can only use this on w32"))
(let ((system-type (if (string= "cmd" shell-file-name)
system-type
'gnu/linux)))
(shell-quote-argument argument)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Custom
(defgroup w32shell nil
"Customization group for w32shell"
:group 'w32)
(defcustom w32shell-cygwin-bin ""
"Path to Cygwin bin directory.
Note that you can set this automatically from the menus through
Options - Customize EmacsW32 if you are using EmacsW32."
:type 'directory
:group 'w32shell)
(defcustom w32shell-msys-bin ""
"Path to MSYS bin directory.
Note that you can set this automatically from the menus through
Options - Customize EmacsW32 if you are using EmacsW32."
:type 'directory
:group 'w32shell)
(defcustom w32shell-emacsw32-gnuwin32-bindir ""
"Path to GNU Win32 bin directory.
Note that you can set this automatically from the menus through
Options - Customize EmacsW32 if you are using EmacsW32."
:type 'directory
:group 'w32shell)
(defvar w32shell-old nil)
(defcustom w32shell-shell nil
"Shell to use for `shell' command.
Value should be 'cmd, 'cygwin or 'msys. If it is cygwin or msys
those utilities bin path are put first in path.
Setting is done with `w32shell-set-shell'."
;; Make sure emacsw32 is loaded:
;;:set-after '(emacsw32-style-frame-title)
:type '(choice
(const :tag "(unset)" nil)
(const :tag "Windows cmd.exe - uses unix progs from EmacsW32" cmd)
(const :tag "Cygwin" cygwin)
(const :tag "MSYS" msys)
)
:set (lambda (symbol value)
(set-default symbol value)
(when value
(unless (eq w32shell-old value)
(setq w32shell-old value)
(w32shell-set-shell (format "%s" value))
))
t)
:group 'w32shell)
(defcustom w32shell-add-emacs-to-path t
"Add Emacs bin directory to path when non-nil."
:type 'boolean
:set (lambda (symbol value)
(set-default symbol value)
(if value
(unless (w32shell-in-exec-path exec-directory)
(w32shell-add-emacs))
(w32shell-remove-emacs)))
:group 'w32shell)
(defvar w32shell-with-shell-internal nil)
(defmacro w32shell-with-shell (use-shell &rest body)
"Execute the BODY forms with shell temporary set to USE-SHELL."
(declare (indent 0) (debug t))
`(let ((shell-file-name)
(exec-path exec-path)
(envpath (getenv "PATH")))
(condition-case err
(when (w32shell-set-shell ,use-shell)
,@body)
(error (message "%s" (error-message-string err))))
(setenv "PATH" envpath)))
(defun cygwin-shell ()
"Run `shell' with Cygwin as the shell.
Does not affect the setting of `w32shell-shell' but otherwise
works as if you had set this to 'cygwin.
See also `msys-shell' and `cmd-shell'."
"Run `shell' with MSYS as the shell.
Is otherwise similar to `cygwin-shell'."
(interactive)
(w32shell-with-shell "cygwin" (shell "*cygwin shell*")))
(defun msys-shell ()
"Run `shell' with MSYS as the shell.
Is otherwise similar to `cygwin-shell'."
(interactive)
(w32shell-with-shell "msys" (shell "*msys shell*")))
(defun cmd-shell ()
"Run `shell' with Windows Command Prompt as the shell.
File name completion with Tab/Shift-Tab is done in the style that
Windows Command Prompt does it.
Is otherwise similar to `cygwin-shell'."
(interactive)
(w32shell-with-shell
"cmd"
(progn
(shell "*cmd shell*")
;; fix-me: Temporary, until removed from viper
;; (when (and (boundp 'viper-insert-basic-map)
;; (keymapp viper-insert-basic-map))
;; (define-key viper-insert-basic-map
;; (if viper-xemacs-p [(shift tab)] [S-tab]) nil))
(local-set-key [tab] 'w32shell-dynamic-complete-filename-like-cmd-fw)
(local-set-key [(shift tab)]
'w32shell-dynamic-complete-filename-like-cmd-bw))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun w32shell-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 `w32shell-dynamic-complete-filename-like-cmd-bw'."
(interactive)
(w32shell-dynamic-complete-filename-like-cmd t))
(defun w32shell-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 `w32shell-dynamic-complete-filename-like-cmd-fw'."
(interactive)
(w32shell-dynamic-complete-filename-like-cmd nil))
(defconst w32shell-dynamic-complete-state nil)
(defcustom w32shell-dynamic-complete-sync-dirs t
"Synchronize process directory and `default-directory' if non-nil.
If non-nil then `w32shell-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 'w32shell)
(defcustom w32shell-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 `w32shell-dynamic-complete-filename-like-cmd-fw' (and
dito -bw)."
:type '(repeat string)
:group 'w32shell)
(defun w32shell-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 (w32shell-get-argv cmdstr))
(first-arg (car argv))
(last-arg (car (reverse argv)))
(only-dirs (member (car first-arg) w32shell-dynamic-complete-only-dirs))
(prev-cmdstr (nth 0 w32shell-dynamic-complete-state))
(prev-completion (nth 1 w32shell-dynamic-complete-state))
(prev-begin-filename (nth 2 w32shell-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 w32shell-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 w32shell-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 w32shell-dynamic-complete-state
(list
(buffer-substring-no-properties pmark (point))
new-completion
begin-filename))))
(defun w32shell-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] 'w32shell-dynamic-complete-filename-like-cmd-fw)
(global-set-key [(shift f9)] 'w32shell-dynamic-complete-filename-like-cmd-bw)
)
(when nil
(let* ((cmd "cd \\\"hej\"\\du \"sista\"")
(argv (w32shell-get-argv cmd)))
(dolist (a argv)
(message "%s %s %s (%s)"
(nth 0 a)
(nth 1 a)
(nth 2 a)
(substring cmd (nth 1 a) (nth 2 a)))))
)
;;(w32-shell-execute nil (concat (getenv "SystemRoot") "\\explorer.exe") "/n,/select,c:\\test\\temp.htm")
(defun w32shell-explorer-file (file)
"Open Windows Explorer with file FILE selected."
(interactive "fFile to focus in Explorer: ")
(let ((full-file (expand-file-name file)))
(setq full-file (replace-regexp-in-string "/" "\\" full-file t t))
(w32-shell-execute nil (concat (getenv "SystemRoot") "\\explorer.exe")
(concat "/n,/select," full-file))))
(defun w32shell-explorer-current-file ()
"Open Windows Explorer with current file selected."
(interactive)
(if buffer-file-name
(w32shell-explorer-file buffer-file-name)
(message "Buffer has no file name")))
(defun w32shell-explorer-old (dir)
"Open Windows Explorer in directory DIR.
For some reason with this function Explorer does not get
focus. Use the new version instead."
(interactive "DStart in directory: ")
(setq dir (expand-file-name dir))
(w32-shell-execute nil dir))
(defun w32shell-explorer (dir)
"Open Windows Explorer in directory DIR."
(interactive "DStart in directory: ")
(setq dir (expand-file-name dir))
;;(setq dir (directory-file-name dir))
(message "dir=%s" dir) (sit-for 2)
(w32-shell-execute
"explore" ;;nil
"" ;(concat (getenv "SystemRoot") "\\explorer.exe")
(concat "/n," dir)
))
(defun w32shell-explorer-here ()
"Open Windows Explorer in current directory."
(interactive)
(w32shell-explorer default-directory))
(defun w32shell-cmd (dir)
"Open a Windows command prompt in directory DIR.
Emacs bin dir is added to path in the started command window."
(interactive "DStart in directory: ")
(let ((default-directory (expand-file-name dir))
(old-emacs-dir (getenv "emacs_dir"))
(old-path (getenv "PATH")))
(setenv "emacs_dir"
(save-match-data
(replace-regexp-in-string "/" "\\" old-emacs-dir t t)))
(w32shell-add-envpath exec-directory)
(unwind-protect
(condition-case err
(progn
;;(call-process "cmd.exe" nil 0 nil "/c" "start" (concat '(?\") "hej4" '(?\")) "cmd.exe")
;; Bug in call-process quoting, use this instead this:
;;(w32-shell-execute nil "cmd.exe" "/c start \"Command Prompt with Emacs in PATH\"")
;; Nope, that will not give the correct path ... - turn off quoting is spawnve instead:
(let ((w32-quote-process-args nil))
(call-process "cmd.exe" nil 0 nil "/c" "start"
(concat '(?\") "Command Prompt with Emacs in PATH" '(?\")) "cmd.exe")))
(error (message "%s" (error-message-string err))))
(setenv "emacs_dir" old-emacs-dir)
(setenv "PATH" old-path))))
(defun w32shell-cmd-here ()
"Open a Windows command prompt in current directory.
Emacs bin dir is added to path in the started command window."
(interactive)
(w32shell-cmd default-directory))
(provide 'w32shell)
;;; w32shell.el ends here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment