summaryrefslogtreecommitdiff
path: root/modules/custom-file-buffer.el
diff options
context:
space:
mode:
Diffstat (limited to 'modules/custom-file-buffer.el')
-rw-r--r--modules/custom-file-buffer.el148
1 files changed, 148 insertions, 0 deletions
diff --git a/modules/custom-file-buffer.el b/modules/custom-file-buffer.el
new file mode 100644
index 00000000..2918ed97
--- /dev/null
+++ b/modules/custom-file-buffer.el
@@ -0,0 +1,148 @@
+;;; custom-file-buffer.el --- Custom Buffer and File Operations -*- coding: utf-8; lexical-binding: t; -*-
+
+;;; Commentary:
+;;
+
+;;; Code:
+
+;; ------------------------- Buffer And File Operations ------------------------
+
+(defun cj/move-buffer-and-file (dir)
+ "Move both current buffer and the file it visits to DIR."
+ (interactive "DMove buffer and file (to new directory): ")
+ (let* ((name (buffer-name))
+ (filename (buffer-file-name))
+ (dir
+ (if (string-match dir "\\(?:/\\|\\\\)$")
+ (substring dir 0 -1) dir))
+ (newname (concat dir "/" name)))
+ (if (not filename)
+ (message "Buffer '%s' is not visiting a file!" name)
+ (progn (copy-file filename newname 1) (delete-file filename)
+ (set-visited-file-name newname) (set-buffer-modified-p nil) t))))
+
+(defun cj/rename-buffer-and-file (new-name)
+ "Rename both current buffer and the file it visits to NEW-NAME."
+ (interactive
+ (list (if (not (buffer-file-name))
+ (user-error "Buffer '%s' is not visiting a file!" (buffer-name))
+ (read-string "Rename buffer and file (to new name): "
+ (file-name-nondirectory (buffer-file-name))))))
+ (let ((name (buffer-name))
+ (filename (buffer-file-name)))
+ (if (get-buffer new-name)
+ (message "A buffer named '%s' already exists!" new-name)
+ (progn
+ (rename-file filename new-name 1)
+ (rename-buffer new-name)
+ (set-visited-file-name new-name)
+ (set-buffer-modified-p nil)))))
+
+(defun cj/delete-buffer-and-file ()
+ "Kill the current buffer and delete the file it visits."
+ (interactive)
+ (let ((filename (buffer-file-name)))
+ (when filename
+ (if (vc-backend filename)
+ (vc-delete-file filename)
+ (progn
+ (delete-file filename t)
+ (message "Deleted file %s" filename)
+ (kill-buffer))))))
+
+(defun cj/copy-link-to-buffer-file ()
+ "Copy the full file:// path of the current buffer's source file to the kill ring."
+ (interactive)
+ (let ((file-path (buffer-file-name)))
+ (when file-path
+ (setq file-path (concat "file://" file-path))
+ (kill-new file-path)
+ (message "Copied file link to kill ring: %s" file-path))))
+
+(defun cj/copy-path-to-buffer-file-as-kill ()
+ "Copy the full path of the current buffer's file to the kill ring.
+Signal an error if the buffer is not visiting a file."
+ (interactive)
+ (let ((path (buffer-file-name)))
+ (if (not path)
+ (user-error "Current buffer is not visiting a file")
+ (kill-new path)
+ (message "Copied file path: %s" path)
+ path)))
+
+(defun cj/copy-whole-buffer ()
+ "Copy the entire contents of the current buffer to the kill ring.
+Point and mark are left exactly where they were. No transient region
+is created. A message is displayed when done."
+ (interactive)
+ (let ((contents (buffer-substring-no-properties (point-min) (point-max))))
+ (kill-new contents)
+ (message "Buffer contents copied to kill ring")))
+
+(defun cj/clear-to-bottom-of-buffer ()
+ "Delete all text from point to the end of the current buffer.
+This does not save the deleted text in the kill ring."
+ (interactive)
+ (delete-region (point) (point-max))
+ (message "Buffer contents removed to the end of the buffer."))
+
+(defun cj/clear-to-top-of-buffer ()
+ "Delete all text from point to the beginning of the current buffer.
+Do not save the deleted text in the kill ring."
+ (interactive)
+ (delete-region (point) (point-min))
+ (message "Buffer contents removed to the beginning of the buffer."))
+
+
+
+;; ------------------------- Print Buffer As Postscript ------------------------
+
+;; prints using postscript for much nicer output
+(use-package ps-print
+ :ensure nil ;; built-in
+ :config
+ (defun cj/print-buffer-ps ()
+ "Print the current buffer as PostScript (monochrome) to the system default printer.
+Sends directly to the spooler (no temp files), with no page header."
+ (interactive)
+ (let* ((spooler
+ (cond
+ ((executable-find "lpr") "lpr")
+ ((executable-find "lp") "lp")
+ (t (user-error "Cannot print: neither 'lpr' nor 'lp' found in PATH"))))
+ ;; Configure spooler for this invocation
+ (ps-lpr-command spooler)
+ (ps-printer-name nil) ;; nil => system default printer
+ (ps-lpr-switches nil)
+ ;; Force monochrome and ignore face backgrounds for this job
+ (ps-print-color-p nil)
+ (ps-use-face-background nil)
+ ;; Ensure no headers
+ (ps-print-header nil)
+ (ps-header-lines 0)
+ (ps-left-header nil)
+ (ps-right-header nil))
+ (ps-print-buffer-with-faces)
+ (message "Sent print job via %s to default printer (no header)" spooler))))
+
+;; --------------------------- Buffer And File Keymap --------------------------
+
+;; Buffer & file operations prefix and keymap
+(define-prefix-command 'cj/buffer-and-file-map nil
+ "Keymap for buffer-and-file operations.")
+(define-key cj/custom-keymap "b" 'cj/buffer-and-file-map)
+(define-key cj/buffer-and-file-map "m" 'cj/move-buffer-and-file)
+(define-key cj/buffer-and-file-map "r" 'cj/rename-buffer-and-file)
+(define-key cj/buffer-and-file-map "p" 'cj/print-buffer-ps)
+(define-key cj/buffer-and-file-map "d" 'cj/delete-buffer-and-file)
+(define-key cj/buffer-and-file-map "c" 'cj/copy-whole-buffer)
+(define-key cj/buffer-and-file-map "t" 'cj/clear-to-top-of-buffer)
+(define-key cj/buffer-and-file-map "b" 'cj/clear-to-bottom-of-buffer)
+(define-key cj/buffer-and-file-map "x" 'erase-buffer)
+(define-key cj/buffer-and-file-map "s" 'write-file) ;; save as :)
+
+(define-key cj/buffer-and-file-map "l" 'cj/copy-link-to-buffer-file)
+(define-key cj/buffer-and-file-map "P" 'cj/copy-path-to-buffer-file-as-kill)
+
+(provide 'custom-file-buffer)
+;;; custom-file-buffer.el ends here.