unofficial mirror of emacs-orgmode@gnu.org
 help / color / Atom feed
* Setting org-todo-keywords through directory-local variables
@ 2020-05-20 21:12 Kévin Le Gouguec
  2020-05-21 23:12 ` Kévin Le Gouguec
  2020-05-22  8:42 ` Nicolas Goaziou
  0 siblings, 2 replies; 6+ messages in thread
From: Kévin Le Gouguec @ 2020-05-20 21:12 UTC (permalink / raw)
  To: emacs-orgmode

Hello,

I'd like to set org-todo-keywords and org-todo-keyword-faces through
directory-local variables, to get rid of duplicate #+SEQ_TODO lines in
my Org files[1].

Right now I see two obstacles for this to work:

(1) org-set-regexps-and-options, which sets up a bunch of TODO-related
    machinery, insists on using (default-value 'org-todo-keywords),

(2) this function is called in the major mode function, which IIUC means
    that directory-local values have not been applied yet.

The first obstacle looks like it can be easily removed[2]; the second
obstacle looks more substantial.  It is trivially side-stepped by
sticking (hack-local-variables) at the top of org-mode; to my untrained
eye, it looks like TRT would rather be for Org to add
org-set-regexps-and-options to hack-local-variables-hook.

This sounds like a risky change though: I imagine that a lot of what
happens in the major mode function depends on what
org-set-regexps-and-options sets up, and would therefore need to be
moved to this hook as well.  Figuring which parts should be moved seems
like a non-trivial task that might introduce some regressions…


Can anyone confirm that this would (in principle) be the way forward, or
tell me if I am missing something[3]?


Thank you for your time.


[1] For example:

#+begin_src elisp
((org-mode
  . ((org-todo-keywords
      . ((sequence "REPORT" "REPORTED" "WAITING" "FIXED")
         (sequence "CANCELED")))
     (org-todo-keyword-faces
      . (("REPORT" . org-todo)
         ("REPORTED" . warning)
         ("WAITING" . warning)
         ("FIXED" . org-done)
         ("CANCELED" . shadow))))))
#+end_src

I'd like that so much that I went through the trouble of writing
safe-local-variable predicates for these variables:

#+begin_src elisp
(put 'org-todo-keywords
     'safe-local-variable
     (lambda (x)
       (cl-every
        (lambda (seq)
          (and (memq (car seq) '(sequence type))
               (cl-every (lambda (i) (stringp i)) (cdr seq))))
        x)))

(put 'org-todo-keyword-faces
     'safe-local-variable
     (lambda (x)
       (cl-every
        (lambda (pair)
          (pcase pair
            (`(,keyword . ,face)
             (and (stringp keyword)
                  (or (facep face) (listp face))))))
        x)))
#end_src

[2] I tried to go through org.el's history, but I could not find a
rationale for using default-value.

[3] Alternatively, maybe the answer is as simple as "Org documents
should be self-sufficient; keywords should be explicitly set in
#+SEQ_TODO lines"; that wouldn't sound right though, since
org-todo-keywords is customizable.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Setting org-todo-keywords through directory-local variables
  2020-05-20 21:12 Setting org-todo-keywords through directory-local variables Kévin Le Gouguec
@ 2020-05-21 23:12 ` Kévin Le Gouguec
  2020-05-22 15:11   ` Nicolas Goaziou
  2020-05-22  8:42 ` Nicolas Goaziou
  1 sibling, 1 reply; 6+ messages in thread
From: Kévin Le Gouguec @ 2020-05-21 23:12 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1031 bytes --]

Kévin Le Gouguec <kevin.legouguec@gmail.com> writes:

> Can anyone confirm that this would (in principle) be the way forward, or
> tell me if I am missing something[3]?

I went ahead and cooked up a proof-of-concept patch, which

(1) adds safe-local-variable properties to org-todo-keywords and
    org-todo-keyword-faces,

(2) stops applying default-value to org-todo-keywords,

(3) delays regexps/font-lock setups until after file- and dir-local
    variables have been set.

While this patch contains a few things that make me weary[1], it solves
my use-case, and passes the current test suite with Emacs 26.3 and 28.

Does this look sound overall?  Does anyone have any idea what kind of
breakage might be slipping through the test suite?

Thank you for your time.


[1] - It's hard to feel confident that moving org-regexps-and-options
      and org-set-font-lock-defaults like this will not introduce
      regressions.

    - Also, these safe-local-variable validation functions could
      probably use some unit tests.



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: dir-local-todo-keywords.patch --]
[-- Type: text/x-patch, Size: 3275 bytes --]

diff --git a/lisp/org-faces.el b/lisp/org-faces.el
index d78b606ec..544563276 100644
--- a/lisp/org-faces.el
+++ b/lisp/org-faces.el
@@ -291,7 +291,15 @@ determines if it is a foreground or a background color."
 	   (string :tag "Keyword")
 	   (choice :tag "Face   "
 		   (string :tag "Color")
-		   (sexp :tag "Face")))))
+		   (sexp :tag "Face"))))
+  :safe (lambda (x)
+          (cl-every
+           (lambda (pair)
+             (pcase pair
+               (`(,keyword . ,face)
+                (and (stringp keyword)
+                     (or (facep face) (listp face))))))
+           x)))
 
 (defface org-priority '((t :inherit font-lock-keyword-face))
   "Face used for priority cookies."
diff --git a/lisp/org.el b/lisp/org.el
index e577dc661..7f4672058 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -1945,7 +1945,13 @@ taken from the (otherwise obsolete) variable `org-todo-interpretation'."
 					 org-todo-interpretation-widgets))
 		      widget))
 		   (repeat
-		    (string :tag "Keyword"))))))
+		    (string :tag "Keyword")))))
+  :safe (lambda (x)
+          (cl-every
+           (lambda (seq)
+             (and (memq (car seq) '(sequence type))
+                  (cl-every (lambda (i) (stringp i)) (cdr seq))))
+           x)))
 
 (defvar-local org-todo-keywords-1 nil
   "All TODO and DONE keywords active in a buffer.")
@@ -4358,10 +4364,9 @@ related expressions."
 				     (cons 'sequence (split-string value)))
 				   (append (cdr (assoc "TODO" alist))
 					   (cdr (assoc "SEQ_TODO" alist)))))
-		   (let ((d (default-value 'org-todo-keywords)))
-		     (if (not (stringp (car d))) d
-		       ;; XXX: Backward compatibility code.
-		       (list (cons org-todo-interpretation d)))))))
+		   (if (not (stringp (car org-todo-keywords))) org-todo-keywords
+		     ;; XXX: Backward compatibility code.
+		     (list (cons org-todo-interpretation org-todo-keywords))))))
 	  (dolist (sequence todo-sequences)
 	    (let* ((sequence (or (run-hook-with-args-until-success
 				  'org-todo-setup-filter-hook sequence)
@@ -4801,8 +4806,6 @@ The following commands are available:
      (vconcat (mapcar (lambda (c) (make-glyph-code c 'org-ellipsis))
 		      org-ellipsis)))
     (setq buffer-display-table org-display-table))
-  (org-set-regexps-and-options)
-  (org-set-font-lock-defaults)
   (when (and org-tag-faces (not org-tags-special-faces-re))
     ;; tag faces set outside customize.... force initialization.
     (org-set-tag-faces 'org-tag-faces org-tag-faces))
@@ -4909,7 +4912,16 @@ The following commands are available:
   ;; Try to set `org-hide' face correctly.
   (let ((foreground (org-find-invisible-foreground)))
     (when foreground
-      (set-face-foreground 'org-hide foreground))))
+      (set-face-foreground 'org-hide foreground)))
+
+  ;; For file-visiting buffers, delay some setup until after
+  ;; file-local and directory-local variables have been set.
+  (if (buffer-file-name)
+      (progn
+	(add-hook 'hack-local-variables-hook 'org-set-regexps-and-options 1 t)
+	(add-hook 'hack-local-variables-hook 'org-set-font-lock-defaults 1 t))
+    (org-set-regexps-and-options)
+    (org-set-font-lock-defaults)))
 
 ;; Update `customize-package-emacs-version-alist'
 (add-to-list 'customize-package-emacs-version-alist

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Setting org-todo-keywords through directory-local variables
  2020-05-20 21:12 Setting org-todo-keywords through directory-local variables Kévin Le Gouguec
  2020-05-21 23:12 ` Kévin Le Gouguec
@ 2020-05-22  8:42 ` Nicolas Goaziou
  1 sibling, 0 replies; 6+ messages in thread
From: Nicolas Goaziou @ 2020-05-22  8:42 UTC (permalink / raw)
  To: Kévin Le Gouguec; +Cc: emacs-orgmode

Hello,

Kévin Le Gouguec <kevin.legouguec@gmail.com> writes:

> I'd like to set org-todo-keywords and org-todo-keyword-faces through
> directory-local variables, to get rid of duplicate #+SEQ_TODO lines in
> my Org files[1].
>
> Right now I see two obstacles for this to work:
>
> (1) org-set-regexps-and-options, which sets up a bunch of TODO-related
>     machinery, insists on using (default-value 'org-todo-keywords),
>
> (2) this function is called in the major mode function, which IIUC means
>     that directory-local values have not been applied yet.
>
> The first obstacle looks like it can be easily removed[2]; the second
> obstacle looks more substantial.  It is trivially side-stepped by
> sticking (hack-local-variables) at the top of org-mode; to my untrained
> eye, it looks like TRT would rather be for Org to add
> org-set-regexps-and-options to hack-local-variables-hook.
>
> This sounds like a risky change though: I imagine that a lot of what
> happens in the major mode function depends on what
> org-set-regexps-and-options sets up, and would therefore need to be
> moved to this hook as well.  Figuring which parts should be moved seems
> like a non-trivial task that might introduce some regressions…
>
>
> Can anyone confirm that this would (in principle) be the way forward, or
> tell me if I am missing something[3]?

Did you consider using SETUPFILE?

Regards,

-- 
Nicolas Goaziou


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Setting org-todo-keywords through directory-local variables
  2020-05-21 23:12 ` Kévin Le Gouguec
@ 2020-05-22 15:11   ` Nicolas Goaziou
  2020-05-23 12:58     ` Kévin Le Gouguec
  0 siblings, 1 reply; 6+ messages in thread
From: Nicolas Goaziou @ 2020-05-22 15:11 UTC (permalink / raw)
  To: Kévin Le Gouguec; +Cc: emacs-orgmode

Hello,

Kévin Le Gouguec <kevin.legouguec@gmail.com> writes:

> Kévin Le Gouguec <kevin.legouguec@gmail.com> writes:
>
>> Can anyone confirm that this would (in principle) be the way forward, or
>> tell me if I am missing something[3]?
>
> I went ahead and cooked up a proof-of-concept patch, which
>
> (1) adds safe-local-variable properties to org-todo-keywords and
>     org-todo-keyword-faces,
>
> (2) stops applying default-value to org-todo-keywords,
>
> (3) delays regexps/font-lock setups until after file- and dir-local
>     variables have been set.
>
> While this patch contains a few things that make me weary[1], it solves
> my use-case, and passes the current test suite with Emacs 26.3 and 28.
>
> Does this look sound overall?  Does anyone have any idea what kind of
> breakage might be slipping through the test suite?

This looks hackish. Also, Org needs the STARTUP part early on, so you
cannot really delay it.

I /think/ the rest can be delayed, but I admit I'm not too sure either.
I think the expected way to do this is to add a SETUPFILE.

Regards,

-- 
Nicolas Goaziou


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Setting org-todo-keywords through directory-local variables
  2020-05-22 15:11   ` Nicolas Goaziou
@ 2020-05-23 12:58     ` Kévin Le Gouguec
  2020-06-24 17:54       ` Kévin Le Gouguec
  0 siblings, 1 reply; 6+ messages in thread
From: Kévin Le Gouguec @ 2020-05-23 12:58 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 2025 bytes --]

Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:

> This looks hackish.

Any bit in particular?  AFAICT hack-local-variables-hook is the expected
way to perform plumbing that might be affected by file/directory-local
variables.  It is used by e.g. shell-script-mode, cc-mode, markdown-mode
and AUCTeX, to name a few.  The docstring says:

> Major modes can use this to examine user-specified local variables
> in order to initialize other data structure based on them.

I think the buffer-file-name bit looks dodgy; I mainly did that to get
the unit tests to pass on this POC.

>                     Also, Org needs the STARTUP part early on, so you
> cannot really delay it.
>
> I /think/ the rest can be delayed, but I admit I'm not too sure either.

Right.  Now that I've looked at other major modes (especially
AUCTeX[1]), it seems a more conventional approach would be to

- keep the calls to org-set-regexps-and-options and
  org-set-font-lock-defaults where they are now,

- in hack-local-variables-hook, *if* file-local-variables-alist contains
  Org variables that affect those functions, and call them again to
  refresh regexps and fontification.

IIUC this would pretty much guarantee that things can only break for
weirdos like me who try to use directory-local variables.

> I think the expected way to do this is to add a SETUPFILE.

Thanks for the pointer!  Unless I'm misreading (info "(org) In-buffer
Settings"), I could move my SEQ_TODO settings there, but that wouldn't
work for org-todo-keyword-faces, right?


In light of your comments, and based on what I've seen in AUCTeX, I'm
attaching what I believe to be a less intrusive patch.  WDYT?


Thank you for taking the time to review this.  I'm not opposed to using
SETUPFILE (if I can handle org-todo-keyword-faces there); I'm just
wondering if this could be one more opportunity to have Org play nice
with other Emacs facilities (directory-local variables).


[1] https://git.savannah.gnu.org/cgit/auctex.git/tree/font-latex.el?h=release_12_2#n1435



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: dir-local-todo-keywords.patch --]
[-- Type: text/x-patch, Size: 2850 bytes --]

diff --git a/lisp/org-faces.el b/lisp/org-faces.el
index d78b606ec..fc834f37d 100644
--- a/lisp/org-faces.el
+++ b/lisp/org-faces.el
@@ -291,7 +291,15 @@ determines if it is a foreground or a background color."
 	   (string :tag "Keyword")
 	   (choice :tag "Face   "
 		   (string :tag "Color")
-		   (sexp :tag "Face")))))
+		   (sexp :tag "Face"))))
+  :safe (lambda (x)
+          (cl-every
+           (lambda (pair)
+	     (let ((keyword (car pair))
+		   (face (cdr pair)))
+	       (and (stringp keyword)
+		    (or (facep face) (listp face)))))
+           x)))
 
 (defface org-priority '((t :inherit font-lock-keyword-face))
   "Face used for priority cookies."
diff --git a/lisp/org.el b/lisp/org.el
index e577dc661..da38beb45 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -1945,7 +1945,13 @@ taken from the (otherwise obsolete) variable `org-todo-interpretation'."
 					 org-todo-interpretation-widgets))
 		      widget))
 		   (repeat
-		    (string :tag "Keyword"))))))
+		    (string :tag "Keyword")))))
+  :safe (lambda (x)
+          (cl-every
+           (lambda (seq)
+             (and (memq (car seq) '(sequence type))
+                  (cl-every (lambda (i) (stringp i)) (cdr seq))))
+           x)))
 
 (defvar-local org-todo-keywords-1 nil
   "All TODO and DONE keywords active in a buffer.")
@@ -4358,10 +4364,9 @@ related expressions."
 				     (cons 'sequence (split-string value)))
 				   (append (cdr (assoc "TODO" alist))
 					   (cdr (assoc "SEQ_TODO" alist)))))
-		   (let ((d (default-value 'org-todo-keywords)))
-		     (if (not (stringp (car d))) d
-		       ;; XXX: Backward compatibility code.
-		       (list (cons org-todo-interpretation d)))))))
+		   (if (not (stringp (car org-todo-keywords))) org-todo-keywords
+		     ;; XXX: Backward compatibility code.
+		     (list (cons org-todo-interpretation org-todo-keywords))))))
 	  (dolist (sequence todo-sequences)
 	    (let* ((sequence (or (run-hook-with-args-until-success
 				  'org-todo-setup-filter-hook sequence)
@@ -4909,7 +4914,18 @@ The following commands are available:
   ;; Try to set `org-hide' face correctly.
   (let ((foreground (org-find-invisible-foreground)))
     (when foreground
-      (set-face-foreground 'org-hide foreground))))
+      (set-face-foreground 'org-hide foreground)))
+
+  (add-hook 'hack-local-variables-hook #'org--process-local-variables nil t))
+
+(defun org--process-local-variables ()
+  "Refresh settings affected by file-local or directory-local variables."
+  (when
+      (let ((local-vars (mapcar #'car file-local-variables-alist)))
+	(or (memq 'org-todo-keywords local-vars)
+	    (memq 'org-todo-keyword-faces local-vars)))
+    (org-set-regexps-and-options)
+    (org-set-font-lock-defaults)))
 
 ;; Update `customize-package-emacs-version-alist'
 (add-to-list 'customize-package-emacs-version-alist

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Setting org-todo-keywords through directory-local variables
  2020-05-23 12:58     ` Kévin Le Gouguec
@ 2020-06-24 17:54       ` Kévin Le Gouguec
  0 siblings, 0 replies; 6+ messages in thread
From: Kévin Le Gouguec @ 2020-06-24 17:54 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1897 bytes --]

Hello,

I would like to re-submit this idea, now that I am reasonably sure that
my implementation will not impact users who do not use the feature.

(I understand that Org 9.4 is on the way.  I am not asking for this
feature to be included right now; I would like to get some feedback
first, then move on to documenting it.)

* Motivation

To recap: AFAIK it is not possible to define both org-todo-keywords and
org-todo-keyword-faces per-directory.  The former can be set with
#+SETUPFILE, but the latter simply can't be set locally, unless I'm
mistaken.

I'd like to specify, for all Org files in a directory, which keywords to
use and how they must look.  Setting both org-todo-* variables in
.dir-locals.el would be ideal IMO: the definitions for keywords and
their faces would be right next to each other.

This cannot work right now because (1) of a stray call to default-value
(2) Org computes the TODO machinery (regexps and font-lock) when setting
up the major mode, before directory-local variables are in effect.

* Prior art

AUCTeX[1] and markdown-mode[2] both solve this using
hack-local-variables-hook.  This seems to be the expected way for modes
to (re)compute things that may be affected by file or directory-local
variables.

[1] http://git.savannah.gnu.org/cgit/auctex.git/tree/font-latex.el?h=release_12_2#n1331
[2] https://github.com/jrblevin/markdown-mode/blob/v2.4/markdown-mode.el#L9403

The idea is to register a function that will check whether the user
overloaded variables we care about; if that's the case, then we
recompute what we need to.

* Patch

The attached patch:

- does not change org-mode's default setup logic,

- adds a function to hack-local-variables-hook that will look for
  org-todo-* variables, and recompute org-set-regexps-and-options and
  org-set-font-lock-defaults if needed,

- adds :safe predicates for these variables,

- adds unit tests.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Allow-users-to-configure-TODO-keywords-from-dir-loca.patch --]
[-- Type: text/x-patch, Size: 6926 bytes --]

From 148c5fa45e1fb8d58ecc86bb266d0fa33b8994a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?K=C3=A9vin=20Le=20Gouguec?= <kevin.legouguec@gmail.com>
Date: Wed, 27 May 2020 22:53:56 +0200
Subject: [PATCH] Allow users to configure TODO keywords from dir-locals.el

This uses the same method as AUCTeX and markdown-mode to refresh
fontification based on file-local and directory-local variables:

http://git.savannah.gnu.org/cgit/auctex.git/tree/font-latex.el?h=release_12_2#n1331
https://github.com/jrblevin/markdown-mode/blob/v2.4/markdown-mode.el#L9403

* lisp/org-faces.el (org-todo-keyword-faces): Add safe-local-variable
predicate.

* lisp/org.el (org-todo-keywords): Add safe-local-variable predicate.
(org-set-regexps-and-options): Use buffer-local value of
org-todo-keywords.
(org-mode): Register a function to reset regexps and font-lock once
file-local variables have been applied.
(org--process-local-variables): Recompute regexps and font-lock if the
user set relevant variables.

* testing/examples/dir-locals/.dir-locals.el:
* testing/examples/dir-locals/todo.org: Support files for new tests.

* testing/lisp/test-org.el (test-org/dir-local-todo-keyword-faces):
(test-org/dir-local-todo-cycling): New tests.
---
 lisp/org-faces.el                          | 10 ++++++-
 lisp/org.el                                | 28 +++++++++++++++----
 testing/examples/dir-locals/.dir-locals.el | 11 ++++++++
 testing/examples/dir-locals/todo.org       |  8 ++++++
 testing/lisp/test-org.el                   | 32 ++++++++++++++++++++++
 5 files changed, 82 insertions(+), 7 deletions(-)
 create mode 100644 testing/examples/dir-locals/.dir-locals.el
 create mode 100644 testing/examples/dir-locals/todo.org

diff --git a/lisp/org-faces.el b/lisp/org-faces.el
index d78b606ec..fc834f37d 100644
--- a/lisp/org-faces.el
+++ b/lisp/org-faces.el
@@ -291,7 +291,15 @@ determines if it is a foreground or a background color."
 	   (string :tag "Keyword")
 	   (choice :tag "Face   "
 		   (string :tag "Color")
-		   (sexp :tag "Face")))))
+		   (sexp :tag "Face"))))
+  :safe (lambda (x)
+          (cl-every
+           (lambda (pair)
+	     (let ((keyword (car pair))
+		   (face (cdr pair)))
+	       (and (stringp keyword)
+		    (or (facep face) (listp face)))))
+           x)))
 
 (defface org-priority '((t :inherit font-lock-keyword-face))
   "Face used for priority cookies."
diff --git a/lisp/org.el b/lisp/org.el
index 4d46b4173..c0183dbff 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -1945,7 +1945,13 @@ taken from the (otherwise obsolete) variable `org-todo-interpretation'."
 					 org-todo-interpretation-widgets))
 		      widget))
 		   (repeat
-		    (string :tag "Keyword"))))))
+		    (string :tag "Keyword")))))
+  :safe (lambda (x)
+          (cl-every
+           (lambda (seq)
+             (and (memq (car seq) '(sequence type))
+                  (cl-every (lambda (i) (stringp i)) (cdr seq))))
+           x)))
 
 (defvar-local org-todo-keywords-1 nil
   "All TODO and DONE keywords active in a buffer.")
@@ -4358,10 +4364,9 @@ related expressions."
 				     (cons 'sequence (split-string value)))
 				   (append (cdr (assoc "TODO" alist))
 					   (cdr (assoc "SEQ_TODO" alist)))))
-		   (let ((d (default-value 'org-todo-keywords)))
-		     (if (not (stringp (car d))) d
-		       ;; XXX: Backward compatibility code.
-		       (list (cons org-todo-interpretation d)))))))
+		   (if (not (stringp (car org-todo-keywords))) org-todo-keywords
+		     ;; XXX: Backward compatibility code.
+		     (list (cons org-todo-interpretation org-todo-keywords))))))
 	  (dolist (sequence todo-sequences)
 	    (let* ((sequence (or (run-hook-with-args-until-success
 				  'org-todo-setup-filter-hook sequence)
@@ -4908,7 +4913,18 @@ The following commands are available:
   ;; Try to set `org-hide' face correctly.
   (let ((foreground (org-find-invisible-foreground)))
     (when foreground
-      (set-face-foreground 'org-hide foreground))))
+      (set-face-foreground 'org-hide foreground)))
+
+  (add-hook 'hack-local-variables-hook #'org--process-local-variables nil t))
+
+(defun org--process-local-variables ()
+  "Refresh settings affected by file-local or directory-local variables."
+  (when
+      (let ((local-vars (mapcar #'car file-local-variables-alist)))
+	(or (memq 'org-todo-keywords local-vars)
+	    (memq 'org-todo-keyword-faces local-vars)))
+    (org-set-regexps-and-options)
+    (org-set-font-lock-defaults)))
 
 ;; Update `customize-package-emacs-version-alist'
 (add-to-list 'customize-package-emacs-version-alist
diff --git a/testing/examples/dir-locals/.dir-locals.el b/testing/examples/dir-locals/.dir-locals.el
new file mode 100644
index 000000000..677eaca10
--- /dev/null
+++ b/testing/examples/dir-locals/.dir-locals.el
@@ -0,0 +1,11 @@
+((org-mode
+  . ((org-todo-keywords
+      . ((sequence "TODO" "|" "DONE")
+         (sequence "REPORT" "BUG" "KNOWNCAUSE" "|" "FIXED")
+         (sequence "|" "CANCELED")))
+     (org-todo-keyword-faces
+      . (("REPORT" . org-todo)
+         ("BUG" . warning)
+         ("KNOWNCAUSE" . warning)
+         ("FIXED" . org-done)
+         ("CANCELED" . shadow))))))
diff --git a/testing/examples/dir-locals/todo.org b/testing/examples/dir-locals/todo.org
new file mode 100644
index 000000000..cd06b5ebd
--- /dev/null
+++ b/testing/examples/dir-locals/todo.org
@@ -0,0 +1,8 @@
+#+Title: headings with TODO keywords set in .dir-locals.el
+* TODO heading
+* DONE heading
+* REPORT heading
+* BUG heading
+* KNOWNCAUSE heading
+* FIXED heading
+* CANCELED heading
diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el
index 375e1a718..2adcb2681 100644
--- a/testing/lisp/test-org.el
+++ b/testing/lisp/test-org.el
@@ -7158,6 +7158,38 @@ CLOCK: [2012-03-29 Thu 10:00]--[2012-03-29 Thu 16:40] =>  6:40"
 	(org-todo "DONE")
 	(buffer-string))))))
 
+(ert-deftest test-org/dir-local-todo-keyword-faces ()
+  "Make sure TODO faces honor dir-local variables."
+  (org-test-in-example-file
+      (expand-file-name "dir-locals/todo.org" org-test-example-dir)
+    (font-lock-ensure (point-min) (point-max))
+    (dolist (expected-face '(org-todo
+			     org-done
+			     org-todo
+			     warning
+			     warning
+			     org-done
+			     shadow))
+      (should (equal (get-text-property (+ 2 (point)) 'face)
+		     expected-face))
+      (next-line))))
+
+(ert-deftest test-org/dir-local-todo-cycling ()
+  "Make sure TODO cycling honors dir-local variables."
+  (org-test-in-example-file
+      (expand-file-name "dir-locals/todo.org" org-test-example-dir)
+    (dolist (expected-heading '("* DONE heading"
+				"* heading"
+				"* BUG heading"
+				"* KNOWNCAUSE heading"
+				"* FIXED heading"
+				"* heading"
+				"* heading"))
+      (org-todo)
+      (should (string= (buffer-substring (point) (line-end-position))
+		       expected-heading))
+      (next-line))
+    (revert-buffer t t)))
 \f
 ;;; Timestamps API
 
-- 
2.27.0


[-- Attachment #3: Type: text/plain, Size: 112 bytes --]


Am I on the right track with this patch, or are there problems I haven't
thought of?

Thank you for your time.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, back to index

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-20 21:12 Setting org-todo-keywords through directory-local variables Kévin Le Gouguec
2020-05-21 23:12 ` Kévin Le Gouguec
2020-05-22 15:11   ` Nicolas Goaziou
2020-05-23 12:58     ` Kévin Le Gouguec
2020-06-24 17:54       ` Kévin Le Gouguec
2020-05-22  8:42 ` Nicolas Goaziou

unofficial mirror of emacs-orgmode@gnu.org

Archives are clonable:
	git clone --mirror https://yhetil.org/orgmode/0 orgmode/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 orgmode orgmode/ https://yhetil.org/orgmode \
		emacs-orgmode@gnu.org
	public-inbox-index orgmode

Example config snippet for mirrors

Newsgroups are available over NNTP:
	nntp://news.yhetil.org/yhetil.emacs.orgmode
	nntp://news.gmane.io/gmane.emacs.orgmode


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git