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

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

[nongnu] elpa/crux 12c4901 001/112: Initial commit


From: ELPA Syncer
Subject: [nongnu] elpa/crux 12c4901 001/112: Initial commit
Date: Wed, 11 Aug 2021 09:57:42 -0400 (EDT)

branch: elpa/crux
commit 12c4901d85813a5308767fda5d46507e7ce68078
Author: Bozhidar Batsov <bozhidar@batsov.com>
Commit: Bozhidar Batsov <bozhidar@batsov.com>

    Initial commit
---
 README.md |  85 ++++++++++++++
 crux.el   | 373 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 458 insertions(+)

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d64dc89
--- /dev/null
+++ b/README.md
@@ -0,0 +1,85 @@
+[![License GPL 3][badge-license]][copying]
+[![MELPA][melpa-badge]][melpa-package]
+[![MELPA Stable][melpa-stable-badge]][melpa-stable-package]
+
+# crux
+
+A **C**ollection of **R**idiculously **U**seful e**X**tensions for Emacs.
+crux bundles a few useful interactive commands to enhance your
+overall Emacs experience.
+
+## Installation
+
+Available on all major `package.el` community maintained repos -
+[MELPA Stable][] and [MELPA][] repos.
+
+MELPA Stable is recommended as it has the latest stable version.
+MELPA has a development snapshot for users who don't mind breakage but
+don't want to run from a git checkout.
+
+You can install `crux` using the following command:
+
+<kbd>M-x package-install [RET] crux [RET]</kbd>
+
+or if you'd rather keep it in your dotfiles:
+
+```el
+(unless (package-installed-p 'crux)
+  (package-refresh-contents)
+  (package-install 'crux))
+```
+
+If the installation doesn't work try refreshing the package list:
+
+<kbd>M-x package-refresh-contents</kbd>
+
+Add the following to your Emacs config to enable
+`crux`:
+
+```el
+(crux-setup-default-keybindings)
+```
+
+## Keybindings
+
+Here's the list of the default keybindings. Feel free to bind
+individual commands to whatever keybindings you prefer.
+
+Keybinding         | Description
+-------------------|------------------------------------------------------------
+<kbd>C-c o</kbd>   | Open the currently visited file with an external program.
+<kbd>C-S-RET</kbd> or <kbd>Super-o</kbd> | Insert an empty line above the 
current line and indent it properly.
+<kbd>S-RET</kbd> or <kbd>M-o</kbd> | Insert an empty line and indent it 
properly (as in most IDEs).
+<kbd>C-c n</kbd> | Fix indentation in buffer and strip whitespace.
+<kbd>C-c f</kbd> | Open recently visited file.
+<kbd>C-M-\\</kbd> | Indent region (if selected) or the entire buffer.
+<kbd>C-c u</kbd> | Open a new buffer containing the contents of URL.
+<kbd>C-c e</kbd> | Eval a bit of Emacs Lisp code and replace it with its 
result.
+<kbd>C-c s</kbd> | Swap two active windows.
+<kbd>C-c D</kbd> | Delete current file and buffer.
+<kbd>C-c r</kbd> | Rename the current buffer and its visiting file if any.
+<kbd>C-c t</kbd> | Open a terminal emulator (`ansi-term`).
+<kbd>C-c k</kbd> | Kill all open buffers except the one you're currently in.
+<kbd>C-c TAB</kbd> | Indent and copy region to clipboard
+<kbd>C-c I</kbd> | Open user's init file.
+<kbd>C-c S</kbd> | Open shell's init file.
+<kbd>Super-r</kbd> | Recent files
+<kbd>Super-j</kbd> | Join lines
+<kbd>Super-k</kbd> | Kill whole line
+<kbd>C-Backspace</kbd> | Kill line backwards
+
+## License
+
+Copyright © 2015 Bozhidar Batsov and [contributors][].
+
+Distributed under the GNU General Public License; type <kbd>C-h C-c</kbd> to 
view it.
+
+[badge-license]: https://img.shields.io/badge/license-GPL_3-green.svg
+[melpa-badge]: http://melpa.org/packages/crux-badge.svg
+[melpa-stable-badge]: http://stable.melpa.org/packages/crux-badge.svg
+[melpa-package]: http://melpa.org/#/crux
+[melpa-stable-package]: http://stable.melpa.org/#/crux
+[COPYING]: http://www.gnu.org/copyleft/gpl.html
+[contributors]: https://github.com/clojure-emacs/crux/contributors
+[melpa]: http://melpa.org
+[melpa stable]: http://stable.melpa.org
diff --git a/crux.el b/crux.el
new file mode 100644
index 0000000..95b299a
--- /dev/null
+++ b/crux.el
@@ -0,0 +1,373 @@
+;;; crux --- A Collection of Ridiculously Useful eXtensions.
+;;
+;; Copyright © 2015 Bozhidar Batsov
+;;
+;; Author: Bozhidar Batsov <bozhidar@batsov.com>
+;; URL: https://github.com/bbatsov/crux
+;; Version: 0.1.0
+;; Keywords: convenience
+;; Package-Requires: ((seq "1.11"))
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; A cornucopia of useful interactive commands to make your Emacs
+;; experience more enjoyable.
+
+;;; License:
+
+;; 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 GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Code:
+
+(require 'thingatpt)
+(require 'seq)
+
+(defun crux-open-with (arg)
+  "Open visited file in default external program.
+When in dired mode, open file under the cursor.
+
+With a prefix ARG always prompt for command to use."
+  (interactive "P")
+  (let* ((current-file-name
+          (if (eq major-mode 'dired-mode)
+              (dired-get-file-for-visit)
+            buffer-file-name))
+         (open (pcase system-type
+                 (`darwin "open")
+                 ((or `gnu `gnu/linux `gnu/kfreebsd) "xdg-open")))
+         (program (if (or arg (not open))
+                      (read-shell-command "Open current file with: ")
+                    open)))
+    (start-process "crux-open-with-process" nil program current-file-name)))
+
+(defun crux-buffer-mode (buffer-or-name)
+  "Retrieve the `major-mode' of BUFFER-OR-NAME."
+  (with-current-buffer buffer-or-name
+    major-mode))
+
+(defvar crux-term-buffer-name "ansi"
+  "The default `ansi-term' name used by `crux-visit-term-buffer'.
+This variable can be set via .dir-locals.el to provide multi-term support.")
+
+(defun crux-visit-term-buffer ()
+  "Create or visit a terminal buffer."
+  (interactive)
+  (crux-start-or-switch-to (lambda ()
+                                (ansi-term crux-shell (concat 
crux-term-buffer-name "-term")))
+                              (format "*%s-term*" crux-term-buffer-name)))
+
+(defun crux-indent-rigidly-and-copy-to-clipboard (begin end arg)
+  "Indent region between BEGIN and END by ARG columns and copy to clipboard."
+  (interactive "r\nP")
+  (let ((arg (or arg 4))
+        (buffer (current-buffer)))
+    (with-temp-buffer
+      (insert-buffer-substring-no-properties buffer begin end)
+      (indent-rigidly (point-min) (point-max) arg)
+      (clipboard-kill-ring-save (point-min) (point-max)))))
+
+(defun crux-smart-open-line-above ()
+  "Insert an empty line above the current line.
+Position the cursor at it's beginning, according to the current mode."
+  (interactive)
+  (move-beginning-of-line nil)
+  (newline-and-indent)
+  (forward-line -1)
+  (indent-according-to-mode))
+
+(defun crux-smart-open-line (arg)
+  "Insert an empty line after the current line.
+Position the cursor at its beginning, according to the current mode.
+
+With a prefix ARG open line above the current line."
+  (interactive "P")
+  (if arg
+      (crux-smart-open-line-above)
+    (progn
+      (move-end-of-line nil)
+      (newline-and-indent))))
+
+(defun crux-top-join-line ()
+  "Join the current line with the line beneath it."
+  (interactive)
+  (delete-indentation 1))
+
+(defun crux-kill-whole-line (&optional arg)
+  "A simple wrapper around command `kill-whole-line' that respects indentation.
+Passes ARG to command `kill-whole-line' when provided."
+  (interactive "p")
+  (kill-whole-line arg)
+  (back-to-indentation))
+
+(defun crux-kill-like-backwards ()
+  "Kill line backwards and adjust the indentation."
+  (interactive)
+  (kill-line 0)
+  (indent-according-to-mode))
+
+(defun crux-move-beginning-of-line (arg)
+  "Move point back to indentation of beginning of line.
+
+Move point to the first non-whitespace character on this line.
+If point is already there, move to the beginning of the line.
+Effectively toggle between the first non-whitespace character and
+the beginning of the line.
+
+If ARG is not nil or 1, move forward ARG - 1 lines first.  If
+point reaches the beginning or end of the buffer, stop there."
+  (interactive "^p")
+  (setq arg (or arg 1))
+
+  ;; Move lines first
+  (when (/= arg 1)
+    (let ((line-move-visual nil))
+      (forward-line (1- arg))))
+
+  (let ((orig-point (point)))
+    (back-to-indentation)
+    (when (= orig-point (point))
+      (move-beginning-of-line 1))))
+
+(defun crux-indent-defun ()
+  "Indent the current defun."
+  (interactive)
+  (save-excursion
+    (mark-defun)
+    (indent-region (region-beginning) (region-end))))
+
+(defun crux-get-positions-of-line-or-region ()
+  "Return positions (beg . end) of the current line
+or region."
+  (let (beg end)
+    (if (and mark-active (> (point) (mark)))
+        (exchange-point-and-mark))
+    (setq beg (line-beginning-position))
+    (if mark-active
+        (exchange-point-and-mark))
+    (setq end (line-end-position))
+    (cons beg end)))
+
+(defun crux-rename-buffer-and-file ()
+  "Rename current buffer and if the buffer is visiting a file, rename it too."
+  (interactive)
+  (let ((filename (buffer-file-name)))
+    (if (not (and filename (file-exists-p filename)))
+        (rename-buffer (read-from-minibuffer "New name: " (buffer-name)))
+      (let ((new-name (read-file-name "New name: " filename)))
+        (cond
+         ((vc-backend filename) (vc-rename-file filename new-name))
+         (t
+          (rename-file filename new-name t)
+          (set-visited-file-name new-name t t)))))))
+
+(defun crux-delete-file-and-buffer ()
+  "Kill the current buffer and deletes the file it is visiting."
+  (interactive)
+  (let ((filename (buffer-file-name)))
+    (when filename
+      (if (vc-backend filename)
+          (vc-delete-file filename)
+        (when (y-or-n-p (format "Are you sure you want to delete %s? " 
filename))
+          (delete-file filename delete-by-moving-to-trash)
+          (message "Deleted file %s" filename)
+          (kill-buffer))))))
+
+(defun crux-view-url ()
+  "Open a new buffer containing the contents of URL."
+  (interactive)
+  (let* ((default (thing-at-point-url-at-point))
+         (url (read-from-minibuffer "URL: " default)))
+    (switch-to-buffer (url-retrieve-synchronously url))
+    (rename-buffer url t)
+    (goto-char (point-min))
+    (re-search-forward "^$")
+    (delete-region (point-min) (point))
+    (delete-blank-lines)
+    (set-auto-mode)))
+
+(defun crux-cleanup-buffer-or-region ()
+  "Cleanup a region if selected, otherwise the whole buffer."
+  (interactive)
+  (call-interactively 'untabify)
+  (unless (member major-mode crux-indent-sensitive-modes)
+    (call-interactively 'indent-region))
+  (whitespace-cleanup))
+
+(defun crux-eval-and-replace ()
+  "Replace the preceding sexp with its value."
+  (interactive)
+  (let ((value (eval (preceding-sexp))))
+    (backward-kill-sexp)
+    (insert (format "%s" value))))
+
+(defun crux-recompile-init ()
+  "Byte-compile all your dotfiles again."
+  (interactive)
+  (byte-recompile-directory crux-dir 0))
+
+(defun crux-file-owner-uid (filename)
+  "Return the UID of the FILENAME as an integer.
+
+See `file-attributes' for more info."
+  (nth 2 (file-attributes filename 'integer)))
+
+(defun crux-file-owned-by-user-p (filename)
+  "Return t if file FILENAME is owned by the currently logged in user."
+  (equal (crux-file-owner-uid filename)
+         (user-uid)))
+
+(defun crux-find-alternate-file-as-root (filename)
+  "Wraps `find-alternate-file' with opening a file as root."
+  (find-alternate-file (concat "/sudo:root@localhost:" filename)))
+
+(require 'ido)
+(defun crux-sudo-edit (&optional arg)
+  "Edit currently visited file as root.
+
+With a prefix ARG prompt for a file to visit.
+Will also prompt for a file to visit if current
+buffer is not visiting a file."
+  (interactive "P")
+  (if (or arg (not buffer-file-name))
+      (find-file (concat "/sudo:root@localhost:"
+                         (ido-read-file-name "Find file(as root): ")))
+    (crux-find-alternate-file-as-root buffer-file-name)))
+
+(defun crux-reopen-as-root ()
+  "Find file as root if necessary."
+  (unless (or (tramp-tramp-file-p buffer-file-name)
+              (equal major-mode 'dired-mode)
+              (not (file-exists-p (file-name-directory buffer-file-name)))
+              (file-writable-p buffer-file-name)
+              (crux-file-owned-by-user-p buffer-file-name))
+    (crux-find-alternate-file-as-root buffer-file-name)))
+(add-hook 'find-file-hook 'crux-reopen-as-root)
+
+(defun crux-start-or-switch-to (function buffer-name)
+  "Invoke FUNCTION if there is no buffer with BUFFER-NAME.
+Otherwise switch to the buffer named BUFFER-NAME.  Don't clobber
+the current buffer."
+  (if (not (get-buffer buffer-name))
+      (progn
+        (split-window-sensibly (selected-window))
+        (other-window 1)
+        (funcall function))
+    (switch-to-buffer-other-window buffer-name)))
+
+(defun crux-insert-date ()
+  "Insert a timestamp according to locale's date and time format."
+  (interactive)
+  (insert (format-time-string "%c" (current-time))))
+
+(defun crux-recentf-ido-find-file ()
+  "Find a recent file using ido."
+  (interactive)
+  (let ((file (ido-completing-read "Choose recent file: "
+                                   (mapcar #'abbreviate-file-name recentf-list)
+                                   nil t)))
+    (when file
+      (find-file file))))
+
+(defun crux-swap-windows ()
+  "If you have 2 windows, it swaps them."
+  (interactive)
+  (if (/= (count-windows) 2)
+      (message "You need exactly 2 windows to do this.")
+    (let* ((w1 (car (window-list)))
+           (w2 (cadr (window-list)))
+           (b1 (window-buffer w1))
+           (b2 (window-buffer w2))
+           (s1 (window-start w1))
+           (s2 (window-start w2)))
+      (set-window-buffer w1 b2)
+      (set-window-buffer w2 b1)
+      (set-window-start w1 s2)
+      (set-window-start w2 s1)))
+  (other-window 1))
+
+(defun crux-switch-to-previous-buffer ()
+  "Switch to previously open buffer.
+Repeated invocations toggle between the two most recently open buffers."
+  (interactive)
+  (switch-to-buffer (other-buffer (current-buffer) 1)))
+
+(defun crux-kill-other-buffers ()
+  "Kill all buffers but the current one.
+Doesn't mess with special buffers."
+  (interactive)
+  (when (y-or-n-p "Are you sure you want to kill all buffers but the current 
one? ")
+    (seq-each
+     #'kill-buffer
+     (delete (current-buffer) (seq-filter #'buffer-file-name (buffer-list))))))
+
+(defun crux-create-scratch-buffer ()
+  "Create a new scratch buffer."
+  (interactive)
+  (let ((buf (generate-new-buffer "*scratch*")))
+    (switch-to-buffer buf)
+    (funcall initial-major-mode)))
+
+(defun crux-find-user-init-file ()
+  "Edit the `user-init-file', in another window."
+  (interactive "P")
+  (find-file-other-window user-init-file)
+  )
+
+(defun crux-find-shell-init-file ()
+  "Edit the shell init file in another window."
+  (interactive)
+  (let* ((shell (car (reverse (split-string (getenv "SHELL") "/" t))))
+         (shell-init-file (cond
+                           ((string= "zsh" shell) ".zshrc")
+                           ((string= "bash" shell) ".bashrc")
+                           (t (error "Unknown shell")))))
+    (find-file-other-window (expand-file-name shell-init-file (getenv 
"HOME")))))
+
+;;;###autoload
+(defun crux-setup-default-keybindings ()
+  "Set the recommended global keybindings for crux's commands."
+  (interactive)
+  (global-set-key [remap move-beginning-of-line] #'crux-move-beginning-of-line)
+  (global-set-key (kbd "C-c o") #'crux-open-with)
+  ;; mimic popular IDEs binding, note that it doesn't work in a terminal 
session
+  (global-set-key [(shift return)] #'crux-smart-open-line)
+  (global-set-key (kbd "M-o") #'crux-smart-open-line)
+  (global-set-key [(control shift return)] #'crux-smart-open-line-above)
+  (global-set-key (kbd "C-c n") #'crux-cleanup-buffer-or-region)
+  (global-set-key (kbd "C-c f")  #'crux-recentf-ido-find-file)
+  (global-set-key (kbd "C-M-z") #'crux-indent-defun)
+  (global-set-key (kbd "C-c u") #'crux-view-url)
+  (global-set-key (kbd "C-c e") #'crux-eval-and-replace)
+  (global-set-key (kbd "C-c s") #'crux-swap-windows)
+  (global-set-key (kbd "C-c D") #'crux-delete-file-and-buffer)
+  (global-set-key (kbd "C-c r") #'crux-rename-buffer-and-file)
+  (global-set-key (kbd "C-c t") #'crux-visit-term-buffer)
+  (global-set-key (kbd "C-c k") #'crux-kill-other-buffers)
+  (global-set-key (kbd "C-c TAB") #'crux-indent-rigidly-and-copy-to-clipboard)
+  (global-set-key (kbd "C-c I") #'crux-find-user-init-file)
+  (global-set-key (kbd "C-c S") #'crux-find-shell-init-file)
+  (global-set-key (kbd "s-r") #'crux-recentf-ido-find-file)
+  (global-set-key (kbd "s-j") #'crux-top-join-line)
+  (global-set-key (kbd "C-^") #'crux-top-join-line)
+  (global-set-key (kbd "s-k") #'crux-kill-whole-line)
+  (global-set-key (kbd "C-<backspace>" #'crux-kill-line-backwards))
+  (global-set-key (kbd "s-o") #'crux-smart-open-line-above)
+  (global-set-key [remap kill-whole-line] #'crux-kill-whole-line))
+
+(provide 'crux)
+;;; crux.el ends here



reply via email to

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