From bf53c657a891de6d13612530567c6969c2c340c1 Mon Sep 17 00:00:00 2001 From: Alexander Rosenberg Date: Sat, 15 Nov 2025 02:33:11 -0800 Subject: [PATCH] Better C-style indentation --- elisp/c-comments.el | 64 ++++++++++++++++++++++++++++++++++++++++ init.el | 71 +++++++++++++++++++++++++-------------------- 2 files changed, 103 insertions(+), 32 deletions(-) create mode 100644 elisp/c-comments.el diff --git a/elisp/c-comments.el b/elisp/c-comments.el new file mode 100644 index 0000000..d73b60f --- /dev/null +++ b/elisp/c-comments.el @@ -0,0 +1,64 @@ +;;; c-comments.el --- Functions for working with C-style comments.-*- lexical-binding: t -*- +;;; Commentary: +;;; Code: + +(defun c-comments-bounds-at-point () + "Return the bounds of the multi-line comment around point." + (let* ((syntax-info (syntax-ppss)) + (in-comment (nth 4 syntax-info)) + (is-multiline (and in-comment + (not (nth 7 syntax-info))))) + (cond + (is-multiline + (let ((start (save-excursion + (end-of-line) + (search-backward "/*" nil t))) + (end (save-excursion + (beginning-of-line) + (search-forward "*/" nil t)))) + (when (and start + (>= (point) start) + (or (not end) + (<= (point) (- end 2)))) + (cons start end)))) + (in-comment + (let ((start (save-excursion + (beginning-of-line) + (search-forward "//" (pos-eol) t)))) + (and (>= (point) start) + (cons start (pos-eol)))))))) +(defun c-comments--need-comment-terminator (bounds) + "Return non-nil if a comment terminator needs to be inserted given BOUNDS." + (and (or (not (cdr bounds)) + (save-excursion + (search-forward "/*" (cdr bounds) t))))) +(defun c-comments-newline (&optional arg always-continue) + "Insert ARG newlines and indent, automatically closing multi-line comments. +Also, insert \"* \" at the beginning of every line when executed from inside a +multi-line comment. If ALWAYS-CONTINUE is true, also insert \"//\" if called +from inside a C++-style single-line comment." + (interactive "*Pi") + (when (and arg (< (prefix-numeric-value arg) 0)) + (user-error "Count cannot be negative")) + (if-let ((bounds (c-comments-bounds-at-point)) + ((or always-continue (not (nth 7 (syntax-ppss)))))) + (progn + (when (c-comments--need-comment-terminator bounds) + (save-excursion + (insert "\n*/") + (indent-region (pos-bol) (pos-eol)))) + (dotimes (_ (prefix-numeric-value arg)) + (default-indent-new-line)) + (when (save-excursion + (forward-char -1) + (looking-at-p (regexp-opt '("*" "/")))) + (insert " "))) + (newline arg t))) +(defun c-comments-newline-always-continue (&optional arg) + "Like calling `c-comments-newline', but always continue comments. +That is, this is equivalent to (c-comments-newline ARG t)." + (interactive "*P") + (c-comments-newline arg t)) + +(provide 'c-comments) +;;; c-comments.el ends here diff --git a/init.el b/init.el index 68c0c1d..08aa01f 100644 --- a/init.el +++ b/init.el @@ -118,6 +118,7 @@ (advice-add 'trusted-content-p :around #'my/-fix-trusted-content-p-for-remote) + ;; Increase responsiveness (setq gc-cons-threshold 80000000 inhibit-compacting-font-caches t @@ -237,7 +238,8 @@ (bash "https://github.com/tree-sitter/tree-sitter-bash") (cmake "https://github.com/uyha/tree-sitter-cmake") (blueprint "https://github.com/huanie/tree-sitter-blueprint") - (kdl "https://github.com/tree-sitter-grammars/tree-sitter-kdl"))) + (kdl "https://github.com/tree-sitter-grammars/tree-sitter-kdl") + (php "https://github.com/tree-sitter/tree-sitter-php"))) ;; Tree sitter major mode conversions (dolist (ent '((c-mode . c-ts-mode) (c++-mode . c++-ts-mode) @@ -250,7 +252,9 @@ (yaml-mode . yaml-ts-mode) (css-mode . css-ts-mode) (javascript-mode . js-ts-mode) - (cmake-mode . cmake-ts-mode))) + (cmake-mode . cmake-ts-mode) + ;; (go-mode . go-ts-mode) <- doesn't work very well + )) (add-to-list 'major-mode-remap-alist ent)) (defun my/treesit-compile-all (force) "Compile all the modules defined in `treesit-language-source-alist'. @@ -1812,7 +1816,7 @@ otherwise, call `bibtex-find-text'." (setq-local indent-line-function 'my/bibtex-indent-line electric-indent-chars '(?\n ?\{ ?\} ?,))) (defun my/-bibtex-fix-fill-prefix () - "`bivtex-mode' has a bad habbit of messing up `fill-prefix'." + "`bivtex-mode' has a bad habit of messing up `fill-prefix'." (when (eq major-mode 'bibtex-mode) (setq-local fill-prefix nil))) (advice-add 'bibtex-mode :after 'my/-bibtex-fix-fill-prefix) @@ -1902,11 +1906,22 @@ otherwise, call `bibtex-find-text'." (use-package pyvenv) (use-package pyenv-mode) +;; my own C comment logic +(require 'c-comments) +(defun my/setup-c-style-newline-keys (&rest maps) + "Redefine some newline commands in each of MAPS. +MAPS are expected to be keymaps for modes for languages with C-style comments." + (dolist (map maps) + (keymap-set map " " #'c-comments-newline) + (keymap-set map " " + #'c-comments-newline-always-continue))) + ;; java-ts-mode (use-package java-ts-mode :hook ((java-ts-mode . my/eglot-if-trusted) (java-ts-mode . my/-setup-java-ts-mode)) :config + (my/setup-c-style-newline-keys java-ts-mode-map) (defun my/-setup-java-ts-mode () (let ((rules (car treesit-simple-indent-rules))) (setcdr rules @@ -1934,30 +1949,9 @@ EVENT is the same as the original command." :after evil :hook ((c-ts-mode c++-ts-mode) . my/eglot-if-trusted) :init - (defun my/-c-ts-in-doc-comment-p (&optional include-end) - (when-let ((node (treesit-thing-at-point "comment" 'toplevel)) - (start (treesit-node-start node)) - (end (treesit-node-end node))) - (and (> (point) (+ start 2)) - (eql (char-after (+ start 1)) ?*) - (memql (char-after (+ start 2)) '(?* ?!)) - (or include-end - (<= (point) (- end 2)))))) - (defun my/c-ts-newline (&optional arg) - "Insert ARG newlines as with `newline'. -If inside a comment and in multi-line comment mode, act as -`default-indent-new-line'." - (interactive "*P") - (when (and arg (< (prefix-numeric-value arg) 0)) - (user-error "Count cannot be negative")) - (if (my/-c-ts-in-doc-comment-p) - (dotimes (_ (prefix-numeric-value arg)) - (default-indent-new-line)) - (newline arg t))) (setq-default c-ts-mode-indent-offset 4) :config - (dolist (sym '(c-ts-mode-map c++-ts-mode-map)) - (keymap-set (symbol-value sym) " " #'my/c-ts-newline)) + (my/setup-c-style-newline-keys c-ts-mode-map c++-ts-mode-map) (evil-define-key 'normal 'c-ts-mode-map "go" #'my/find-other-file "gO" #'my/find-other-file-other-window) @@ -1980,7 +1974,9 @@ This is :around advice, so OLDFUN is the real function (add-to-list 'auto-mode-alist '("\\.ino\\'" . arduino-ts-mode)) ;; GLSL -(use-package glsl-mode) +(use-package glsl-mode + :config + (my/setup-c-style-newline-keys glsl-mode-map)) ;; php-mode (use-package php-ts-mode @@ -2006,6 +2002,7 @@ This is :around advice, so OLDFUN is the real function ("C-M-x" . my/js-send-defun)) :hook (js-comint-mode . my/-setup-js-comint-mode) :config + (my/setup-c-style-newline-keys js-ts-mode-map) (defun my/-setup-js-comint-mode () (setq-local comint-highlight-input nil)) (defun my/js-send-defun () @@ -2020,7 +2017,9 @@ This is :around advice, so OLDFUN is the real function :ensure nil :hook (typescript-ts-mode . my/eglot-if-trusted) :init - (add-to-list 'auto-mode-alist `(,(rx ".ts" eos) . typescript-ts-mode))) + (add-to-list 'auto-mode-alist `(,(rx ".ts" eos) . typescript-ts-mode)) + :config + (my/setup-c-style-newline-keys typescript-ts-mode-map)) ;; Polymode (use-package polymode @@ -2049,16 +2048,23 @@ This is :around advice, so OLDFUN is the real function ;; go mode (use-package go-mode :defer nil - :hook (go-mode . my/eglot-if-trusted)) -(use-package go-ts-mode - :ensure nil - :hook (go-ts-mode . my/eglot-if-trusted)) + :hook (go-mode . my/eglot-if-trusted) + :config + (my/setup-c-style-newline-keys go-mode-map)) +;; (use-package go-ts-mode +;; :ensure nil +;; :hook (go-ts-mode . my/eglot-if-trusted) +;; :custom (go-ts-mode-indent-offset 4) +;; :config +;; (my/setup-c-style-newline-keys go-ts-mode-map)) ;; rust (use-package rust-mode) (use-package rust-ts-mode :ensure nil - :hook (rust-ts-mode . my/eglot-if-trusted)) + :hook (rust-ts-mode . my/eglot-if-trusted) + :config + (my/setup-c-style-newline-keys rust-ts-mode-map)) ;; zig (use-package zig-mode @@ -2092,6 +2098,7 @@ This is :around advice, so OLDFUN is the real function (use-package json-ts-mode :hook (json-ts-mode . my/eglot-if-trusted) :custom + (my/setup-c-style-newline-keys json-ts-mode-map) (json-ts-mode-indent-offset 4)) ;; csv