From e681fa8b1263a1d53cc565b4ab85537f9ca37b49 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Tue, 12 Apr 2022 02:19:05 +0200 Subject: [PATCH] Create a repo for box-comment --- packages.el | 2 + repos/x-lib/box-comment.el | 131 +++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 repos/x-lib/box-comment.el diff --git a/packages.el b/packages.el index 755c755..74d87c4 100644 --- a/packages.el +++ b/packages.el @@ -10,6 +10,8 @@ ;;(package! some-package) (package! ace-jump-mode :recipe (:local-repo "repos/ace-jump-mode")) +(package! box-comment + :recipe (:local-repo "repos/x-lib")) (package! deadgrep) (package! duplicate-thing) (package! treemacs-icons-dired) diff --git a/repos/x-lib/box-comment.el b/repos/x-lib/box-comment.el new file mode 100644 index 0000000..ba776d9 --- /dev/null +++ b/repos/x-lib/box-comment.el @@ -0,0 +1,131 @@ +;;; box-comment.el -*- lexical-binding: t -*- + +;; +;;; Variables: + +(defvar box-comment--comment-start-emacs-lisp-mode ";; " + "String to begin comment lines in `emacs-lisp-mode'.") + +(defvar box-comment--comment-start-lisp-interaction-mode ";; " + "String to begin comment lines in `list-interaction-mode'.") + +(defvar box-comment--comment-start-scheme-mode ";; " + "String to begin comment lines in `scheme-mode'.") + +;; +;;; Code: + +(defun +x-box-comment--comment-start () + "Get the string that starts box comments for the current mode." + (let ((box-comment-var + (intern (format "box-comment--comment-start-%s" major-mode)))) + (string-trim-right (if (boundp box-comment-var) + (eval box-comment-var) + comment-start) + "[[:space:]]"))) + +(defun +x-box-comment--box-comment-line-p (box-comment-start) + "Return t if point is in a line suitable for box comments." + (save-excursion + (end-of-line) + (search-backward (string-trim-right box-comment-start "[[:space:]]") + (line-beginning-position) + t))) + +(defun +x-box-comment--box-comment-boundary-p (box-comment-start) + "Return non-nil if point is in a box comment boundary line." + (save-excursion + (if (/= (- (line-end-position) (line-beginning-position)) fill-column) + nil + (end-of-line) + (re-search-backward (format "^[[:space:]]*%s -+$" box-comment-start) + (line-beginning-position) + t)))) + +(defun +x-box-comment--insert-box-boundary (box-comment-start indent len) + "Insert a box comment boundary line." + (indent-line-to indent) + (insert box-comment-start " " (make-string len ?-))) + +(defun +x-box-comment--re-search (re beg end) + "Return non-nil if RE is between BEG and END." + (save-excursion + (goto-char beg) + (re-search-forward re end t))) + +;;;###autoload +(defun +x-box-comment/box-comment () + "Format the comment at point into a box comment. + +If the comment at point is already a box comment, this command +will update and fix the box comment format (if necessary)." + (interactive) + (let ((box-comment-start (+x-box-comment--comment-start)) + (use-region (use-region-p)) + offset region-len indent len) + + ;; If we are not in a comment, create a comment. + (unless (+x-box-comment--box-comment-line-p box-comment-start) + (if (and (not use-region) + (+x-box-comment--re-search "^[[:space:]]*$" + (line-beginning-position) + (line-end-position))) + (comment-dwim nil) + (comment-line nil) + ;; `comment-line' behaves differently whether its invoked on a region or + ;; not. In a region, the point ends up within the comment, unless the + ;; region ended on an empty line in which case the point ends up on the + ;; next line. Outside of a region, the point ends up on the next line. + (if use-region + (progn + (unless (or (+x-box-comment--box-comment-line-p box-comment-start) + (not (+x-box-comment--re-search box-comment-start + (region-beginning) + (region-end)))) + (forward-line -1)) + (end-of-line) + (setq region-len (- (region-end) (region-beginning)))) + (forward-line -1) + (end-of-line)))) + + (save-excursion + (end-of-line) + (when (search-backward box-comment-start (line-beginning-position) t) + + ;; Get the variables. + (setq indent (current-column)) + (setq len (- (- fill-column (+ (length box-comment-start) 1)) indent)) + + ;; Find the first line. + (if use-region + (progn + (goto-char (region-beginning)) + (setq offset (- (current-column) indent))) + (while (+x-box-comment--box-comment-line-p box-comment-start) + (forward-line -1)) + (forward-line +1)) + + ;; If not a box comment boundary, insert it. + (unless (+x-box-comment--box-comment-boundary-p box-comment-start) + (beginning-of-line) + (+x-box-comment--insert-box-boundary box-comment-start indent len) + (newline) + (indent-line-to indent)) + + ;; Now find the last line + (if use-region + (forward-char (+ offset region-len)) + (while (+x-box-comment--box-comment-line-p box-comment-start) + (forward-line +1)) + (forward-line -1)) + + ;; If not a box comment boundary, insert it. + (unless (+x-box-comment--box-comment-boundary-p box-comment-start) + (end-of-line) + (newline) + (+x-box-comment--insert-box-boundary box-comment-start + indent + len)))))) + +(provide 'box-comment) +;;; box-comment.el ends here