[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/objed 639dc87 163/216: Add interactive pipe op
From: |
Stefan Monnier |
Subject: |
[elpa] externals/objed 639dc87 163/216: Add interactive pipe op |
Date: |
Tue, 8 Jan 2019 12:29:32 -0500 (EST) |
branch: externals/objed
commit 639dc87e89fae6cb027f7724ccdf186de47f93d5
Author: Clemera <address@hidden>
Commit: Clemera <address@hidden>
Add interactive pipe op
---
objed.el | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 185 insertions(+), 1 deletion(-)
diff --git a/objed.el b/objed.el
index 0efa4e6..3e35b32 100644
--- a/objed.el
+++ b/objed.el
@@ -702,9 +702,15 @@ BEFORE and AFTER are forms to execute before/after calling
the command."
(define-key map "j" 'objed-occur)
;; TODO: start query replace in current object,
;; or for all
- (define-key map "%" (objed-define-op nil objed-replace current))
+ (define-key map "%"
+ (objed-define-op nil objed-replace current))
(define-key map "&"
(objed-define-op nil objed-pipe-region))
+
+ (define-key map "|"
+ (objed-define-op nil objed-ipipe))
+
+
(define-key map "!"
(objed-define-op nil objed-replace-op))
@@ -2553,6 +2559,184 @@ c: capitalize."
(call-interactively 'query-replace-regexp))))
+;; * Ipipe
+;; inspired by jq-mode
+
+;; ** Minibuffer setup
+
+(defvar objed-ipipe-hist '()
+ "History for `objed-ipipe'.")
+
+(defvar objed-ipipe-minibuffer-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map minibuffer-local-map)
+ (define-key map (kbd "<tab>") #'objed-ipipe-complete)
+ (define-key map (kbd "<return>") #'objed-ipipe-commit)
+ map)
+ "Keymap for `objed-ipipe'.")
+
+;; ** Display update
+
+(defvar objed--ipipe-schedule-time 0.15
+ "Time frame to update the display.")
+
+(defvar objed--ipipe-timer nil)
+
+(defun objed--ipipe-reset-timer ()
+ (when objed--ipipe-timer
+ (cancel-timer objed--ipipe-timer))
+ (setq objed--ipipe-timer nil))
+
+(defun objed--ipipe-schedule-timer ()
+ (let ((mini (window-buffer (active-minibuffer-window))))
+ (objed--ipipe-reset-timer)
+ (setq objed--ipipe-timer
+ (run-with-idle-timer
+ objed--ipipe-schedule-time nil
+ (lambda (buf)
+ (with-current-buffer buf
+ (objed--ipipe-update-display)))
+ mini))))
+
+(defvar objed--ipipe-overlay nil
+ "Overlay showing the results in current buffer.")
+
+(defvar objed--ipipe-last ""
+ "Cache last used command.")
+
+(defvar objed--ipipe-region-string ""
+ "Cache last region.")
+
+
+(defun objed--ipipe-update-display ()
+ "Update display.
+
+ Assumes current buffer is minibuffer."
+ (let ((cmd (minibuffer-contents))
+ (res nil))
+ ;; only update display if user provides new input
+ (if (and (minibufferp)
+ ;; make sure we are in an ipipe session
+ (eq (current-local-map) objed-ipipe-minibuffer-map))
+ (if (string= "" cmd)
+ ;; after commit or delete update the overlay
+ (overlay-put objed--ipipe-overlay 'after-string
+ objed--ipipe-region-string)
+ ;; save last input and update if possible
+ (setq objed--ipipe-last cmd)
+ (if (setq res (objed--ipipe-to-string cmd
objed--ipipe-region-string))
+ (overlay-put objed--ipipe-overlay 'after-string res)
+ (overlay-put objed--ipipe-overlay 'after-string
+ objed--ipipe-region-string)))
+ (when (minibufferp)
+ (remove-hook 'after-change-functions 'objed--ipipe-schedule-time t)))))
+
+
+(defun objed--ipipe-parse (str)
+ (with-temp-buffer
+ (insert str)
+ (goto-char (point-min))
+ (when (re-search-forward "\\(.*?\\)\\( \\|\\'\\)" nil t)
+ (cons (match-string 1)
+ (buffer-substring (point) (line-end-position))))))
+
+
+(defun objed--ipipe-to-string (cmd-args str)
+ (let* ((cmdline (minibuffer-contents))
+ (parsed (objed--ipipe-parse cmdline))
+ (cmd (car-safe parsed))
+ (args (cdr-safe parsed)))
+ (cond ((and cmd (executable-find cmd))
+ (with-temp-buffer
+ (let ((exit (call-process-region
+ str nil
+ shell-file-name
+ nil t nil
+ shell-command-switch
+ cmdline)))
+ (when (= 0 exit)
+ (buffer-string)))))
+ ((or (and (intern-soft (concat cmd "-region"))
+ (setq cmd (concat cmd "-region")))
+ (intern-soft cmd))
+ (when (commandp (setq cmd (intern cmd)))
+ (with-temp-buffer
+ (insert str)
+ (goto-char (point-min))
+ (push-mark (point-max) t t)
+ (when (ignore-errors (call-interactively cmd) t)
+ (buffer-string))))))))
+
+
+
+;; ** Minibuffer commands
+
+(defun objed-ipipe-commit ()
+ "Commit current minibuffer input.
+
+Exit if there is no content."
+ (interactive)
+ (if (string= "" (minibuffer-contents))
+ (exit-minibuffer)
+ ;; when timer did not run yet, update manually
+ (when objed--ipipe-timer
+ (objed--ipipe-reset-timer)
+ (objed--ipipe-update-display))
+ ;; cache current string
+ (setq objed--ipipe-region-string
+ (overlay-get objed--ipipe-overlay 'after-string))
+ (cl-pushnew (minibuffer-contents)
+ objed-ipipe-hist :test #'string=)
+ (delete-minibuffer-contents)))
+
+(defun objed-ipipe-complete ()
+ "Complete for shell commands and region commands."
+ (interactive)
+ (let ((bounds (or (bounds-of-thing-at-point 'symbol)
+ (cons (point)
+ (point))))
+ (sym (or (thing-at-point 'symbol) "")))
+ (cl-destructuring-bind (beg . end) bounds
+ (completion-in-region
+ beg end (append
+ (locate-file-completion-table
+ exec-path exec-suffixes sym 'identity t)
+ (or objed--cmd-cache
+ (progn
+ (mapatoms #'objed--init-cmd-cache)
+ objed--cmd-cache)))))))
+
+;; ** Entry command
+
+(defun objed-ipipe (beg end)
+ (interactive "r")
+ ;; init
+ (setq objed--ipipe-last "")
+ (setq objed--ipipe-overlay (make-overlay beg end))
+ (objed--ipipe-reset-timer)
+ (overlay-put objed--ipipe-overlay 'invisible t)
+ (overlay-put objed--ipipe-overlay 'after-string
+ (setq objed--ipipe-region-string
+ (buffer-substring-no-properties beg end)))
+ (unwind-protect
+ (minibuffer-with-setup-hook
+ (lambda ()
+ (add-hook 'after-change-functions 'objed--ipipe-schedule-timer nil
t))
+ ;; on success replace region with current overlay
+ (save-restriction
+ (narrow-to-region beg end)
+ (when (read-from-minibuffer "Command (leave blank to accept current
state): " nil
+ objed-ipipe-minibuffer-map nil
'objed-ipipe-hist)
+ (objed--ipipe-reset-timer)
+ (delete-region beg end)
+ (save-excursion
+ (insert (overlay-get objed--ipipe-overlay 'after-string))))))
+ (objed--ipipe-reset-timer)
+ (dolist (buf (buffer-list))
+ (when (minibufferp buf)
+ (remove-hook 'after-change-functions 'objed--ipipe-schedule-time t)))
+ (delete-overlay objed--ipipe-overlay)))
+
;; * Exit active state
(defun objed--line-p (text)
- [elpa] externals/objed ac6ecb0 149/216: Mention new extend functionality, (continued)
- [elpa] externals/objed ac6ecb0 149/216: Mention new extend functionality, Stefan Monnier, 2019/01/08
- [elpa] externals/objed 4a84e59 174/216: Bind this-command when executing region command, Stefan Monnier, 2019/01/08
- [elpa] externals/objed 60c4731 139/216: Remove key binding info in header, use readme for that, Stefan Monnier, 2019/01/08
- [elpa] externals/objed 62c2dee 118/216: Improve move object code, Stefan Monnier, 2019/01/08
- [elpa] externals/objed c88bb7b 134/216: Mention new functionality, Stefan Monnier, 2019/01/08
- [elpa] externals/objed 6951f1b 177/216: Add convenience bindings for forward/backward until buffer, Stefan Monnier, 2019/01/08
- [elpa] externals/objed fbabb7a 178/216: Add command to insert new object of current type, Stefan Monnier, 2019/01/08
- [elpa] externals/objed d792eb0 160/216: Dont reinit object for first extend, Stefan Monnier, 2019/01/08
- [elpa] externals/objed 7f575aa 180/216: Fix dispatch, when no object found, Stefan Monnier, 2019/01/08
- [elpa] externals/objed f643281 171/216: Correct key names, Stefan Monnier, 2019/01/08
- [elpa] externals/objed 639dc87 163/216: Add interactive pipe op,
Stefan Monnier <=
- [elpa] externals/objed 179ac60 185/216: Update docs for exit-op, Stefan Monnier, 2019/01/08
- [elpa] externals/objed de09955 153/216: Markup fixes again, Stefan Monnier, 2019/01/08
- [elpa] externals/objed 4489ea3 187/216: Fixup forward word extend when already at word end pos, Stefan Monnier, 2019/01/08
- [elpa] externals/objed 9a0ea65 192/216: Fix override of default for comint-prompt-regexp, Stefan Monnier, 2019/01/08
- [elpa] externals/objed a7b9df6 183/216: Add C-RET, M-RET for eval-in-repl and inserting new object, Stefan Monnier, 2019/01/08
- [elpa] externals/objed 5ca0678 195/216: Indent for tab command should not activate objed, Stefan Monnier, 2019/01/08
- [elpa] externals/objed 93db5bc 215/216: Fix last commit, Stefan Monnier, 2019/01/08
- [elpa] externals/objed cd7be8b 211/216: Improve objed-extend, Stefan Monnier, 2019/01/08
- [elpa] externals/objed 10de1ad 189/216: Comment about commandline test, Stefan Monnier, 2019/01/08
- [elpa] externals/objed 77d1691 157/216: Update extend behavior, Stefan Monnier, 2019/01/08