2023-07-21 18:10:10 +01:00
|
|
|
;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*-
|
|
|
|
;;
|
2024-02-18 16:08:02 +00:00
|
|
|
;; Copyright (c) 2010-2024 Sameer Rahmani <lxsameer@gnu.org>
|
2023-07-21 18:10:10 +01:00
|
|
|
;;
|
|
|
|
;; Author: Sameer Rahmani <lxsameer@gnu.org>
|
|
|
|
;; URL: https://devheroes.codes/FG42/FG42
|
2024-04-05 21:04:36 +01:00
|
|
|
;; Version: 4.0.0
|
2023-07-21 18:10:10 +01:00
|
|
|
;;
|
|
|
|
;; 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 <http://www.gnu.org/licenses/>.
|
|
|
|
;;
|
|
|
|
;;; Commentary:
|
|
|
|
;; `System' is just a state monad which holds the state of the editor.
|
|
|
|
;; Each system has to have a `start' function to start the setup process.
|
|
|
|
;;
|
|
|
|
;;; Code:
|
|
|
|
(require 'seq)
|
|
|
|
(require 'fg42/utils)
|
|
|
|
|
2023-10-17 10:46:45 +01:00
|
|
|
(fpkg/require 's)
|
|
|
|
|
2023-07-21 18:10:10 +01:00
|
|
|
(defmacro ->commands (&rest body)
|
|
|
|
"Return a list of shell commands in the BODY.
|
|
|
|
|
|
|
|
Each element has to be list like `(cd \"..\")' the command is static but
|
|
|
|
the arguments get evaluated."
|
|
|
|
`(quote
|
|
|
|
,(mapcar
|
|
|
|
(lambda (x)
|
|
|
|
(when (not (listp x))
|
|
|
|
(error "Expect a list. Got %s" x))
|
2023-10-17 10:46:45 +01:00
|
|
|
(let ((command (car x))
|
|
|
|
(args (cdr x)))
|
|
|
|
(cond
|
|
|
|
((string= command "and") (s-join " && " (eval `(->commands ,@args))))
|
|
|
|
((string= command "or") (s-join " || " (eval `(->commands ,@args))))
|
|
|
|
(t (format "%s %s" command (mapconcat #'eval args " "))))))
|
2023-07-21 18:10:10 +01:00
|
|
|
body)))
|
|
|
|
|
2023-10-17 10:46:45 +01:00
|
|
|
|
2023-07-21 18:10:10 +01:00
|
|
|
(defun shell<- (commands &rest opts)
|
|
|
|
"Run the give list of COMMANDS via ssh on HOST with the given OPTS.
|
|
|
|
|
|
|
|
OPTS:
|
|
|
|
- `:shell' The shell to run the commands with. (default /bin/bash)
|
|
|
|
- `:buffer' The buffer name to use. (default '*ssh[SHELL]*')
|
|
|
|
- `:erase?' Whether or not erase the buffer. (default t)"
|
|
|
|
(let* ((sh (or (plist-get opts :shell) "/bin/bash"))
|
|
|
|
(buffer (or (plist-get opts :buffer) (format "*shell[%s]*" sh)))
|
|
|
|
(erase? (or (plist-get opts :erase-buffer?) t))
|
|
|
|
(cmds (format "'%s'" (mapconcat #'identity commands ";")))
|
|
|
|
(output-buffer (get-buffer-create buffer)))
|
|
|
|
|
|
|
|
(when erase?
|
|
|
|
(with-current-buffer output-buffer
|
|
|
|
(setq buffer-read-only nil)
|
|
|
|
(erase-buffer)))
|
|
|
|
(let ((p (start-process-shell-command
|
|
|
|
"shell<-"
|
|
|
|
(buffer-name output-buffer)
|
|
|
|
(format "%s -c %s"
|
|
|
|
sh
|
|
|
|
cmds))))
|
|
|
|
(set-process-sentinel p
|
|
|
|
(lambda (_ event)
|
|
|
|
(when (string= event "finished\n")
|
|
|
|
(message "Commands finished.")
|
|
|
|
;;(kill-process process)
|
|
|
|
))))))
|
|
|
|
|
|
|
|
|
|
|
|
(defun ssh<- (host commands &rest opts)
|
|
|
|
"Run the give list of COMMANDS via ssh on HOST with the given OPTS.
|
|
|
|
|
|
|
|
OPTS:
|
|
|
|
- `:shell' The shell to run the commands with. (default /bin/bash)
|
|
|
|
- `:buffer' The buffer name to use. (default '*ssh[HOST]*')
|
|
|
|
- `:erase?' Whether or not erase the buffer. (default t)"
|
2023-10-17 10:46:45 +01:00
|
|
|
(let* ((sh (or (plist-get opts :shell) "/bin/bash"))
|
|
|
|
(buffer (or (plist-get opts :buffer) (format "*ssh[%s]*" host)))
|
|
|
|
(erase? (or (plist-get opts :erase-buffer?) t))
|
|
|
|
(cmds (format "'%s'" (mapconcat #'identity commands ";")))
|
|
|
|
(output-buffer (get-buffer-create buffer)))
|
2023-07-21 18:10:10 +01:00
|
|
|
|
|
|
|
(when erase?
|
|
|
|
(with-current-buffer output-buffer
|
|
|
|
(setq buffer-read-only nil)
|
|
|
|
(erase-buffer)))
|
|
|
|
|
|
|
|
(let ((p (start-process-shell-command
|
|
|
|
(format "ssh-to-%s" host)
|
|
|
|
(buffer-name output-buffer)
|
|
|
|
(format "ssh -t %s %s -c %s"
|
|
|
|
host
|
|
|
|
sh
|
|
|
|
cmds))))
|
|
|
|
(set-process-sentinel p
|
|
|
|
(lambda (_ event)
|
|
|
|
(when (string= event "finished\n")
|
|
|
|
(message "Commands finished. Closing SSH connection.")
|
|
|
|
;;(kill-process process)
|
2023-10-17 10:46:45 +01:00
|
|
|
))))))
|
2023-07-21 18:10:10 +01:00
|
|
|
|
2023-10-17 10:46:45 +01:00
|
|
|
(provide 'fg42/shell)
|
2024-03-21 19:37:50 +00:00
|
|
|
;;; shell.el ends here
|