;;; em-unix.el --- UNIX command aliases
-;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
-;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2012 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;;; Code:
(require 'eshell)
+(require 'esh-opt)
+(require 'pcomplete)
-(defgroup eshell-unix nil
+;;;###autoload
+(eshell-defgroup eshell-unix nil
"This module defines many of the more common UNIX utilities as
aliases implemented in Lisp. These include mv, ln, cp, rm, etc. If
the user passes arguments which are too complex, or are unrecognized
:tag "UNIX commands in Lisp"
:group 'eshell-module)
-(defcustom eshell-unix-load-hook '(eshell-unix-initialize)
- "*A list of functions to run when `eshell-unix' is loaded."
+(defcustom eshell-unix-load-hook nil
+ "A list of functions to run when `eshell-unix' is loaded."
+ :version "24.1" ; removed eshell-unix-initialize
:type 'hook
:group 'eshell-unix)
(defcustom eshell-plain-grep-behavior nil
- "*If non-nil, standalone \"grep\" commands will behave normally.
+ "If non-nil, standalone \"grep\" commands will behave normally.
Standalone in this context means not redirected, and not on the
receiving side of a command pipeline."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-no-grep-available (not (eshell-search-path "grep"))
- "*If non-nil, no grep is available on the current machine."
+ "If non-nil, no grep is available on the current machine."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-plain-diff-behavior nil
- "*If non-nil, standalone \"diff\" commands will behave normally.
+ "If non-nil, standalone \"diff\" commands will behave normally.
Standalone in this context means not redirected, and not on the
receiving side of a command pipeline."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-plain-locate-behavior (featurep 'xemacs)
- "*If non-nil, standalone \"locate\" commands will behave normally.
+ "If non-nil, standalone \"locate\" commands will behave normally.
Standalone in this context means not redirected, and not on the
receiving side of a command pipeline."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-rm-removes-directories nil
- "*If non-nil, `rm' will remove directory entries.
+ "If non-nil, `rm' will remove directory entries.
Otherwise, `rmdir' is required."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-rm-interactive-query (= (user-uid) 0)
- "*If non-nil, `rm' will query before removing anything."
+ "If non-nil, `rm' will query before removing anything."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-mv-interactive-query (= (user-uid) 0)
- "*If non-nil, `mv' will query before overwriting anything."
+ "If non-nil, `mv' will query before overwriting anything."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-mv-overwrite-files t
- "*If non-nil, `mv' will overwrite files without warning."
+ "If non-nil, `mv' will overwrite files without warning."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-cp-interactive-query (= (user-uid) 0)
- "*If non-nil, `cp' will query before overwriting anything."
+ "If non-nil, `cp' will query before overwriting anything."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-cp-overwrite-files t
- "*If non-nil, `cp' will overwrite files without warning."
+ "If non-nil, `cp' will overwrite files without warning."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-ln-interactive-query (= (user-uid) 0)
- "*If non-nil, `ln' will query before overwriting anything."
+ "If non-nil, `ln' will query before overwriting anything."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-ln-overwrite-files nil
- "*If non-nil, `ln' will overwrite files without warning."
+ "If non-nil, `ln' will overwrite files without warning."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-default-target-is-dot nil
- "*If non-nil, the default destination for cp, mv or ln is `.'."
+ "If non-nil, the default destination for cp, mv or ln is `.'."
:type 'boolean
:group 'eshell-unix)
(defcustom eshell-du-prefer-over-ange nil
- "*Use Eshell's du in ange-ftp remote directories.
+ "Use Eshell's du in ange-ftp remote directories.
Otherwise, Emacs will attempt to use rsh to invoke du on the remote machine."
:type 'boolean
:group 'eshell-unix)
(make-local-variable 'eshell-complex-commands)
(setq eshell-complex-commands
(append '("grep" "egrep" "fgrep" "agrep" "glimpse" "locate"
- "cat" "time" "cp" "mv" "make" "du" "diff")
+ "cat" "time" "cp" "mv" "make" "du" "diff" "su" "sudo")
eshell-complex-commands)))
(defalias 'eshell/date 'current-time-string)
(defalias 'eshell/basename 'file-name-nondirectory)
(defalias 'eshell/dirname 'file-name-directory)
-(eval-when-compile
- (defvar interactive)
- (defvar preview)
- (defvar recursive)
- (defvar verbose))
+(defvar em-interactive)
+(defvar em-preview)
+(defvar em-recursive)
+(defvar em-verbose)
(defun eshell/man (&rest args)
"Invoke man, flattening the arguments appropriately."
(eshell-error "rm: cannot remove `.' or `..'\n"))
(if (and (file-directory-p (car files))
(not (file-symlink-p (car files))))
- (let ((dir (file-name-as-directory (car files))))
- (eshell-remove-entries dir
- (mapcar
- (function
- (lambda (file)
- (concat dir file)))
- (directory-files dir)))
- (if verbose
+ (progn
+ (if em-verbose
(eshell-printn (format "rm: removing directory `%s'"
(car files))))
(unless
- (or preview
- (and interactive
+ (or em-preview
+ (and em-interactive
(not (y-or-n-p
(format "rm: remove directory `%s'? "
(car files))))))
- (eshell-funcalln 'delete-directory (car files))))
- (if verbose
+ (eshell-funcalln 'delete-directory (car files) t t)))
+ (if em-verbose
(eshell-printn (format "rm: removing file `%s'"
(car files))))
- (unless (or preview
- (and interactive
+ (unless (or em-preview
+ (and em-interactive
(not (y-or-n-p
(format "rm: remove `%s'? "
(car files))))))
- (eshell-funcalln 'delete-file (car files)))))
+ (eshell-funcalln 'delete-file (car files) t))))
(setq files (cdr files))))
(defun eshell/rm (&rest args)
"rm" args
'((?h "help" nil nil "show this usage screen")
(?f "force" nil force-removal "force removal")
- (?i "interactive" nil interactive "prompt before any removal")
- (?n "preview" nil preview "don't change anything on disk")
- (?r "recursive" nil recursive
+ (?i "interactive" nil em-interactive "prompt before any removal")
+ (?n "preview" nil em-preview "don't change anything on disk")
+ (?r "recursive" nil em-recursive
"remove the contents of directories recursively")
- (?R nil nil recursive "(same)")
- (?v "verbose" nil verbose "explain what is being done")
+ (?R nil nil em-recursive "(same)")
+ (?v "verbose" nil em-verbose "explain what is being done")
:preserve-args
:external "rm"
:show-usage
:usage "[OPTION]... FILE...
Remove (unlink) the FILE(s).")
- (unless interactive
- (setq interactive eshell-rm-interactive-query))
- (if (and force-removal interactive)
- (setq interactive nil))
+ (unless em-interactive
+ (setq em-interactive eshell-rm-interactive-query))
+ (if (and force-removal em-interactive)
+ (setq em-interactive nil))
(while args
(let ((entry (if (stringp (car args))
(directory-file-name (car args))
(car args)))))
(cond
((bufferp entry)
- (if verbose
+ (if em-verbose
(eshell-printn (format "rm: removing buffer `%s'" entry)))
- (unless (or preview
- (and interactive
+ (unless (or em-preview
+ (and em-interactive
(not (y-or-n-p (format "rm: delete buffer `%s'? "
entry)))))
(eshell-funcalln 'kill-buffer entry)))
((eshell-processp entry)
- (if verbose
+ (if em-verbose
(eshell-printn (format "rm: killing process `%s'" entry)))
- (unless (or preview
- (and interactive
+ (unless (or em-preview
+ (and em-interactive
(not (y-or-n-p (format "rm: kill process `%s'? "
entry)))))
(eshell-funcalln 'kill-process entry)))
((symbolp entry)
- (if verbose
+ (if em-verbose
(eshell-printn (format "rm: uninterning symbol `%s'" entry)))
(unless
- (or preview
- (and interactive
+ (or em-preview
+ (and em-interactive
(not (y-or-n-p (format "rm: unintern symbol `%s'? "
entry)))))
(eshell-funcalln 'unintern entry)))
((stringp entry)
(if (and (file-directory-p entry)
(not (file-symlink-p entry)))
- (if (or recursive
+ (if (or em-recursive
eshell-rm-removes-directories)
- (if (or preview
- (not interactive)
+ (if (or em-preview
+ (not em-interactive)
(y-or-n-p
(format "rm: descend into directory `%s'? "
entry)))
(put 'eshell/rmdir 'eshell-no-numeric-conversions t)
-(eval-when-compile
- (defvar no-dereference)
- (defvar preview)
- (defvar verbose))
+(defvar no-dereference)
(defvar eshell-warn-dot-directories t)
"Shuffle around some filesystem entries, using FUNC to do the work."
(let ((attr-target (eshell-file-attributes target))
(is-dir (or (file-directory-p target)
- (and preview (not eshell-warn-dot-directories))))
+ (and em-preview (not eshell-warn-dot-directories))))
attr)
- (if (and (not preview) (not is-dir)
+ (if (and (not em-preview) (not is-dir)
(> (length files) 1))
(error "%s: when %s multiple files, last argument must be a directory"
command action))
(not (memq func '(make-symbolic-link
add-name-to-file))))
(if (and (eq func 'copy-file)
- (not recursive))
+ (not em-recursive))
(eshell-error (format "%s: %s: omitting directory\n"
command (car files)))
(let (eshell-warn-dot-directories)
(expand-file-name target)))))))
(apply 'eshell-funcalln func source target args)
(unless (file-directory-p target)
- (if verbose
+ (if em-verbose
(eshell-printn
(format "%s: making directory %s"
command target)))
- (unless preview
+ (unless em-preview
(eshell-funcalln 'make-directory target)))
(apply 'eshell-shuffle-files
command action
(directory-files source))
target func t args)
(when (eq func 'rename-file)
- (if verbose
+ (if em-verbose
(eshell-printn
(format "%s: deleting directory %s"
command source)))
- (unless preview
+ (unless em-preview
(eshell-funcalln 'delete-directory source))))))
- (if verbose
+ (if em-verbose
(eshell-printn (format "%s: %s -> %s" command
source target)))
- (unless preview
+ (unless em-preview
(if (and no-dereference
(setq link (file-symlink-p source)))
(progn
(if (file-exists-p archive)
(setq tar-args (concat "u" tar-args))
(setq tar-args (concat "c" tar-args)))
- (if verbose
+ (if em-verbose
(setq tar-args (concat "v" tar-args)))
(if (equal command "mv")
(setq tar-args (concat "--remove-files -" tar-args)))
(eshell-shuffle-files
,command ,action args target ,func nil
,@(append
- `((if (and (or interactive
+ `((if (and (or em-interactive
,query-var)
(not force))
1 (or force ,force-var)))
"mv" args
'((?f "force" nil force
"remove existing destinations, never prompt")
- (?i "interactive" nil interactive
+ (?i "interactive" nil em-interactive
"request confirmation if target already exists")
- (?n "preview" nil preview
+ (?n "preview" nil em-preview
"don't change anything on disk")
- (?v "verbose" nil verbose
+ (?v "verbose" nil em-verbose
"explain what is being done")
(nil "help" nil nil "show this usage screen")
:preserve-args
"preserve links")
(?f "force" nil force
"remove existing destinations, never prompt")
- (?i "interactive" nil interactive
+ (?i "interactive" nil em-interactive
"request confirmation if target already exists")
- (?n "preview" nil preview
+ (?n "preview" nil em-preview
"don't change anything on disk")
(?p "preserve" nil preserve
"preserve file attributes if possible")
- (?R "recursive" nil recursive
+ (?R "recursive" nil em-recursive
"copy directories recursively")
- (?v "verbose" nil verbose
+ (?v "verbose" nil em-verbose
"explain what is being done")
(nil "help" nil nil "show this usage screen")
:preserve-args
or: cp [OPTION]... SOURCE... DIRECTORY
Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.")
(if archive
- (setq preserve t no-dereference t recursive t))
+ (setq preserve t no-dereference t em-recursive t))
(eshell-mvcpln-template "cp" "copying" 'copy-file
eshell-cp-interactive-query
eshell-cp-overwrite-files preserve)))
'((?h "help" nil nil "show this usage screen")
(?s "symbolic" nil symbolic
"make symbolic links instead of hard links")
- (?i "interactive" nil interactive
+ (?i "interactive" nil em-interactive
"request confirmation if target already exists")
(?f "force" nil force "remove existing destinations, never prompt")
- (?n "preview" nil preview
+ (?n "preview" nil em-preview
"don't change anything on disk")
- (?v "verbose" nil verbose "explain what is being done")
+ (?v "verbose" nil em-verbose "explain what is being done")
:preserve-args
:external "ln"
:show-usage
(setq args (eshell-stringify-list (eshell-flatten-list args)))
(if (or eshell-in-pipeline-p
(catch 'special
- (eshell-for arg args
+ (dolist (arg args)
(unless (or (and (stringp arg)
(> (length arg) 0)
(eq (aref arg 0) ?-))
:show-usage
:usage "[OPTION] FILE...
Concatenate FILE(s), or standard input, to standard output.")
- (eshell-for file args
+ (dolist (file args)
(if (string= file "-")
(throw 'eshell-external
(eshell-external-command "cat" args))))
(let ((curbuf (current-buffer)))
- (eshell-for file args
+ (dolist (file args)
(with-temp-buffer
(insert-file-contents file)
(goto-char (point-min))
"In Occur mode, go to the occurrence whose line you click on."
(interactive "e")
(let (pos)
- (save-excursion
- (set-buffer (window-buffer (posn-window (event-end event))))
+ (with-current-buffer (window-buffer (posn-window (event-end event)))
(save-excursion
(goto-char (posn-point (event-end event)))
(setq pos (occur-mode-find-occurrence))))
(funcall (or (pcomplete-find-completion-function (pcomplete-arg 1))
pcomplete-default-completion-function)))
-(defalias 'pcomplete/ssh 'pcomplete/rsh)
-
-(eval-when-compile
- (defvar block-size)
- (defvar by-bytes)
- (defvar dereference-links)
- (defvar grand-total)
- (defvar human-readable)
- (defvar max-depth)
- (defvar only-one-filesystem)
- (defvar show-all))
+(defvar block-size)
+(defvar by-bytes)
+(defvar dereference-links)
+(defvar grand-total)
+(defvar human-readable)
+(defvar max-depth)
+(defvar only-one-filesystem)
+(defvar show-all)
(defsubst eshell-du-size-string (size)
(let* ((str (eshell-printable-size size human-readable block-size t))
(let ((ext-du (eshell-search-path "du")))
(if (and ext-du
(not (catch 'have-ange-path
- (eshell-for arg args
- (if (eq (find-file-name-handler (expand-file-name arg)
- 'directory-files)
- 'ange-ftp-hook-function)
+ (dolist (arg args)
+ (if (string-equal
+ (file-remote-p (expand-file-name arg) 'method) "ftp")
(throw 'have-ange-path t))))))
(throw 'eshell-replace-command
(eshell-parse-command ext-du args))
(defvar eshell-time-start nil)
(defun eshell-show-elapsed-time ()
- (let ((elapsed (format "%.3f secs\n"
- (- (eshell-time-to-seconds (current-time))
- eshell-time-start))))
+ (let ((elapsed (format "%.3f secs\n" (- (float-time) eshell-time-start))))
(set-text-properties 0 (length elapsed) '(face bold) elapsed)
(eshell-interactive-print elapsed))
(remove-hook 'eshell-post-command-hook 'eshell-show-elapsed-time t))
:show-usage
:usage "COMMAND...
Show wall-clock time elapsed during execution of COMMAND.")
- (setq eshell-time-start (eshell-time-to-seconds (current-time)))
+ (setq eshell-time-start (float-time))
(add-hook 'eshell-post-command-hook 'eshell-show-elapsed-time nil t)
;; after setting
(throw 'eshell-replace-command
(eshell-stringify-list
(eshell-flatten-list (cdr time-args))))))))
-(defalias 'eshell/whoami 'user-login-name)
+(defun eshell/whoami (&rest args)
+ "Make \"whoami\" Tramp aware."
+ (or (file-remote-p default-directory 'user) (user-login-name)))
(defvar eshell-diff-window-config nil)
((string-match "[^[:blank:]]" string) string)
(nil)))
+(autoload 'diff-no-select "diff")
+
(defun eshell/diff (&rest args)
"Alias \"diff\" to call Emacs `diff' function."
(let ((orig-args (eshell-stringify-list (eshell-flatten-list args))))
(setcdr (last args 3) nil))
(with-current-buffer
(condition-case err
- (diff old new
- (nil-blank-string (eshell-flatten-and-stringify args)))
+ (diff-no-select
+ old new
+ (nil-blank-string (eshell-flatten-and-stringify args)))
(error
(throw 'eshell-replace-command
(eshell-parse-command "*diff" orig-args))))
(put 'eshell/occur 'eshell-no-numeric-conversions t)
+;; Pacify the byte-compiler.
+(defvar tramp-default-proxies-alist)
+
+(defun eshell/su (&rest args)
+ "Alias \"su\" to call Tramp."
+ (require 'tramp)
+ (setq args (eshell-stringify-list (eshell-flatten-list args)))
+ (let ((orig-args (copy-tree args)))
+ (eshell-eval-using-options
+ "su" args
+ '((?h "help" nil nil "show this usage screen")
+ (?l "login" nil login "provide a login environment")
+ (? nil nil login "provide a login environment")
+ :usage "[- | -l | --login] [USER]
+Become another USER during a login session.")
+ (throw 'eshell-replace-command
+ (let ((user "root")
+ (host (or (file-remote-p default-directory 'host)
+ "localhost"))
+ (dir (or (file-remote-p default-directory 'localname)
+ (expand-file-name default-directory))))
+ (dolist (arg args)
+ (if (string-equal arg "-") (setq login t) (setq user arg)))
+ ;; `eshell-eval-using-options' does not handle "-".
+ (if (member "-" orig-args) (setq login t))
+ (if login (setq dir "~/"))
+ (if (and (file-remote-p default-directory)
+ (or
+ (not (string-equal
+ "su" (file-remote-p default-directory 'method)))
+ (not (string-equal
+ user (file-remote-p default-directory 'user)))))
+ (add-to-list
+ 'tramp-default-proxies-alist
+ (list host user (file-remote-p default-directory))))
+ (eshell-parse-command
+ "cd" (list (format "/su:%s@%s:%s" user host dir))))))))
+
+(put 'eshell/su 'eshell-no-numeric-conversions t)
+
+(defun eshell/sudo (&rest args)
+ "Alias \"sudo\" to call Tramp."
+ (require 'tramp)
+ (setq args (eshell-stringify-list (eshell-flatten-list args)))
+ (let ((orig-args (copy-tree args)))
+ (eshell-eval-using-options
+ "sudo" args
+ '((?h "help" nil nil "show this usage screen")
+ (?u "user" t user "execute a command as another USER")
+ :show-usage
+ :usage "[(-u | --user) USER] COMMAND
+Execute a COMMAND as the superuser or another USER.")
+ (throw 'eshell-external
+ (let ((user (or user "root"))
+ (host (or (file-remote-p default-directory 'host)
+ "localhost"))
+ (dir (or (file-remote-p default-directory 'localname)
+ (expand-file-name default-directory))))
+ ;; `eshell-eval-using-options' reads options of COMMAND.
+ (while (and (stringp (car orig-args))
+ (member (car orig-args) '("-u" "--user")))
+ (setq orig-args (cddr orig-args)))
+ (if (and (file-remote-p default-directory)
+ (or
+ (not (string-equal
+ "sudo" (file-remote-p default-directory 'method)))
+ (not (string-equal
+ user (file-remote-p default-directory 'user)))))
+ (add-to-list
+ 'tramp-default-proxies-alist
+ (list host user (file-remote-p default-directory))))
+ (let ((default-directory (format "/sudo:%s@%s:%s" user host dir)))
+ (eshell-named-command (car orig-args) (cdr orig-args))))))))
+
+(put 'eshell/sudo 'eshell-no-numeric-conversions t)
+
(provide 'em-unix)
-;; arch-tag: 2462edd2-a76a-4cf2-897d-92e9a82ac1c9
+;; Local Variables:
+;; generated-autoload-file: "esh-groups.el"
+;; End:
+
;;; em-unix.el ends here