Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define whole line comment syntax in Emacs?

I want the sequence // to start a comment when it is at the beginning of a line. But inside of a line it should not start any comments.

// this is a comment
This is a URL: http://example.com

Is it possible?

like image 490
Menschenkindlein Avatar asked Aug 11 '14 14:08

Menschenkindlein


1 Answers

You can do this by writing a syntax-propertize-function

I have written an example major mode that shows this below. Emacs built in parsing will call your syntax-propertize-function so that it can manually set the syntax-table text property on lines starting with //.

(define-derived-mode my-syntax-test-mode fundamental-mode
  "A major mode where // denotes a comment but only if it is at the beginning of a line."
  :syntax-table (make-syntax-table) 
  (setq mode-name "my syntax test")
  ;; our mode will use `apply-my-custom-syntax-table-appropriately' to manually set
  ;; the syntax-table text property on lines starting with //"
  (setq syntax-propertize-function 'apply-my-custom-syntax-table-appropriately)
  ;; change `comment-dwim` to handle this type of comments correctly
  (local-set-key [remap comment-dwim] 'my-comment-dwim))

(defvar my-custom-syntax-table
  ;; syntax table where // starts a comment and \n ends it
  (let ((table (make-syntax-table)))
    (modify-syntax-entry ?/ "< 1" table)
    (modify-syntax-entry ?/ "< 2" table)
    (modify-syntax-entry ?\n "> " table)
    table))

(defun apply-my-custom-syntax-table-appropriately (beg end)
  (save-excursion
    (save-restriction
      (widen)
      (goto-char beg)
      ;; for every line between points BEG and END
      (while (and (not (eobp)) (< (point) end))
        (beginning-of-line)
        ;; if it starts with a //
        (when (looking-at "^//")
          ;; remove current syntax-table property
          (remove-text-properties (1- (line-beginning-position))
                                  (1+ (line-end-position))
                                  '(syntax-table))
          ;; set syntax-table property to our custom one
          ;; for the whole line including the beginning and ending newlines
          (add-text-properties (1- (line-beginning-position))
                               (1+ (line-end-position))
                               (list 'syntax-table my-custom-syntax-table)))
        (forward-line 1)))))

(defun my-comment-dwim (arg)
  (interactive "*P")
  (require 'newcomment)
  (save-excursion
    (let ((comment-start "//") (comment-end "")
          (comment-column 0)
          ;; don't indent comments
          (comment-style 'plain))
      ;; create the region containing current line if there is no active region
      (unless (use-region-p)
        (end-of-line)
        (push-mark (line-beginning-position))
        (setq mark-active t))
      (comment-dwim nil))))
like image 168
Jordon Biondo Avatar answered Oct 28 '22 15:10

Jordon Biondo