;; Lets you run files from dired, with tab completion. ;; The key bindings I use: (add to your .emacs after loading this file) ;; ;; (global-set-key [(alt ?e)] 'run-file-rerun) ;; (define-key dired-mode-map [(alt ?e)] 'dired-run-file) ;; ;; - Peter Amstutz (tetron@student.umass.edu) ;; ;; This ELisp code is licensed under the GNU General Public License, ;; just like the rest of Emacs. ;; some common lisp stuff that ELisp doesn't have... (defun string-right-trim (what str) (if (string= (subseq str (- (length str) (length what)) (length str)) what) (string-left-trim what (subseq str 0 (- (length str) (length what)))) str)) (defun string-left-trim (what str) (if (= 0 (length str)) str (if (string= (subseq str 0 (length what)) what) (string-left-trim what (subseq str (length what) (length str))) str))) (defun string-split (x &optional deliniator) (unless deliniator (setq deliniator ?\ )) (let ( (x (string-left-trim (char-to-string deliniator) x)) (n 0) ) (loop until (or (>= n (length x)) (and (char= (elt x n) deliniator) (not (char= (elt x (- n 1)) ?\\)))) do (if (and (char= (elt x n) deliniator) (char= (elt x (- n 1)) ?\\)) (setq x (concat (subseq x 0 (- n 1)) (subseq x n))) (incf n))) (if (string= x "") nil (cons (subseq x 0 n) (string-split (subseq x n) deliniator))))) (defun prepend-to-bit (bit-to-be-added postfix thestring) (unless (string= thestring "") (let ((n 0)) (when (char= postfix (elt thestring 0)) (setq thestring (concat bit-to-be-added thestring)) (setq n 2)) (loop while (and (< n (length thestring)) (not (char= (elt thestring n) postfix))) do (incf n)) (setq thestring (concat (subseq thestring 0 n) (prepend-to-bit bit-to-be-added postfix (subseq thestring n)))))) thestring) (defun readline-like-tab-complete () "Does a libreadline-like tab completion from the current point" (interactive) (let ( (filename "") (directory "") (curchar) (numchar 0) (file-or-dir t) (pt (point)) (isquote nil) ) (loop while (and (/= (setq curchar (preceding-char)) 0) (not isquote)) do (when (char= curchar ?\") (setq isquote t)) (backward-char)) (when isquote (delete-char 1)) (goto-char pt) (loop while (and (/= (setq curchar (preceding-char)) 0) (if isquote t (or (not (char= curchar ?\ )) (progn (backward-char) (char= (preceding-char) ?\\)) ))) do (when (char= curchar ?/) (setq file-or-dir nil)) (when (char= curchar ?\") (setq isquote nil)) (unless (or (char= ?\" curchar) (and (char= ?\\ curchar) (not (char= ?\\ (char-after))))) (if file-or-dir (setq filename (concat (char-to-string curchar) filename)) (setq directory (concat (char-to-string curchar) directory))) (when file-or-dir (incf numchar)) ) (backward-char) (when (and (char= curchar ?\ ) (not (char= ?\\ (char-after)))) (insert "\\") (backward-char) (incf pt) ) ) (goto-char pt) (let ((n (file-name-completion filename directory))) (when (< 0 (length n)) (insert (prepend-to-bit "\\" ?\ (subseq n numchar (length n)))))))) (load "dired.el") (load "comint.el") (defun dired-run-file () "In dired, run specified (hopefully executable) file" (interactive) (let* ((minimap minibuffer-local-map) (minibuffer-local-map minimap) (arguments "") (buffer (get-buffer-create "*run-file*")) ) (define-key minibuffer-local-map [tab] 'readline-like-tab-complete) (setq arguments (string-split (read-string (format "%s " (dired-get-filename))))) (comint-exec buffer (dired-get-filename) (dired-get-filename) nil arguments) (setq running (list buffer (dired-get-filename) (dired-get-filename) nil arguments))) (switch-to-buffer "*run-file*") (comint-mode)) (defun run-file-rerun () (interactive) (when running (comint-exec (nth 0 running) (nth 1 running) (nth 2 running) (nth 3 running) (nth 4 running)) (switch-to-buffer "*run-file*")))