Last active
November 4, 2023 19:09
-
-
Save amno1/ee649f9e3c11566678d67125ef730444 to your computer and use it in GitHub Desktop.
Use Bash aliases in interactive shell-comands
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; shell-command-with-aliases.el --- Use Bash aliases in interactive shell-comands -*- lexical-binding: t; -*- | |
;; Copyright (C) 2023 Arthur Miller | |
;; Author: Arthur Miller <[email protected]> | |
;; Keywords: | |
;; This program is free software; you can redistribute it and/or modify | |
;; it under the terms of the GNU General Public License as published by | |
;; the Free Software Foundation, either version 3 of the License, or | |
;; (at your option) any later version. | |
;; This program is distributed in the hope that it will be useful, | |
;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
;; GNU General Public License for more details. | |
;; You should have received a copy of the GNU General Public License | |
;; along with this program. If not, see <https://www.gnu.org/licenses/>. | |
;;; Commentary: | |
;; Bind shell-command-with-aliases to M-! as the replacement for shell-command | |
;;; Code: | |
(defgroup shell-command nil | |
"Shell-command that understands Bash aliases" | |
:group 'tools) | |
(defvar bash-alias-table (make-hash-table :test 'equal) | |
"Table containg names and values for Bash aliases.") | |
(defvar bash-alias-file | |
(expand-file-name "etc/bash-alias-table" user-emacs-directory) | |
"Serialize Bash aliases to this file.") | |
(defun bash-aliases () | |
"Obtain list of bash aliases for the current user." | |
(interactive) | |
(let ((shell-command-switch "-ic") beg) | |
(with-temp-buffer | |
(shell-command "alias" t) | |
(goto-char 1) | |
(switch-to-buffer (current-buffer)) | |
(while (search-forward "alias" nil t) | |
(setq beg (point)) | |
(search-forward "=" (line-end-position)) ;; this has to succeed | |
(replace-match " ") | |
(let ((name (string-trim (buffer-substring-no-properties | |
beg (1- (point))))) | |
(beg (1+ (point)))) | |
(while (and (char-after) | |
(/= (char-before) ?\') | |
(/= (char-before) ?\")) | |
(forward-char)) | |
(goto-char (line-end-position)) | |
(while (and (char-before) | |
(/= (char-before) ?\') | |
(/= (char-before) ?\")) | |
(backward-char)) | |
(puthash name (buffer-substring-no-properties beg (1- (point))) | |
bash-alias-table))) | |
(erase-buffer) | |
(prin1 bash-alias-table (current-buffer)) | |
(write-region (point-min) (point-max) bash-alias-file)))) | |
(defun bash-command-from-alias (cmd) | |
"Convert a command in CMD with alias into real command name." | |
(with-temp-buffer | |
(insert cmd) | |
(goto-char 1) | |
(let ((alias (gethash (current-word) bash-alias-table))) | |
(if (not alias) | |
cmd | |
(delete-region 1 (length cmd)) | |
(insert alias) | |
(buffer-substring-no-properties (point-min) (point-max)))))) | |
;;;###autoload | |
(defun async-shell-command-with-aliases () | |
"Like `shell-command' but understands Bash aliases." | |
(interactive) | |
(let ((args (eval (cadr (interactive-form 'shell-command))))) | |
(apply #'async-shell-command (bash-command-from-alias (pop args)) args))) | |
;;;###autoload | |
(defun shell-command-with-aliases () | |
"Like `shell-command' but understands Bash aliases." | |
(interactive) | |
(let ((args (eval (cadr (interactive-form 'shell-command))))) | |
(apply #'shell-command (bash-command-from-alias (pop args)) args))) | |
(defvar bash-alias-mode-map | |
(let ((map (make-sparse-keymap))) | |
(define-key map [remap shell-command] #'shell-command-with-aliases) | |
(define-key map [remap async-shell-command] #'async-shell-command-with-aliases) | |
map)) | |
;;;###autoload | |
(define-minor-mode bash-alias-mode | |
"Enable Bash aliases in shell-command and async-shell-command" | |
:global t :lighter " alias") | |
(progn ;; init the table | |
(unless (file-exists-p bash-alias-file) | |
(bash-aliases)) | |
(with-temp-buffer | |
(insert-file-contents bash-alias-file) | |
(setq bash-alias-table (read (current-buffer))))) | |
(provide 'shell-command-with-aliases) | |
;;; shell-command-with-aliases.el ends here |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment