132 lines
4.9 KiB
EmacsLisp
132 lines
4.9 KiB
EmacsLisp
;;; 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
|