diff --git a/doc/emacs/modes.texi b/doc/emacs/modes.texi index 0e4b15fb514..d2f96af0b55 100644 --- a/doc/emacs/modes.texi +++ b/doc/emacs/modes.texi @@ -473,9 +473,12 @@ specify which mode you prefer. If you have changed the major mode of a buffer, you can return to the major mode Emacs would have chosen automatically, by typing @kbd{M-x normal-mode}. This is the same function that -@code{find-file} calls to choose the major mode. It also processes -the file's @samp{-*-} line or local variables list (if any). -@xref{File Variables}. +@code{find-file} calls to choose the major mode. If the buffer is +visiting a file, this command also processes the file's @samp{-*-} +line and file-local variables list (if any). @xref{File Variables}. +If the buffer doesn't visit a file, the command processes only the +major mode specification, if any, in the @samp{-*-} line and in the +file-local variables list. @vindex change-major-mode-with-file-name The commands @kbd{C-x C-w} and @code{set-visited-file-name} change to diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index fedb2804f26..c12224230fc 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -5117,10 +5117,10 @@ This anchor is a function that is called with 3 arguments: @var{node}, @var{parent}, and @var{bol}, and returns the first non-whitespace character on the previous line. -@item point-min +@item column-0 This anchor is a function that is called with 3 arguments: @var{node}, -@var{parent}, and @var{bol}, and returns the beginning of the buffer. -This is useful as the beginning of the buffer is always at column 0. +@var{parent}, and @var{bol}, and returns the beginning of the current +line, which is at column 0. @item comment-start This anchor is a function that is called with 3 arguments: @var{node}, diff --git a/lisp/files.el b/lisp/files.el index 387a3b5dc66..6f02aac33d3 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -2775,7 +2775,11 @@ not set local variables (though we do notice a mode specified with -*-.) `enable-local-variables' is ignored if you run `normal-mode' interactively, or from Lisp without specifying the optional argument FIND-FILE; -in that case, this function acts as if `enable-local-variables' were t." +in that case, this function acts as if `enable-local-variables' were t. + +If invoked in a buffer that doesn't visit a file, this function +processes only the major mode specification in the -*- line and +the local variables spec." (interactive) (kill-all-local-variables) (unless delay-mode-hooks @@ -3925,9 +3929,6 @@ variables. Uses `hack-local-variables-apply' to apply the variables. -See `hack-local-variables--find-variables' for the meaning of -HANDLE-MODE. - If `enable-local-variables' or `local-enable-local-variables' is nil, or INHIBIT-LOCALS is non-nil, this function disregards all normal local variables. If `inhibit-local-variables-regexps' @@ -3937,7 +3938,14 @@ applied. Variables present in `permanently-enabled-local-variables' will still be evaluated, even if local variables are otherwise -inhibited." +inhibited. + +If HANDLE-MODE is t, the function only checks whether a \"mode:\" +is specified, and returns the corresponding mode symbol, or nil. +In this case, try to ignore minor-modes, and return only a major-mode. +If HANDLE-MODE is nil, the function gathers all the specified local +variables. If HANDLE-MODE is neither nil nor t, the function gathers +all the specified local variables, but ignores any settings of \"mode:\"." ;; We don't let inhibit-local-variables-p influence the value of ;; enable-local-variables, because then it would affect dir-local ;; variables. We don't want to search eg tar files for file local diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 96d2615c1f7..132c44d330a 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -299,6 +299,23 @@ PARENT and BOL are like other anchor functions." ;; prev-sibling doesn't have a child. (treesit-node-start prev-sibling))) +(defun c-ts-mode--standalone-parent-skip-preproc (_n parent &rest _) + "Like the standalone-parent anchor but skips preproc nodes. +PARENT is the same as other anchor functions." + (save-excursion + (treesit-node-start + (treesit-parent-until + ;; Use PARENT rather than NODE, to handle the case where NODE is + ;; nil. + parent (lambda (node) + (and node + (not (string-match "preproc" (treesit-node-type node))) + (progn + (goto-char (treesit-node-start node)) + (looking-back (rx bol (* whitespace)) + (line-beginning-position))))) + t)))) + (defun c-ts-mode--standalone-grandparent (_node parent bol &rest args) "Like the standalone-parent anchor but pass it the grandparent. PARENT, BOL, ARGS are the same as other anchor functions." @@ -309,8 +326,8 @@ PARENT, BOL, ARGS are the same as other anchor functions." "Indent rules supported by `c-ts-mode'. MODE is either `c' or `cpp'." (let ((common - `(((parent-is "translation_unit") point-min 0) - ((query "(ERROR (ERROR)) @indent") point-min 0) + `(((parent-is "translation_unit") column-0 0) + ((query "(ERROR (ERROR)) @indent") column-0 0) ((node-is ")") parent 1) ((node-is "]") parent-bol 0) ((node-is "else") parent-bol 0) @@ -330,13 +347,28 @@ MODE is either `c' or `cpp'." ((parent-is "labeled_statement") c-ts-mode--standalone-grandparent c-ts-mode-indent-offset) - ((node-is "preproc") point-min 0) - ((node-is "#endif") point-min 0) - ((match "preproc_call" "compound_statement") point-min 0) + ;; Preproc directives + ((node-is "preproc") column-0 0) + ((node-is "#endif") column-0 0) + ((match "preproc_call" "compound_statement") column-0 0) - ((n-p-gp nil "preproc" "translation_unit") point-min 0) - ((n-p-gp nil "\n" "preproc") great-grand-parent c-ts-mode--preproc-offset) - ((parent-is "preproc") grand-parent c-ts-mode-indent-offset) + ;; Top-level things under a preproc directive. Note that + ;; "preproc" matches more than one type: it matches + ;; preproc_if, preproc_elif, etc. + ((n-p-gp nil "preproc" "translation_unit") column-0 0) + ;; Indent rule for an empty line after a preproc directive. + ((and no-node (parent-is ,(rx (or "\n" "preproc")))) + c-ts-mode--standalone-parent-skip-preproc c-ts-mode--preproc-offset) + ;; Statement under a preproc directive, the first statement + ;; indents against parent, the rest statements indent to + ;; their prev-sibling. + ((match nil ,(rx "preproc_" (or "if" "elif")) nil 3 3) + c-ts-mode--standalone-parent-skip-preproc c-ts-mode-indent-offset) + ((match nil "preproc_ifdef" nil 2 2) + c-ts-mode--standalone-parent-skip-preproc c-ts-mode-indent-offset) + ((match nil "preproc_else" nil 1 1) + c-ts-mode--standalone-parent-skip-preproc c-ts-mode-indent-offset) + ((parent-is "preproc") c-ts-mode--anchor-prev-sibling 0) ((parent-is "function_definition") parent-bol 0) ((parent-is "conditional_expression") first-sibling 0) @@ -392,14 +424,14 @@ MODE is either `c' or `cpp'." `((gnu ;; Prepend rules to set highest priority ((match "while" "do_statement") parent 0) - (c-ts-mode--top-level-label-matcher point-min 1) + (c-ts-mode--top-level-label-matcher column-0 1) ,@common) (k&r ,@common) (linux ;; Reference: ;; https://www.kernel.org/doc/html/latest/process/coding-style.html, ;; and script/Lindent in Linux kernel repository. - ((node-is "labeled_statement") point-min 0) + ((node-is "labeled_statement") column-0 0) ,@common) (bsd ((node-is "}") parent-bol 0) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 13d30a67083..2f8d2002cd3 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1079,7 +1079,8 @@ variable (which see) can query the value `eglot-lsp-context' to decide whether a given directory is a project containing a suitable root directory for a given LSP server's purposes." (let ((eglot-lsp-context t)) - (or (project-current) `(transient . ,default-directory)))) + (or (project-current) + `(transient . ,(expand-file-name default-directory))))) ;;;###autoload (defun eglot (managed-major-mode project class contact language-id @@ -1922,6 +1923,7 @@ If it is activated, also signal textDocument/didOpen." (eglot--signal-textDocument/didOpen) ;; Run user hook after 'textDocument/didOpen' so server knows ;; about the buffer. + (eglot-inlay-hints-mode 1) (run-hooks 'eglot-managed-mode-hook)))) (add-hook 'after-change-major-mode-hook 'eglot--maybe-activate-editing-mode) @@ -3645,8 +3647,7 @@ If NOERROR, return predicate, else erroring function." (cond (eglot-inlay-hints-mode (if (eglot--server-capable :inlayHintProvider) (jit-lock-register #'eglot--update-hints 'contextual) - (eglot--warn - "No :inlayHintProvider support. Inlay hints will not work."))) + (eglot-inlay-hints-mode -1))) (t (jit-lock-unregister #'eglot--update-hints) (remove-overlays nil nil 'eglot--inlay-hint t)))) diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el index ce77cc3973d..e6e8abd6445 100644 --- a/lisp/progmodes/go-ts-mode.el +++ b/lisp/progmodes/go-ts-mode.el @@ -67,11 +67,12 @@ (defvar go-ts-mode--indent-rules `((go - ((parent-is "source_file") point-min 0) + ((parent-is "source_file") column-0 0) ((node-is ")") parent-bol 0) ((node-is "]") parent-bol 0) ((node-is "}") parent-bol 0) - ((node-is "labeled_statement") no-indent) + ((node-is "labeled_statement") no-indent 0) + ((parent-is "raw_string_literal") no-indent 0) ((parent-is "argument_list") parent-bol go-ts-mode-indent-offset) ((parent-is "block") parent-bol go-ts-mode-indent-offset) ((parent-is "communication_case") parent-bol go-ts-mode-indent-offset) diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index d31d2d71c38..1115eadde7f 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -69,10 +69,10 @@ (defvar java-ts-mode--indent-rules `((java - ((parent-is "program") point-min 0) + ((parent-is "program") column-0 0) ((match "}" "element_value_array_initializer") parent-bol 0) - ((node-is "}") point-min c-ts-common-statement-offset) + ((node-is "}") column-0 c-ts-common-statement-offset) ((node-is ")") parent-bol 0) ((node-is "else") parent-bol 0) ((node-is "]") parent-bol 0) @@ -80,15 +80,15 @@ c-ts-common-comment-start-after-first-star -1) ((parent-is "comment") prev-adaptive-prefix 0) ((parent-is "text_block") no-indent) - ((parent-is "class_body") point-min c-ts-common-statement-offset) + ((parent-is "class_body") column-0 c-ts-common-statement-offset) ((parent-is "array_initializer") parent-bol java-ts-mode-indent-offset) - ((parent-is "annotation_type_body") point-min c-ts-common-statement-offset) - ((parent-is "interface_body") point-min c-ts-common-statement-offset) - ((parent-is "constructor_body") point-min c-ts-common-statement-offset) + ((parent-is "annotation_type_body") column-0 c-ts-common-statement-offset) + ((parent-is "interface_body") column-0 c-ts-common-statement-offset) + ((parent-is "constructor_body") column-0 c-ts-common-statement-offset) ((parent-is "enum_body_declarations") parent-bol 0) - ((parent-is "enum_body") point-min c-ts-common-statement-offset) - ((parent-is "switch_block") point-min c-ts-common-statement-offset) - ((parent-is "record_declaration_body") point-min c-ts-common-statement-offset) + ((parent-is "enum_body") column-0 c-ts-common-statement-offset) + ((parent-is "switch_block") column-0 c-ts-common-statement-offset) + ((parent-is "record_declaration_body") column-0 c-ts-common-statement-offset) ((query "(method_declaration (block _ @indent))") parent-bol java-ts-mode-indent-offset) ((query "(method_declaration (block (_) @indent))") parent-bol java-ts-mode-indent-offset) ((parent-is "local_variable_declaration") parent-bol java-ts-mode-indent-offset) @@ -121,7 +121,7 @@ ((parent-is "case_statement") parent-bol java-ts-mode-indent-offset) ((parent-is "labeled_statement") parent-bol java-ts-mode-indent-offset) ((parent-is "do_statement") parent-bol java-ts-mode-indent-offset) - ((parent-is "block") point-min c-ts-common-statement-offset))) + ((parent-is "block") column-0 c-ts-common-statement-offset))) "Tree-sitter indent rules.") (defvar java-ts-mode--keywords diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el index 4530b162e6e..b2842c33d29 100644 --- a/lisp/progmodes/ruby-ts-mode.el +++ b/lisp/progmodes/ruby-ts-mode.el @@ -557,7 +557,7 @@ a statement container is a node that matches (let ((common `( ;; Slam all top level nodes to the left margin - ((parent-is "program") point-min 0) + ((parent-is "program") column-0 0) ;; Do not indent here docs or the end. Not sure why it ;; takes the grand-parent but ok fine. diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index 2d5c3211c1a..696c2633231 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -71,7 +71,7 @@ (defvar rust-ts-mode--indent-rules `((rust - ((parent-is "source_file") point-min 0) + ((parent-is "source_file") column-0 0) ((node-is ")") parent-bol 0) ((node-is "]") parent-bol 0) ((node-is "}") (and parent parent-bol) 0) diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index ca6fd2c09da..b21b1fd2cef 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el @@ -69,7 +69,7 @@ "Rules used for indentation. Argument LANGUAGE is either `typescript' or `tsx'." `((,language - ((parent-is "program") point-min 0) + ((parent-is "program") column-0 0) ((node-is "}") parent-bol 0) ((node-is ")") parent-bol 0) ((node-is "]") parent-bol 0) diff --git a/lisp/subr.el b/lisp/subr.el index 2a8c51eb7c4..8ff3b868fab 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -2441,8 +2441,9 @@ If the variable `delay-mode-hooks' is non-nil, does not do anything, just adds the HOOKS to the list `delayed-mode-hooks'. Otherwise, runs hooks in the sequence: `change-major-mode-after-body-hook', `delayed-mode-hooks' (in reverse order), HOOKS, then runs -`hack-local-variables', runs the hook `after-change-major-mode-hook', and -finally evaluates the functions in `delayed-after-hook-functions' (see +`hack-local-variables' (if the buffer is visiting a file), +runs the hook `after-change-major-mode-hook', and finally +evaluates the functions in `delayed-after-hook-functions' (see `define-derived-mode'). Major mode functions should use this instead of `run-hooks' when diff --git a/lisp/treesit.el b/lisp/treesit.el index e7a8ad6104f..e680668a353 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1254,7 +1254,10 @@ See `treesit-simple-indent-presets'.") (goto-char bol) (forward-line -1) (skip-chars-forward " \t")))) - (cons 'point-min (lambda (&rest _) (point-min))) + (cons 'column-0 (lambda (_n _p bol &rest _) + (save-excursion + (goto-char bol) + (line-beginning-position)))) ;; TODO: Document. (cons 'and (lambda (&rest fns) (lambda (node parent bol &rest _) @@ -1358,9 +1361,9 @@ prev-line Returns the first non-whitespace character on the previous line. -point-min +column-0 - Returns the beginning of buffer, which is always at column 0. + Returns the beginning of the current line, which is at column 0. comment-start diff --git a/lisp/window.el b/lisp/window.el index 576478eef88..08ce8498655 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -4143,6 +4143,10 @@ X and Y are FRAME-relative pixel coordinates. A coordinate on an edge shared by two windows is attributed to the window on the right (or below). Return nil if no such window can be found. +Tool-bar and tab-bar pseudo-windows are ignored by this function: +if the specified coordinates are in any of these two windows, this +function returns nil. + Optional argument FRAME must specify a live frame and defaults to the selected one. Optional argument NO-OTHER non-nil means to return nil if the window located at the specified coordinates has diff --git a/src/window.c b/src/window.c index bf89261e79c..f4e09f49eae 100644 --- a/src/window.c +++ b/src/window.c @@ -1729,8 +1729,11 @@ window_from_coordinates (struct frame *f, int x, int y, DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0, doc: /* Return window containing coordinates X and Y on FRAME. FRAME must be a live frame and defaults to the selected one. -The top left corner of the frame is considered to be row 0, -column 0. */) +X and Y are measured in units of canonical columns and rows. +The top left corner of the frame is considered to be column 0, row 0. +Tool-bar and tab-bar pseudo-windows are ignored by this function: if +the specified coordinates are in any of these two windows, this +function returns nil. */) (Lisp_Object x, Lisp_Object y, Lisp_Object frame) { struct frame *f = decode_live_frame (frame); diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts b/test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts index 57610b5483e..0f9256ad984 100644 --- a/test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts +++ b/test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts @@ -44,3 +44,37 @@ static void /* */ static void =-=-= + +Code: + (lambda () + (c-ts-mode) + (setq-local indent-tabs-mode nil) + (setq-local c-ts-mode-indent-offset 2) + (c-ts-mode-set-style 'gnu) + (indent-region (point-min) (point-max))) + +Name: Prev-Sibling When Prev-Sibling is Preproc + +=-= +static void +free_glyph_pool (struct glyph_pool *pool) +{ + if (pool) + { +#if defined GLYPH_DEBUG + int c = 1; +#endif + int check_this = 3; + +#ifdef stuff + int c = 1; +#elif defined stuff + int e = 5; +#else + int d = 11; + int f = 11; +#endif + int check_this = 3; + } +} +=-=-= diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el index 5d5de59a19a..7a90d68d213 100644 --- a/test/lisp/progmodes/eglot-tests.el +++ b/test/lisp/progmodes/eglot-tests.el @@ -103,22 +103,21 @@ then restored." (set (car spec) (cadr spec))) ((stringp (car spec)) (push spec file-specs)))) (unwind-protect - (let* ((home (getenv "HOME")) - (process-environment + (let* ((process-environment (append `(;; Set XDF_CONFIG_HOME to /dev/null to prevent ;; user-configuration to have an influence on ;; language servers. (See github#441) "XDG_CONFIG_HOME=/dev/null" ;; ... on the flip-side, a similar technique by - ;; Emacs's test makefiles means that HOME is set to - ;; /nonexistent. This breaks some common - ;; installations for LSP servers like pylsp, making - ;; these tests mostly useless, so we hack around it - ;; here with a great big hack. + ;; Emacs's test makefiles means that HOME is + ;; spoofed to /nonexistent, or sometimes /tmp. + ;; This breaks some common installations for LSP + ;; servers like pylsp, rust-analyzer making these + ;; tests mostly useless, so we hack around it here + ;; with a great big hack. ,(format "HOME=%s" - (if (file-exists-p home) home - (format "/home/%s" (getenv "USER"))))) + (expand-file-name (format "~%s" (user-login-name))))) process-environment)) ;; Prevent "Can't guess python-indent-offset ..." messages. (python-indent-guess-indent-offset-verbose . nil)