emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/shell-command+ 57afacb 01/36: initial export


From: Stefan Monnier
Subject: [elpa] externals/shell-command+ 57afacb 01/36: initial export
Date: Fri, 25 Sep 2020 11:01:21 -0400 (EDT)

branch: externals/shell-command+
commit 57afacb82ae40ee97da953d844e18800554909b6
Author: Philip K <philip@warpmail.net>
Commit: Philip K <philip@warpmail.net>

    initial export
---
 bang.el | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 113 insertions(+)

diff --git a/bang.el b/bang.el
new file mode 100644
index 0000000..8658ab6
--- /dev/null
+++ b/bang.el
@@ -0,0 +1,113 @@
+;;; -*- lexical-binding: t -*-
+;;; published under CC0 into the public domain
+;;; author: philip k. [https://zge.us.to], 2019
+;;;
+;;; based on bang from http://chneukirchen.org/dotfiles/.emacs
+
+(require 'rx)
+
+(defconst bang--command-regexp
+  (rx bos (* space)
+         (or (seq (group "!" )
+                          (or (group (+ digit))
+                                  (group (+ alnum))))
+                 (group "<") (group ">") (group "|") "")
+         (? (* space)
+                (group (* not-newline)
+                               (not space)
+                               (*? not-newline)))
+         eos)
+  "Regular expression to parse input to `bang'.")
+
+(defvar bang--last-commands '()
+  "List of non-history commands last executed by `bang'.")
+
+(defvar bang-history-size 80
+  "Number of commands to save in `bang--last-commands'.")
+
+(defun bang--remember-command (command)
+  (push command bang--last-commands)
+  (let ((overflow (- (length bang--last-commands)
+                                        bang-history-size)))
+       (when (> overflow 0)
+         (setq bang--last-commands
+                       (nbutlast bang--last-commands overflow)))))
+
+(defun bang--find-last-command (prefix)
+  (catch 'found
+       (dolist (cmd bang--last-commands)
+         (when (string-prefix-p prefix cmd)
+               (throw 'found cmd)))
+       (error "no such command in history")))
+
+(defun bang--get-command-number (arg rest)
+  (let* ((num (string-to-number arg))
+                (pos (- (length bang--last-commands)
+                                (1- num)))
+                (cmd (nth pos bang--last-commands)))
+       (concat cmd " " rest)))
+
+(defun bang-history ()
+  "Display a buffer with overview of previous bang commands."
+  (interactive)
+  (let ((buf (get-buffer-create "*bang-history*"))
+               (i (length bang--last-commands)))
+       (with-current-buffer buf
+         (setq buffer-read-only nil)
+         (delete-region (goto-char (point-min))
+                                        (point-max))
+         (dolist (cmd bang--last-commands)
+               (insert (format "%d\t%s\n" i cmd))
+               (setq i (1- i)))
+         (special-mode))
+       (pop-to-buffer buf)))
+
+(defun bang (command beg end)
+  "Intelligently execute string COMMAND in inferior shell, like
+with `shell-command'.
+
+When COMMAND starts with
+  <  the output of COMMAND replaces the current selection
+  >  COMMAND is run with the current selection as input
+  |  the current selection is filtered through COMMAND
+  !  executes the last command that started with COMMAND,
+     or if a number, re-execute nth last command
+
+Without any argument, `bang' will behave like `shell-command'.
+
+Inside COMMAND, % is replaced with the current file name. To
+insert a literal % quote it using a backslash."
+  (interactive (list (read-shell-command "Bang command: ")
+                                        (if mark-active (region-beginning) 
(point-min))
+                                        (if mark-active (region-end) 
(point-max))))
+  (save-match-data
+       (unless (string-match bang--command-regexp command)
+         (error "Invalid command"))
+       (let ((has-! (match-string-no-properties 1 command))
+                 (num-! (match-string-no-properties 2 command))
+                 (arg-! (match-string-no-properties 3 command))
+                 (has-< (match-string-no-properties 4 command))
+                 (has-> (match-string-no-properties 5 command))
+                 (has-| (match-string-no-properties 6 command))
+                 (rest  (match-string-no-properties 7 command)))
+         (cond (arg-! (bang (bang--find-last-command arg-!)
+                                                beg end))
+                       (num-! (bang (bang--get-command-number num-! rest)
+                                                beg end))
+                       (has-< (delete-region beg end)
+                                  (shell-command rest t 
shell-command-default-error-buffer)
+                                  (exchange-point-and-mark))
+                       (has-> (shell-command-on-region
+                                       beg end rest nil nil
+                                       shell-command-default-error-buffer t))
+                       (has-| (shell-command-on-region
+                                       beg end rest t t
+                                       shell-command-default-error-buffer t))
+                       (t (shell-command command nil 
shell-command-default-error-buffer)))
+         (when (or has-! has->)
+               (with-current-buffer "*Shell Command Output*"
+                 (kill-ring-save (point-min) (point-max))))
+         (unless (or num-! arg-!)
+               (bang--remember-command command)))))
+
+(provide 'bang)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]