Álvaro Ramírez
Emacs: Clone git repo from clipboard
Cloning git repositories is a pretty common task. For me, it typically goes something like:
- Copy git repo URL from browser.
- Drop to Emacs eshell.
- Change current directory.
- Type "git clone ".
- Paste git repo URL.
- Run git command.
- Change directory to cloned repo.
- Open dired.
No biggie, but why go through the same steps every time? We can do better. We have a hyper malleable editor, so let's get it to grab the URL from clipboard and do its thing.
shell-command or async-shell-command can help in this space, but require additional work: change location, re-type command, what if directory already exists… This is Emacs, so we can craft the exact experience we want. I did take inspiration from shell-command to display the process buffer correctly (git progress, control codes, etc.) and landed on the following experience:
;; -*- lexical-binding: t -*- (defun ar/git-clone-clipboard-url () "Clone git URL in clipboard asynchronously and open in dired when finished." (interactive) (cl-assert (string-match-p "^\\(http\\|https\\|ssh\\)://" (current-kill 0)) nil "No URL in clipboard") (let* ((url (current-kill 0)) (download-dir (expand-file-name "~/Downloads/")) (project-dir (concat (file-name-as-directory download-dir) (file-name-base url))) (default-directory download-dir) (command (format "git clone %s" url)) (buffer (generate-new-buffer (format "*%s*" command))) (proc)) (when (file-exists-p project-dir) (if (y-or-n-p (format "%s exists. delete?" (file-name-base url))) (delete-directory project-dir t) (user-error "Bailed"))) (switch-to-buffer buffer) (setq proc (start-process-shell-command (nth 0 (split-string command)) buffer command)) (with-current-buffer buffer (setq default-directory download-dir) (shell-command-save-pos-or-erase) (require 'shell) (shell-mode) (view-mode +1)) (set-process-sentinel proc (lambda (process state) (let ((output (with-current-buffer (process-buffer process) (buffer-string)))) (kill-buffer (process-buffer process)) (if (= (process-exit-status process) 0) (progn (message "finished: %s" command) (dired project-dir)) (user-error (format "%s\n%s" command output)))))) (set-process-filter proc #'comint-output-filter)))
Updates
- Added lexical binding.
- Checks clipboard for ssh urls also.