[-- Attachment #1: Type: text/plain, Size: 392 bytes --] Hi All, I've been using inline src blocks a fair bit more recently, and I've thought it's a pity how bad they look as they are currently without fontification. A little digging into Org internals and font-lock later and we have this patch. I could speak about what's been done, but I think a screenshot does a much better comparison. For more details, see the attached patch. -- Timothy [-- Attachment #2: fontify-inline-src.png --] [-- Type: image/png, Size: 132455 bytes --] [-- Attachment #3: 0001-org-src-Implement-native-inline-src-fontification.patch --] [-- Type: text/x-patch, Size: 7361 bytes --] From 563281f8bed02e8ec12e48696ebdd98e61ccfbac Mon Sep 17 00:00:00 2001 From: TEC <tec@tecosaur.com> Date: Wed, 31 Mar 2021 22:30:40 +0800 Subject: [PATCH] org-src: Implement native inline src fontification * lisp/org-src.el (org-fontify-inline-src-blocks, org-fontify-inline-src-blocks-1): Create a function to search the buffer up to a limit for inline src blocks. Light fontification is applied to matched inline src blocks. When `org-src-fontify-natively' is set, `org-src-font-lock-fontify-block' to the content. (org-fontify-inline-src-results): Search for {{{results(...)}}} constructs. Then when `org-inline-src-prettify-results` is non-nil, mimic prettify-symbols and use `compose-region' to substitute visually simpler elements for the wrapping around the value. * lisp/org.el (org-set-font-lock-defaults): Add `org-fontify-inline-src-blocks' to `org-font-lock-extra-keywords', which is locally bound inside `org-set-font-lock-defaults'. (org-inline-src-fontify-max-length, org-inline-src-prettify-results): Create variables for use in the new inline src/result fontification methods in org-src.el. --- lisp/org-src.el | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ lisp/org.el | 21 +++++++++++++- 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/lisp/org-src.el b/lisp/org-src.el index 20acee4e6..9119372d7 100644 --- a/lisp/org-src.el +++ b/lisp/org-src.el @@ -624,6 +624,79 @@ (defun org-src-font-lock-fontify-block (lang start end) '(font-lock-fontified t fontified t font-lock-multiline t)) (set-buffer-modified-p modified))))) +(defun org-fontify-inline-src-blocks (limit) + "Try to apply `org-fontify-inline-src-blocks-1'." + (condition-case nil + (org-fontify-inline-src-blocks-1 limit) + (error (message "Org mode fontification error in %S at %d" + (current-buffer) + (line-number-at-pos))))) + +(defun org-fontify-inline-src-blocks-1 (limit) + "Fontify inline src_LANG blocks, from `point' up to LIMIT." + (let ((case-fold-search t) + (initial-point (point))) + (while (re-search-forward "\\_<src_\\([^ \t\n[{]+\\)[{[]?" limit t) ; copied from `org-element-inline-src-block-parser' + (let ((beg (match-beginning 0)) + (lang-beg (match-beginning 1)) + (lang-end (match-end 1)) + pt) + (remove-text-properties beg lang-end '(face nil)) + (font-lock-append-text-property lang-beg lang-end 'face 'org-meta-line) + (font-lock-append-text-property beg lang-beg 'face 'shadow) + (font-lock-append-text-property beg lang-end 'face 'org-block) + (setq pt (goto-char lang-end)) + ;; `org-element--parse-paired-brackets' doesn't take a limit, so to + ;; prevent it searching the entire rest of the buffer we temporarily + ;; narrow the active region. + (save-restriction + (narrow-to-region beg (min (point-max) + limit + (+ lang-end org-inline-src-fontify-max-length))) + (when (ignore-errors (org-element--parse-paired-brackets ?\[)) + (remove-text-properties pt (point) '(face nil)) + (font-lock-append-text-property pt (point) 'face 'org-block) + (setq pt (point))) + (when (ignore-errors (org-element--parse-paired-brackets ?\{)) + (remove-text-properties pt (point) '(face nil)) + (font-lock-append-text-property pt (1+ pt) 'face '(org-block shadow)) + (unless (= (1+ pt) (1- (point))) + (if org-src-fontify-natively + (org-src-font-lock-fontify-block + (buffer-substring-no-properties lang-beg lang-end) + (1+ pt) (1- (point))) + (font-lock-append-text-property (1+ pt) (1- (point)) 'face 'org-block))) + (font-lock-append-text-property (1- (point)) (point)'face '(org-block shadow)) + (setq pt (point)))) + (when (and org-inline-src-prettify-results + (re-search-forward "\\= {{{results(" limit t)) + (font-lock-append-text-property pt (1+ pt) 'face 'org-block) + (goto-char pt)))) + (when org-inline-src-prettify-results + (goto-char initial-point) + (org-fontify-inline-src-results limit)))) + +(defun org-fontify-inline-src-results (limit) + "Apply prettify-symbols modifications to inline results blocks. +Performed according to `org-inline-src-prettify-results'." + (while (re-search-forward "{{{results(\\(.+?\\))}}}" limit t) + (remove-list-of-text-properties (match-beginning 0) (point) + '(composition + prettify-symbols-start + prettify-symbols-end)) + (font-lock-append-text-property (match-beginning 0) (match-end 0) + 'face 'org-block) + (let ((start (match-beginning 0)) (end (match-beginning 1))) + (with-silent-modifications + (compose-region start end (if (eq org-inline-src-prettify-results t) + "⟨" (car org-inline-src-prettify-results))) + (add-text-properties start end `(prettify-symbols-start ,start prettify-symbols-end ,end)))) + (let ((start (match-end 1)) (end (point))) + (with-silent-modifications + (compose-region start end (if (eq org-inline-src-prettify-results t) + "⟩" (cdr org-inline-src-prettify-results))) + (add-text-properties start end `(prettify-symbols-start ,start prettify-symbols-end ,end)))))) + \f ;;; Escape contents diff --git a/lisp/org.el b/lisp/org.el index 04da1afcd..f4d069504 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -5223,6 +5223,23 @@ (defcustom org-allow-promoting-top-level-subtree nil :version "24.1" :group 'org-appearance) +(defcustom org-inline-src-fontify-max-length 200 + "Maximum content length of an inline src block that will be fontified. +This is only relevant when `org-src-fontify-natively' is t." + :type 'integer + :package-version '(Org . "9.5") + :group 'org-appearance + :group 'org-babel) + +(defcustom org-inline-src-prettify-results t + "Whether to use (ab)use prettify-symbols-mode on {{{results(...)}}}. +Either t or a cons cell of strings which are used as substitutions +for the start and end of inline results, respectively." + :type '(choice boolean (cons string string)) + :package-version '(Org . "9.5") + :group 'org-appearance + :group 'org-babel) + (defun org-fontify-meta-lines-and-blocks (limit) (condition-case nil (org-fontify-meta-lines-and-blocks-1 limit) @@ -5720,7 +5737,9 @@ (defun org-set-font-lock-defaults () org-comment-string) '(9 'org-special-keyword t)) ;; Blocks and meta lines - '(org-fontify-meta-lines-and-blocks)))) + '(org-fontify-meta-lines-and-blocks) + ;; Inline src blocks + '(org-fontify-inline-src-blocks)))) (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords)) (run-hooks 'org-font-lock-set-keywords-hook) ;; Now set the full font-lock-keywords -- 2.30.1
Timothy <tecosaur@gmail.com> writes:
> Hi All,
>
> I've been using inline src blocks a fair bit more recently, and I've
> thought it's a pity how bad they look as they are currently without
> fontification. A little digging into Org internals and font-lock later
> and we have this patch. I could speak about what's been done, but I
> think a screenshot does a much better comparison.
>
> For more details, see the attached patch.
Since this affects font-lock, display performance is obviously a key
concern, and so I have two things to note on that front:
1. I have been using this patch for over a month at this point,
frequently in a ~10k line Org file (my Emacs config), and there has
been no noticeable performance degradation
2. The most expensive part of this is the native syntax highlighting,
which is only used when `org-src-fontify-natively' is t, and the
second most expensive part (results formatting) is only performed
when `org-inline-src-prettify-results' (a new variable) is t.
In brief: I don't anticipate any significant performance implications of
this patch, though of course second opinions would be great :)
--
Timothy
On 2021-03-31 11:00, Timothy wrote:
> I've been using inline src blocks a fair bit more recently, and I've
> thought it's a pity how bad they look as they are currently without
> fontification. A little digging into Org internals and font-lock later
> and we have this patch.
I recall trying inline src blocks once, a year or two ago. I couldn't
get it to work, so I gave up.
Of course I figured I was doing something "wrong" or whatever, so it's
nice to see "it's not just me." :)
So, 3x thanks! One for confirming the bug, and 2 more for actually
providing a solution! I look forward to circling back to it when I
have some time.
Cheers,
TRS-80
It would be good to hear if anyone has been able to test this, and if so what your experience has been :) -- Timothy
Hi Timothy, It seems to work more or less as expected. A few comments below. Best, Tom 1. I think there needs to be a function to toggle org-inline-src-prettify-results as there is e.g. for hyperlinks. I was quite confused by the prettified results. 2. I'm also not sure that this approach to prettify is a good idea. There are issues with unexpected killing/yanking and basic navigation behavior of the prettified text which seem worse than the already troublesome issues with hyperlinks. I'm not sure we can do anything about this though? 3. I'm not sure about the default choice for prettified delimiters. I see there is already a way to customize the delimiters by providing a cons. I think a default value of '("" . "") might be a better choice since ⟨ and ⟩ being hardcoded seems like it introduces completely alien characters. Going with empty strings also seems consistent with the behavior for hyperlinks. 4. There is an interaction with rainbow delimiters that there isn't an easy solution for. I wish there was a syntax type that was "this is a paren for electric pair mode but not for font locking." 5. I'm not sure that the faces selected for src_ and lang are the right ones. Is there any issue with adding new faces specifically for those rather than reusing existing faces? I thought that matching the font locking of #+begin_src lines might make sense, but then I realized that that doesn't make sense because that is for blocks more generally.
Thanks for trying this! Tom Gillespie <tgbugs@gmail.com> writes: > Hi Timothy, > It seems to work more or less as expected. A few comments below. Best, > Tom > > 1. I think there needs to be a function to toggle > org-inline-src-prettify-results as there is e.g. for hyperlinks. I was > quite confused by the prettified results. I see. I imagine the expected behaviour of such a function would be to toggle org-inline-src-prettify-results and redisplay? > 2. I'm also not sure that this approach to prettify is a good idea. > There are issues with unexpected killing/yanking and basic navigation > behavior of the prettified text which seem worse than the already > troublesome issues with hyperlinks. I'm not sure we can do anything > about this though? If there is something that can be done, I'd love to hear about it. I'm no aware of anything though. > 3. I'm not sure about the default choice for prettified delimiters. I > see there is already a way to customize the delimiters by providing a > cons. I think a default value of '("" . "") might be a better choice > since ⟨ and ⟩ being hardcoded seems like it introduces completely > alien characters. Going with empty strings also seems consistent with > the behavior for hyperlinks. Hmmm, yes. Perhaps something else would make for a better default. I'm open to suggestions on this, I just didn't personally like any of the ASCII chars I tried when writing this. > 4. There is an interaction with rainbow delimiters that there isn't an > easy solution for. I wish there was a syntax type that was "this is a > paren for electric pair mode but not for font locking." This sounds like something worth being aware of, that nothing can really (currently) be done about. > 5. I'm not sure that the faces selected for src_ and lang are the > right ones. Is there any issue with adding new faces specifically for > those rather than reusing existing faces? I thought that matching the > font locking of #+begin_src lines might make sense, but then I > realized that that doesn't make sense because that is for blocks more > generally. I don't know if adding faces is a big deal or not, so I tried to pick "sensible choices" from the current set. Further input on this would be appreciated (particularly more people's thoughts). -- Timothy
> I see. I imagine the expected behaviour of such a function would be to
> toggle org-inline-src-prettify-results and redisplay?
Yeah, see org-toggle-link-display for inspiration I think.
;;;###autoload
(defun org-toggle-link-display ()
"Toggle the literal or descriptive display of links."
(interactive)
(if org-link-descriptive (remove-from-invisibility-spec '(org-link))
(add-to-invisibility-spec '(org-link)))
(org-restart-font-lock)
(setq org-link-descriptive (not org-link-descriptive)))
Hi Timothy, Another thought about this. In some languages (e.g. python) blocks require an explicit return by default. It would be nice to be able to set header arguments in the property drawer separately for inline source blocks in such cases. src_python[:prologue "x = (" :epilogue ")\nreturn x"]{1 + 2} {{{results(=3=)}}} A quick review of ob-core and a check of the behavior suggests that there is a concept of inline-header-args, but only for default arguments, and that :inline-header-args:python: does not work. Extending the concept so that inline blocks can have headers set via property drawers separate from regular blocks seems important. Especially because inline blocks can accidentally inherit header-args that are incompatible (e.g. :results list). I don't think these patches depend on that though, so probably better to deal with that separately. Best, Tom
[-- Attachment #1: Type: text/plain, Size: 750 bytes --] Tom Gillespie <tgbugs@gmail.com> writes: > 1. I think there needs to be a function to toggle > org-inline-src-prettify-results as there is e.g. for hyperlinks. I was > quite confused by the prettified results. Added org-toggle-inline-results-display. > 3. I'm not sure about the default choice for prettified delimiters. I > see there is already a way to customize the delimiters by providing a > cons. I think a default value of '("" . "") might be a better choice > since ⟨ and ⟩ being hardcoded seems like it introduces completely > alien characters. Going with empty strings also seems consistent with > the behavior for hyperlinks. Changed to your suggestion. Awaiting others' thoughts on 2. and 5. -- Timothy [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-org-src-Implement-native-inline-src-fontification.patch --] [-- Type: text/x-patch, Size: 7451 bytes --] From 81c56a48ebe516890691420243efe966f3c50eef Mon Sep 17 00:00:00 2001 From: TEC <tec@tecosaur.com> Date: Mon, 3 May 2021 11:16:17 +0800 Subject: [PATCH] org-src: Implement native inline src fontification * lisp/org-src.el (org-fontify-inline-src-blocks, org-fontify-inline-src-blocks-1): Create a function to search the buffer up to a limit for inline src blocks. Light fontification is applied to matched inline src blocks. When `org-src-fontify-natively' is set, `org-src-font-lock-fontify-block' to the content. (org-fontify-inline-src-results): Search for {{{results(...)}}} constructs. Then when `org-inline-src-prettify-results` is non-nil, mimic prettify-symbols and use `compose-region' to substitute visually simpler elements for the wrapping around the value. * lisp/org.el (org-set-font-lock-defaults): Add `org-fontify-inline-src-blocks' to `org-font-lock-extra-keywords', which is locally bound inside `org-set-font-lock-defaults'. (org-inline-src-fontify-max-length, org-inline-src-prettify-results): Create variables for use in the new inline src/result fontification methods in org-src.el. --- lisp/org-src.el | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ lisp/org.el | 21 ++++++++++++- 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/lisp/org-src.el b/lisp/org-src.el index a694e5595..1d09f03a8 100644 --- a/lisp/org-src.el +++ b/lisp/org-src.el @@ -623,6 +623,85 @@ (defun org-src-font-lock-fontify-block (lang start end) '(font-lock-fontified t fontified t font-lock-multiline t)) (set-buffer-modified-p modified))))) +(defun org-fontify-inline-src-blocks (limit) + "Try to apply `org-fontify-inline-src-blocks-1'." + (condition-case nil + (org-fontify-inline-src-blocks-1 limit) + (error (message "Org mode fontification error in %S at %d" + (current-buffer) + (line-number-at-pos))))) + +(defun org-fontify-inline-src-blocks-1 (limit) + "Fontify inline src_LANG blocks, from `point' up to LIMIT." + (let ((case-fold-search t) + (initial-point (point))) + (while (re-search-forward "\\_<src_\\([^ \t\n[{]+\\)[{[]?" limit t) ; copied from `org-element-inline-src-block-parser' + (let ((beg (match-beginning 0)) + (lang-beg (match-beginning 1)) + (lang-end (match-end 1)) + pt) + (remove-text-properties beg lang-end '(face nil)) + (font-lock-append-text-property lang-beg lang-end 'face 'org-meta-line) + (font-lock-append-text-property beg lang-beg 'face 'shadow) + (font-lock-append-text-property beg lang-end 'face 'org-block) + (setq pt (goto-char lang-end)) + ;; `org-element--parse-paired-brackets' doesn't take a limit, so to + ;; prevent it searching the entire rest of the buffer we temporarily + ;; narrow the active region. + (save-restriction + (narrow-to-region beg (min (point-max) + limit + (+ lang-end org-inline-src-fontify-max-length))) + (when (ignore-errors (org-element--parse-paired-brackets ?\[)) + (remove-text-properties pt (point) '(face nil)) + (font-lock-append-text-property pt (point) 'face 'org-block) + (setq pt (point))) + (when (ignore-errors (org-element--parse-paired-brackets ?\{)) + (remove-text-properties pt (point) '(face nil)) + (font-lock-append-text-property pt (1+ pt) 'face '(org-block shadow)) + (unless (= (1+ pt) (1- (point))) + (if org-src-fontify-natively + (org-src-font-lock-fontify-block + (buffer-substring-no-properties lang-beg lang-end) + (1+ pt) (1- (point))) + (font-lock-append-text-property (1+ pt) (1- (point)) 'face 'org-block))) + (font-lock-append-text-property (1- (point)) (point)'face '(org-block shadow)) + (setq pt (point)))) + (when (and org-inline-src-prettify-results + (re-search-forward "\\= {{{results(" limit t)) + (font-lock-append-text-property pt (1+ pt) 'face 'org-block) + (goto-char pt)))) + (when org-inline-src-prettify-results + (goto-char initial-point) + (org-fontify-inline-src-results limit)))) + +(defun org-fontify-inline-src-results (limit) + "Apply prettify-symbols modifications to inline results blocks. +Performed according to `org-inline-src-prettify-results'." + (while (re-search-forward "{{{results(\\(.+?\\))}}}" limit t) + (remove-list-of-text-properties (match-beginning 0) (point) + '(composition + prettify-symbols-start + prettify-symbols-end)) + (font-lock-append-text-property (match-beginning 0) (match-end 0) + 'face 'org-block) + (let ((start (match-beginning 0)) (end (match-beginning 1))) + (with-silent-modifications + (compose-region start end (if (eq org-inline-src-prettify-results t) + "(" (car org-inline-src-prettify-results))) + (add-text-properties start end `(prettify-symbols-start ,start prettify-symbols-end ,end)))) + (let ((start (match-end 1)) (end (point))) + (with-silent-modifications + (compose-region start end (if (eq org-inline-src-prettify-results t) + ")" (cdr org-inline-src-prettify-results))) + (add-text-properties start end `(prettify-symbols-start ,start prettify-symbols-end ,end)))))) + +(defun org-toggle-inline-results-display () + "Toggle the literal or contracted display of inline src blocks results." + (interactive) + (setq org-inline-src-prettify-results (not org-inline-src-prettify-results)) + (org-restart-font-lock)) + \f ;;; Escape contents diff --git a/lisp/org.el b/lisp/org.el index 10eeae514..ab817a0a7 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -5239,6 +5239,23 @@ (defcustom org-allow-promoting-top-level-subtree nil :version "24.1" :group 'org-appearance) +(defcustom org-inline-src-fontify-max-length 200 + "Maximum content length of an inline src block that will be fontified. +This is only relevant when `org-src-fontify-natively' is t." + :type 'integer + :package-version '(Org . "9.5") + :group 'org-appearance + :group 'org-babel) + +(defcustom org-inline-src-prettify-results t + "Whether to use (ab)use prettify-symbols-mode on {{{results(...)}}}. +Either t or a cons cell of strings which are used as substitutions +for the start and end of inline results, respectively." + :type '(choice boolean (cons string string)) + :package-version '(Org . "9.5") + :group 'org-appearance + :group 'org-babel) + (defun org-fontify-meta-lines-and-blocks (limit) (condition-case nil (org-fontify-meta-lines-and-blocks-1 limit) @@ -5739,7 +5756,9 @@ (defun org-set-font-lock-defaults () org-comment-string) '(9 'org-special-keyword t)) ;; Blocks and meta lines - '(org-fontify-meta-lines-and-blocks)))) + '(org-fontify-meta-lines-and-blocks) + ;; Inline src blocks + '(org-fontify-inline-src-blocks)))) (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords)) (run-hooks 'org-font-lock-set-keywords-hook) ;; Now set the full font-lock-keywords -- 2.31.1
If anyone else is interested in this, it would be great to get your
thoughts.
I'd also appreciate it if a core maintainer might be able to find the
time to review the patch and let me know if it looks good.
Thanks,
Timothy.
--
> Tom Gillespie <tgbugs@gmail.com> writes:
>
>> 1. I think there needs to be a function to toggle
>> org-inline-src-prettify-results as there is e.g. for hyperlinks. I was
>> quite confused by the prettified results.
>
> Added org-toggle-inline-results-display.
>
>> 3. I'm not sure about the default choice for prettified delimiters. I
>> see there is already a way to customize the delimiters by providing a
>> cons. I think a default value of '("" . "") might be a better choice
>> since ⟨ and ⟩ being hardcoded seems like it introduces completely
>> alien characters. Going with empty strings also seems consistent with
>> the behavior for hyperlinks.
>
> Changed to your suggestion.
>
> Awaiting others' thoughts on 2. and 5.
Timothy <tecosaur@gmail.com> writes:
> If anyone else is interested in this, it would be great to get your
> thoughts.
I do not like abusing prettify-symbols-mode. What if it is not enabled?
What will happen if user toggles prettify-symbols-mode in Org buffer?
Maybe better use something like org-entities?
Best,
Ihor
Thanks for your response. Ihor Radchenko <yantar92@gmail.com> writes: > I do not like abusing prettify-symbols-mode. What if it is not enabled? Ah, it does it anyway at the moment. > What will happen if user toggles prettify-symbols-mode in Org buffer? This seems to be toggled nicely by prettify-symbols-mode too. > Maybe better use something like org-entities? I'm not sure if that would work, perhaps someone else knows otherwise. -- Timothy
Timothy <tecosaur@gmail.com> writes: >> I do not like abusing prettify-symbols-mode. What if it is not enabled? > > Ah, it does it anyway at the moment. Hmm. You are right. You are calling compose-region directly. Note, that you do not add 'decompose-region function for automatic region destruction (see help:pretty-symbol-pattern-to-keyword). If I understand correctly (I did not really install your patch), if you have composed region, disable font-lock, and try to edit the region, edits will be invisible. Or imagine setting org-inline-src-prettify-results to nil in already fontified buffer. Also, you may find help:font-lock-extra-managed-props useful. That way, you will not have to manually remove composition and other non-standard properties during fontification (why are you even removing 'face? It should be already done by font-lock). >> What will happen if user toggles prettify-symbols-mode in Org buffer? > > This seems to be toggled nicely by prettify-symbols-mode too. I would not expect it to. Why would prettify-symbols-mode interfere with Org mode native fontification if it is not strictly necessary? P.S. Nitpick: You do not need to run fontification in while loops. Just fontifying next match before limit should be enough. Font-lock will call the function again if needed. Best, Ihor
Thank you for the detailed feedback :) Ihor Radchenko <yantar92@gmail.com> writes: > Timothy <tecosaur@gmail.com> writes: > >>> I do not like abusing prettify-symbols-mode. What if it is not enabled? If you know of another way of accomplishing text-replacement which changes back when the cursor enters the region, please let me know. >> Ah, it does it anyway at the moment. > > Hmm. You are right. You are calling compose-region directly. Note, that > you do not add 'decompose-region function for automatic region > destruction (see help:pretty-symbol-pattern-to-keyword). Isn't the same effect achieved by the remove-list-of-text-properties call? > If I understand correctly (I did not really install your patch), if you have > composed region, disable font-lock, and try to edit the region, edits > will be invisible. Or imagine setting org-inline-src-prettify-results to > nil in already fontified buffer. I just tried "setting org-inline-src-prettify-results to nil in already fontified buffer." and the region just decomposed and stayed that way. > Also, you may find help:font-lock-extra-managed-props useful. That way, > you will not have to manually remove composition and other non-standard > properties during fontification Hmmm, from a look I can't tell exactly how these are "managed". Are they just removed when a region is processed? > why are you even removing 'face? It should be already done by font-lock). I tried removing such calls, and everything still worked, so this is no longer done. >>> What will happen if user toggles prettify-symbols-mode in Org buffer? >> >> This seems to be toggled nicely by prettify-symbols-mode too. > > I would not expect it to. Why would prettify-symbols-mode interfere with > Org mode native fontification if it is not strictly necessary? Well, I guess this is a by-product of using prettify-symbols-start/end, see my note at the start of this email about not being aware of anything else. > P.S. Nitpick: You do not need to run fontification in while loops. Just > fontifying next match before limit should be enough. Font-lock will call > the function again if needed. I'm guessing for this to work I'd need to return the final char fortified? Or is the moving of point enough? Maybe related - I've noticed this doesn't seem to work with multiple src_ blocks per line, might you have any insight here? Thanks, Timothy
Timothy <tecosaur@gmail.com> writes:
> Thank you for the detailed feedback :)
>
> Ihor Radchenko <yantar92@gmail.com> writes:
>
>> Timothy <tecosaur@gmail.com> writes:
>>
>>>> I do not like abusing prettify-symbols-mode. What if it is not enabled?
>
> If you know of another way of accomplishing text-replacement which
> changes back when the cursor enters the region, please let me know.
>
>>> Ah, it does it anyway at the moment.
>>
>> Hmm. You are right. You are calling compose-region directly. Note, that
>> you do not add 'decompose-region function for automatic region
>> destruction (see help:pretty-symbol-pattern-to-keyword).
>
> Isn't the same effect achieved by the remove-list-of-text-properties call?
>
>> If I understand correctly (I did not really install your patch), if you have
>> composed region, disable font-lock, and try to edit the region, edits
>> will be invisible. Or imagine setting org-inline-src-prettify-results to
>> nil in already fontified buffer.
>
> I just tried "setting org-inline-src-prettify-results to nil in already
> fontified buffer." and the region just decomposed and stayed that way.
>
>> Also, you may find help:font-lock-extra-managed-props useful. That way,
>> you will not have to manually remove composition and other non-standard
>> properties during fontification
>
> Hmmm, from a look I can't tell exactly how these are "managed". Are they
> just removed when a region is processed?
>
>> why are you even removing 'face? It should be already done by font-lock).
>
> I tried removing such calls, and everything still worked, so this is no
> longer done.
>
>>>> What will happen if user toggles prettify-symbols-mode in Org buffer?
>>>
>>> This seems to be toggled nicely by prettify-symbols-mode too.
>>
>> I would not expect it to. Why would prettify-symbols-mode interfere with
>> Org mode native fontification if it is not strictly necessary?
>
> Well, I guess this is a by-product of using prettify-symbols-start/end,
> see my note at the start of this email about not being aware of anything else.
>
>> P.S. Nitpick: You do not need to run fontification in while loops. Just
>> fontifying next match before limit should be enough. Font-lock will call
>> the function again if needed.
>
> I'm guessing for this to work I'd need to return the final char
> fortified? Or is the moving of point enough?
>
> Maybe related - I've noticed this doesn't seem to work with multiple
> src_ blocks per line, might you have any insight here?
>
>
This may or may not be something to consider but ...
What is the impact of using this technique for accessibility and users
of assistive technology like text-to-speech or braille displays?
I'm currently not in the position to test this patch, but once I get
some environments for testing sorted out, I should be able to try it
out.
From an accessibility perspective, behaviour which changes what is
'displayed' based on cursor position is often confusing for things like
text-to-speech. In the past, I have run into issues with prettify
symbols because it results in either less meaningful content (e.g.
unicode numbers rather than defined character names) or additional
spoken text which makes it difficult to understand. Things like
overlays, tooltips or features which make display different from
underlying character content can often be problematic with assistive
technology.
--
Tim Cross
Timothy <tecosaur@gmail.com> writes: >>>> I do not like abusing prettify-symbols-mode. What if it is not enabled? > > If you know of another way of accomplishing text-replacement which > changes back when the cursor enters the region, please let me know. cursor-sensor-mode >>> Ah, it does it anyway at the moment. >> >> Hmm. You are right. You are calling compose-region directly. Note, that >> you do not add 'decompose-region function for automatic region >> destruction (see help:pretty-symbol-pattern-to-keyword). > > Isn't the same effect achieved by the remove-list-of-text-properties call? It is. Though only while font-lock is active. Now, looking at prettify-symbols-mode code, it does not seem to be necessary when font-locking is set correctly. >> If I understand correctly (I did not really install your patch), if you have >> composed region, disable font-lock, and try to edit the region, edits >> will be invisible. Or imagine setting org-inline-src-prettify-results to >> nil in already fontified buffer. > > I just tried "setting org-inline-src-prettify-results to nil in already > fontified buffer." and the region just decomposed and stayed that way. Did you also have prettify-symbols-mode disabled? >> Also, you may find help:font-lock-extra-managed-props useful. That way, >> you will not have to manually remove composition and other non-standard >> properties during fontification > > Hmmm, from a look I can't tell exactly how these are "managed". Are they > just removed when a region is processed? They are removed just before the region is processed and they are removed when font-lock-mode is disabled. On the other hand, it will not be possible to set the managed properties directly (try setting font using a direct M-: command in a buffer with font-lock enabled). >> P.S. Nitpick: You do not need to run fontification in while loops. Just >> fontifying next match before limit should be enough. Font-lock will call >> the function again if needed. > > I'm guessing for this to work I'd need to return the final char > fortified? Or is the moving of point enough? > > Maybe related - I've noticed this doesn't seem to work with multiple > src_ blocks per line, might you have any insight here? As I understand, the fontificatoin function must behave like re-search-forward. From font-lock-keywords docstring: >>> ... MATCHER can be either the regexp to search for, or the function >>> name to call to make the search (called with one argument, the limit >>> of the search; it should return non-nil, move point, and set >>> `match-data' appropriately if it succeeds; like `re-search-forward' >>> would). Best, Ihor
[-- Attachment #1: Type: text/plain, Size: 2413 bytes --] Hi Timothy, Thanks for your work. I hope this can be merged. Here are a few comments. Doesn't this line in ~org-toggle-inline-results-display~ throw the configured delimiters away when called twice ? : (setq org-inline-src-prettify-results (not org-inline-src-prettify-results)) I think the =org-block= face should only be applied to the actual code, note the =src_lang= part, nor the result. For normal src blocks, it is only used inside the block. The ~org-src-font-lock-fontify-block~ function could be modified to take an optional =inline= argument. When =t=, it should not set the =multiline= font property. Although this is very minor, it would allow one to easily advice this function to behave differently in inline src blocks. For example, to not use the =org-block= face in this case. I think the default parenthesis pair around results are bad. I much preferred your original brackets. Yes, as Tom said, they look alien, but alien is appropriate for use of ~prettify-symbols~. Since ~prettify-symbols~ seems to be raising some usability concerns, perhaps ~org-inline-src-prettify-results~ should default to ~nil~. It'd be unlike org to hide things from the user in the default configuration. As Tom points out, the two faces used (for the =src_= and bracket and the language part) should be customizable. The default value you chose are fine IMO. Perhaps the language one could also be used to highlight the language of normal src blocks, though It might be easier to use a single face. Timothy writes: >> P.S. Nitpick: You do not need to run fontification in while loops. Just >> fontifying next match before limit should be enough. Font-lock will call >> the function again if needed. > I'm guessing for this to work I'd need to return the final char > fortified? Or is the moving of point enough? > > Maybe related - I've noticed this doesn't seem to work with multiple > src_ blocks per line, might you have any insight here? You need only return =t= if some fontification has been done (and set point after the fontified part). If your function returns =t=, it will be called again. A case can be made for keeping the loop though. It works fine and is clearer since the aforementioned fontlock behaviour is poorly documented. Really, the only downside is the loss of consistency, since the function ~org-fontify-meta-lines-and-blocks-1~ doesn't loop. Regards, -- Sébastien Miquel [-- Attachment #2: Type: text/html, Size: 3514 bytes --]
[-- Attachment #1: Type: text/plain, Size: 969 bytes --] Hi Sébastien, thanks for your comments. Sébastien Miquel <sebastien.miquel@posteo.eu> writes: > Hi Timothy, > > Thanks for your work. I hope this can be merged. :) > Here are a few comments. > > Doesn't this line in ~org-toggle-inline-results-display~ throw the > configured delimiters away when called twice ? > : (setq org-inline-src-prettify-results (not org-inline-src-prettify-results)) > > I think the =org-block= face should only be applied to the actual > code, note the =src_lang= part, nor the result. For normal src blocks, > it is only used inside the block. In src blocks, you have the org-block-begin-line face applied. This (in any sensible theme) has the same background as org-block. For the sake of visual consistency, I think we want to have this applied to the src_lang and result parts too. However, the org-block-begin-line face overly fades the text, and so I've combined the org-block face with other faces. [-- Attachment #2: inline-src-back.png --] [-- Type: image/png, Size: 9480 bytes --] [-- Attachment #3: Type: text/plain, Size: 2642 bytes --] > The ~org-src-font-lock-fontify-block~ function could be modified to > take an optional =inline= argument. When =t=, it should not set the > =multiline= font property. Although this is very minor, it would allow > one to easily advice this function to behave differently in inline src > blocks. For example, to not use the =org-block= face in this case. I don't see where the multiline property is currently set, would you mind pointing it out to me? > I think the default parenthesis pair around results are bad. I much > preferred your original brackets. Yes, as Tom said, they look alien, > but alien is appropriate for use of ~prettify-symbols~. I'm going to be using the original symbols in my configuration anyway because I think they're nicer, but clearly this is contentious. I'd want to hear from more people on this. > Since ~prettify-symbols~ seems to be raising some usability concerns, > perhaps ~org-inline-src-prettify-results~ should default to ~nil~. > It'd be unlike org to hide things from the user in the default > configuration. This seems somewhat sensible to me, but I must say that {{{results()}}} is /ugly/ and I suspect that many users would like the effect, but a minority will be aware of this option. Perhaps this is worth doing anyway. > As Tom points out, the two faces used (for the =src_= and bracket and > the language part) should be customizable. The default value you chose > are fine IMO. Perhaps the language one could also be used to highlight > the language of normal src blocks, though It might be easier to use a > single face. So are you suggesting I do or don't create new faces for this? > Timothy writes: >>> P.S. Nitpick: You do not need to run fontification in while loops. Just >>> fontifying next match before limit should be enough. Font-lock will call >>> the function again if needed. >> I'm guessing for this to work I'd need to return the final char >> fortified? Or is the moving of point enough? >> >> Maybe related - I've noticed this doesn't seem to work with multiple >> src_ blocks per line, might you have any insight here? > > You need only return =t= if some fontification has been done (and set > point after the fontified part). If your function returns =t=, it will > be called again. > > A case can be made for keeping the loop though. It works fine and is > clearer since the aforementioned fontlock behaviour is poorly > documented. Really, the only downside is the loss of consistency, since > the function ~org-fontify-meta-lines-and-blocks-1~ doesn't loop. Returning t works nicely, and now we can highlight more than one inline src per line :) -- Timothy
[-- Attachment #1: Type: text/plain, Size: 2222 bytes --] Timothy writes: > In src blocks, you have the org-block-begin-line face applied. This (in > any sensible theme) has the same background as org-block. I might be confused by my own config, but that doesn't seem to be the case. Unless customized, the =org-block-begin-line= inherits from org-meta-line, and the org-block documentation does specify that it applies *inside* blocks. I personaly dislike any inline change of background color. It makes some sense for the python code, since it isn't org anymore (indeed, the fontification is done in another buffer), but the src_lang, and the result part are just org syntax. Here's an example of a reasonable -- I hope -- use of those faces. >> The ~org-src-font-lock-fontify-block~ function could be modified to >> take an optional =inline= argument. When =t=, it should not set the >> =multiline= font property. Although this is very minor, it would allow >> one to easily advice this function to behave differently in inline src >> blocks. For example, to not use the =org-block= face in this case. > I don't see where the multiline property is currently set, would you mind > pointing it out to me? Right at the end of ~org-src-font-lock-fontify-block~. The property is =font-lock-multiline=. > I'm going to be using the original symbols in my configuration anyway > because I think they're nicer, but clearly this is contentious. I'd want > to hear from more people on this. If results prettification were disabled by default, There would be much less contention. >> Since ~prettify-symbols~ seems to be raising some usability concerns, >> perhaps ~org-inline-src-prettify-results~ should default to ~nil~. >> It'd be unlike org to hide things from the user in the default >> configuration. > This seems somewhat sensible to me, but I must say that {{{results()}}} > is /ugly/ and I suspect that many users would like the effect, but a > minority will be aware of this option. Perhaps this is worth doing > anyway. I agree. But org-mode is ugly by default, so that is consistent. > So are you suggesting I do or don't create new faces for this? You should create new faces yes. I do not know whether one or two faces is best. Regards, -- Sébastien Miquel [-- Attachment #2.1: Type: text/html, Size: 3880 bytes --] [-- Attachment #2.2: src-block-faces.png --] [-- Type: image/png, Size: 9092 bytes --]
Timothy <tecosaur@gmail.com> writes:
> Hi All,
>
> I've been using inline src blocks a fair bit more recently, and I've
> thought it's a pity how bad they look as they are currently without
> fontification. A little digging into Org internals and font-lock later
> and we have this patch. I could speak about what's been done, but I
> think a screenshot does a much better comparison.
Let me bump this thread again and mark it as a patch ;)
Ihor Radchenko <yantar92@gmail.com> writes:
> Let me bump this thread again and mark it as a patch ;)
Thanks for the bump. I'd like to get this working, but I don't know how best to
deal with the "prettification" of {{{results(=value=)}}}, which is the major blocker as I
see it.
Other than that, this all works fantastically as far as I can tell from a few
months of usage of my branch of Org 🙂.
--
Timothy
Timothy <tecosaur@gmail.com> writes:
> Ihor Radchenko <yantar92@gmail.com> writes:
>
>> Let me bump this thread again and mark it as a patch ;)
>
> Thanks for the bump. I'd like to get this working, but I don't know how best to
> deal with the "prettification" of {{{results(=value=)}}}, which is the major blocker as I
> see it.
What about separating the src_{} fontification into separate patch? I
think that part raised no objections.
As for the results prettifications, I look at this and similar ideas as
at Emacs themes. It looks nice on your screenshot with your fonts and
colours, but may not be good for other people. Similar to org-bullets
and co.
I can see how some people (I am among those people) want to reduce the
markup noise beyond hiding emphasis markers. However, some people
prefer not to hide text in buffer under "bells and whistles". Maybe we
can create some kind of "prettify-symbol themes" replacing different
markup elements in bulk with nice symbols/svg (e.g. inline results,
block headers/footers, uninteresting property drawers aka
org-custom-properties, bullets, etc)?
WDYT?
Also, CCing Prot as it might be of interest for him.
Best,
Ihor
[-- Attachment #1: Type: text/plain, Size: 1864 bytes --] Hi Ihor, > What about separating the src_{nil} fontification into separate patch? I > think that part raised no objections. That sounds like a good idea to me. We may as well get that in. > As for the results prettifications, I look at this and similar ideas as > at Emacs themes. It looks nice on your screenshot with your fonts and > colours, but may not be good for other people. Similar to org-bullets > and co. The behaviour makes me think of link prettification more than what Emacs themes do. Hiding the text {{{results( with an overlay seems like something a major/minor mode should be responsible for, not a theme. > I can see how some people (I am among those people) want to reduce the > markup noise beyond hiding emphasis markers. However, some people > prefer not to hide text in buffer under “bells and whistles”. Indeed, and it’s good to have this option. This is why I also introduced a new setting, `org-inline-src-prettify-results' (similarly named to `org-pretty-entities'). > Maybe we can create some kind of “prettify-symbol themes” replacing different > markup elements in bulk with nice symbols/svg (e.g. inline results, block > headers/footers, uninteresting property drawers aka org-custom-properties, > bullets, etc)? WDYT? Also, CCing Prot as it might be of interest for him. > Best, Ihor I think it could make sense for some prettification capabilities to be built into Org well. Currently there are a few little things we have, but it seems to be handled inconsistently and I think it could be nice to provide a more unified approach. There are also things like <https://github.com/awth13/org-appear/blob/master/org-appear.el> which I feel just make a lot of sense with Org (you never have to guess if `point' is before or after a markup character). All the best, Timothy
On 2021-10-03, 17:09 +0800, Ihor Radchenko <yantar92@gmail.com> wrote: > Timothy <tecosaur@gmail.com> writes: > >> Ihor Radchenko <yantar92@gmail.com> writes: >> >>> Let me bump this thread again and mark it as a patch ;) >> >> Thanks for the bump. I'd like to get this working, but I don't know how best to >> deal with the "prettification" of {{{results(=value=)}}}, which is the major blocker as I >> see it. > > What about separating the src_{} fontification into separate patch? I > think that part raised no objections. > > As for the results prettifications, I look at this and similar ideas as > at Emacs themes. It looks nice on your screenshot with your fonts and > colours, but may not be good for other people. Similar to org-bullets > and co. > > I can see how some people (I am among those people) want to reduce the > markup noise beyond hiding emphasis markers. However, some people > prefer not to hide text in buffer under "bells and whistles". Maybe we > can create some kind of "prettify-symbol themes" replacing different > markup elements in bulk with nice symbols/svg (e.g. inline results, > block headers/footers, uninteresting property drawers aka > org-custom-properties, bullets, etc)? > WDYT? > > Also, CCing Prot as it might be of interest for him. Thank you! I am monitoring the discussion in case there is something I would need to do for my themes. Otherwise I have no technical insight to offer about the substance of this feature. With regard to the use of faces, I generally find that re-purposing faces in an altogether different context than their original can create constraints for users/themes. For example, and without having tried the patch yet, we find this:[1] (font-lock-append-text-property beg lang-end 'face 'org-block) Is the text-to-be-propertised the same as an Org block or does it differ in purpose/presentation? Because a user/theme may like their blocks to e.g. have no background of their own, but also wish to maintain a distinct background colour for inline constructs like org-verbatim, org-code, and those discussed here. The rationale would be that blocks are clear enough due to their innate spacing and indentation, whereas inline constructs are surrounded by text. This is not a hard requirement, of course, while too many overly specific faces can also prove problematic for testing/maintenance. Just something for you to bear in mind. Finally, how does the use of 'org-block' in this context relate to 'org-src-block-faces'? Could there be undesired conflicts in styling or whatnot? All the best, Prot [1] <https://list.orgmode.org/87pmzf4bd0.fsf@gmail.com/> -- Protesilaos Stavrou https://protesilaos.com
[-- Attachment #1: Type: text/plain, Size: 477 bytes --] Hi All, Since the contentious component of my previous patches has been the `{{{results()}}}' prettification, I’ve prepared an alternate version that I’m hoping everybody will be fairly happy with (fingers crossed!) that tosses out the results prettification for now. I think Protesilaos’ comments on making some new faces deserve consideration, but could easily be done subsequently, as I’m quite keen to get this merged for now. All the best, Timothy [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-org-src-Implement-native-inline-src-fontification.patch --] [-- Type: text/x-patch, Size: 5149 bytes --] From 53d2851e248c4f4e4076878a999cbf647b401578 Mon Sep 17 00:00:00 2001 From: TEC <tec@tecosaur.com> Date: Tue, 13 Jul 2021 02:43:29 +0800 Subject: [PATCH] org-src: Implement native inline src fontification * lisp/org-src.el (org-fontify-inline-src-blocks, org-fontify-inline-src-blocks-1): Create a function to search the buffer up to a limit for inline src blocks. Light fontification is applied to matched inline src blocks. When `org-src-fontify-natively' is set, `org-src-font-lock-fontify-block' is applied to the content. * lisp/org.el (org-set-font-lock-defaults): Add `org-fontify-inline-src-blocks' to `org-font-lock-extra-keywords', which is locally bound inside `org-set-font-lock-defaults'. (org-inline-src-fontify-max-length): Create a variable to limit the maximum length of an inline-src block fontified, to protect from lag spikes (e.g. when typing out src_lang{ and half of the buffer is fontified). --- lisp/org-src.el | 46 ++++++++++++++++++++++++++++++++++++++++++++++ lisp/org.el | 18 ++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/lisp/org-src.el b/lisp/org-src.el index 51dde602d..c3a6a40bc 100644 --- a/lisp/org-src.el +++ b/lisp/org-src.el @@ -654,6 +654,52 @@ (defun org-src-font-lock-fontify-block (lang start end) '(font-lock-fontified t fontified t font-lock-multiline t)) (set-buffer-modified-p modified))))) +(defun org-fontify-inline-src-blocks (limit) + "Try to apply `org-fontify-inline-src-blocks-1'." + (condition-case nil + (progn + (org-fontify-inline-src-blocks-1 limit) + (org-fontify-inline-src-results limit)) + (error (message "Org mode fontification error in %S at %d" + (current-buffer) + (line-number-at-pos))))) + +(defun org-fontify-inline-src-blocks-1 (limit) + "Fontify inline src_LANG blocks, from `point' up to LIMIT." + (let ((case-fold-search t) + (initial-point (point))) + (when (re-search-forward "\\_<src_\\([^ \t\n[{]+\\)[{[]?" limit t) ; copied from `org-element-inline-src-block-parser' + (let ((beg (match-beginning 0)) + (lang-beg (match-beginning 1)) + (lang-end (match-end 1)) + pt) + (font-lock-append-text-property lang-beg lang-end 'face 'org-meta-line) + (font-lock-append-text-property beg lang-beg 'face 'shadow) + (font-lock-append-text-property beg lang-end 'face 'org-block) + (setq pt (goto-char lang-end)) + ;; `org-element--parse-paired-brackets' doesn't take a limit, so to + ;; prevent it searching the entire rest of the buffer we temporarily + ;; narrow the active region. + (save-restriction + (narrow-to-region beg (min (point-max) + limit + (+ lang-end org-inline-src-fontify-max-length))) + (when (ignore-errors (org-element--parse-paired-brackets ?\[)) + (font-lock-append-text-property pt (point) 'face 'org-block) + (setq pt (point))) + (when (ignore-errors (org-element--parse-paired-brackets ?\{)) + (remove-text-properties pt (point) '(face nil)) + (font-lock-append-text-property pt (1+ pt) 'face '(org-block shadow)) + (unless (= (1+ pt) (1- (point))) + (if org-src-fontify-natively + (org-src-font-lock-fontify-block + (buffer-substring-no-properties lang-beg lang-end) + (1+ pt) (1- (point))) + (font-lock-append-text-property (1+ pt) (1- (point)) 'face 'org-block))) + (font-lock-append-text-property (1- (point)) (point)'face '(org-block shadow)) + (setq pt (point))))) + t))) + \f ;;; Escape contents diff --git a/lisp/org.el b/lisp/org.el index eeefb4af3..6a424991c 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -5279,6 +5279,23 @@ (defcustom org-allow-promoting-top-level-subtree nil :version "24.1" :group 'org-appearance) +(defcustom org-inline-src-fontify-max-length 200 + "Maximum content length of an inline src block that will be fontified. +This is only relevant when `org-src-fontify-natively' is t." + :type 'integer + :package-version '(Org . "9.5") + :group 'org-appearance + :group 'org-babel) + +(defcustom org-inline-src-prettify-results t + "Whether to use (ab)use prettify-symbols-mode on {{{results(...)}}}. +Either t or a cons cell of strings which are used as substitutions +for the start and end of inline results, respectively." + :type '(choice boolean (cons string string)) + :package-version '(Org . "9.5") + :group 'org-appearance + :group 'org-babel) + (defun org-fontify-meta-lines-and-blocks (limit) (condition-case nil (org-fontify-meta-lines-and-blocks-1 limit) @@ -5785,6 +5802,7 @@ (defun org-set-font-lock-defaults () '(9 'org-special-keyword t)) ;; Blocks and meta lines '(org-fontify-meta-lines-and-blocks) + '(org-fontify-inline-src-blocks) ;; Citations '(org-cite-activate)))) (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords)) -- 2.33.1
[-- Attachment #1: Type: text/plain, Size: 439 bytes --] Hi Everyone, I think there’s room in the future to add more faces for this, but I it occurs to me that the main complaint raised in this thread can be resolved by adding one new face: `org-inline-src-block' (which inherits from `org-block') by default. See attached for a patch which just adds this face. I feel like this might be the final version of this patch so I’d appreciate thoughts on this. All the best, Timothy [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-org-src-Implement-native-inline-src-fontification.patch --] [-- Type: text/x-patch, Size: 5915 bytes --] From 133b7a90853f7f9062bae40af2efc8fd22781125 Mon Sep 17 00:00:00 2001 From: TEC <tec@tecosaur.com> Date: Tue, 13 Jul 2021 02:43:29 +0800 Subject: [PATCH] org-src: Implement native inline src fontification * lisp/org-src.el (org-fontify-inline-src-blocks, org-fontify-inline-src-blocks-1): Create a function to search the buffer up to a limit for inline src blocks. Light fontification is applied to matched inline src blocks. When `org-src-fontify-natively' is set, `org-src-font-lock-fontify-block' is applied to the content. * lisp/org.el (org-set-font-lock-defaults): Add `org-fontify-inline-src-blocks' to `org-font-lock-extra-keywords', which is locally bound inside `org-set-font-lock-defaults'. (org-inline-src-fontify-max-length): Create a variable to limit the maximum length of an inline-src block fontified, to protect from lag spikes (e.g. when typing out src_lang{ and half of the buffer is fontified). * lisp/org-faces.el: Introduce a new face `org-inline-src-block' which inherits from `org-block' by default. --- lisp/org-faces.el | 4 ++++ lisp/org-src.el | 46 ++++++++++++++++++++++++++++++++++++++++++++++ lisp/org.el | 18 ++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/lisp/org-faces.el b/lisp/org-faces.el index b151045a9..272762789 100644 --- a/lisp/org-faces.el +++ b/lisp/org-faces.el @@ -459,6 +459,10 @@ (defface org-block-end-line '((t (:inherit org-block-begin-line))) "Face used for the line delimiting the end of source blocks." :group 'org-faces) +(defface org-inline-src-block '((t (:inherit org-block))) + "Face used for inline source blocks as a whole." + :group 'org-faces) + (defface org-verbatim '((t (:inherit (fixed-pitch shadow)))) "Face for fixed-with text like code snippets." :group 'org-faces diff --git a/lisp/org-src.el b/lisp/org-src.el index 51dde602d..f2aff1f43 100644 --- a/lisp/org-src.el +++ b/lisp/org-src.el @@ -654,6 +654,52 @@ (defun org-src-font-lock-fontify-block (lang start end) '(font-lock-fontified t fontified t font-lock-multiline t)) (set-buffer-modified-p modified))))) +(defun org-fontify-inline-src-blocks (limit) + "Try to apply `org-fontify-inline-src-blocks-1'." + (condition-case nil + (progn + (org-fontify-inline-src-blocks-1 limit) + (org-fontify-inline-src-results limit)) + (error (message "Org mode fontification error in %S at %d" + (current-buffer) + (line-number-at-pos))))) + +(defun org-fontify-inline-src-blocks-1 (limit) + "Fontify inline src_LANG blocks, from `point' up to LIMIT." + (let ((case-fold-search t) + (initial-point (point))) + (while (re-search-forward "\\_<src_\\([^ \t\n[{]+\\)[{[]?" limit t) ; copied from `org-element-inline-src-block-parser' + (let ((beg (match-beginning 0)) + (lang-beg (match-beginning 1)) + (lang-end (match-end 1)) + pt) + (font-lock-append-text-property lang-beg lang-end 'face 'org-meta-line) + (font-lock-append-text-property beg lang-beg 'face 'shadow) + (font-lock-append-text-property beg lang-end 'face 'org-inline-src-block) + (setq pt (goto-char lang-end)) + ;; `org-element--parse-paired-brackets' doesn't take a limit, so to + ;; prevent it searching the entire rest of the buffer we temporarily + ;; narrow the active region. + (save-restriction + (narrow-to-region beg (min (point-max) + limit + (+ lang-end org-inline-src-fontify-max-length))) + (when (ignore-errors (org-element--parse-paired-brackets ?\[)) + (font-lock-append-text-property pt (point) 'face 'org-inline-src-block) + (setq pt (point))) + (when (ignore-errors (org-element--parse-paired-brackets ?\{)) + (remove-text-properties pt (point) '(face nil)) + (font-lock-append-text-property pt (1+ pt) 'face '(org-block shadow)) + (unless (= (1+ pt) (1- (point))) + (if org-src-fontify-natively + (org-src-font-lock-fontify-block + (buffer-substring-no-properties lang-beg lang-end) + (1+ pt) (1- (point))) + (font-lock-append-text-property (1+ pt) (1- (point)) 'face 'org-inline-src-block))) + (font-lock-append-text-property (1- (point)) (point)'face '(org-inline-src-block shadow)) + (setq pt (point))))) + t))) + \f ;;; Escape contents diff --git a/lisp/org.el b/lisp/org.el index 331bd9f65..fc2ec622f 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -5279,6 +5279,23 @@ (defcustom org-allow-promoting-top-level-subtree nil :version "24.1" :group 'org-appearance) +(defcustom org-inline-src-fontify-max-length 200 + "Maximum content length of an inline src block that will be fontified. +This is only relevant when `org-src-fontify-natively' is t." + :type 'integer + :package-version '(Org . "9.5") + :group 'org-appearance + :group 'org-babel) + +(defcustom org-inline-src-prettify-results t + "Whether to use (ab)use prettify-symbols-mode on {{{results(...)}}}. +Either t or a cons cell of strings which are used as substitutions +for the start and end of inline results, respectively." + :type '(choice boolean (cons string string)) + :package-version '(Org . "9.5") + :group 'org-appearance + :group 'org-babel) + (defun org-fontify-meta-lines-and-blocks (limit) (condition-case nil (org-fontify-meta-lines-and-blocks-1 limit) @@ -5785,6 +5802,7 @@ (defun org-set-font-lock-defaults () '(9 'org-special-keyword t)) ;; Blocks and meta lines '(org-fontify-meta-lines-and-blocks) + '(org-fontify-inline-src-blocks) ;; Citations '(org-cite-activate)))) (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords)) -- 2.33.1
Timothy <tecosaur@gmail.com> writes: > See attached for a patch which just adds this face. I feel like this might be > the final version of this patch so I’d appreciate thoughts on this. I have some comments. See below. > (org-inline-src-fontify-max-length): Create a variable to limit the > maximum length of an inline-src block fontified, to protect from lag > spikes (e.g. when typing out src_lang{ and half of the buffer is > fontified). I do not like this. Even with this variable, some part of buffer may be spuriously fontified. Maybe you just verify that you are at actual inline-src block by examining org-element-context? > +(defun org-fontify-inline-src-blocks (limit) > + "Try to apply `org-fontify-inline-src-blocks-1'." > + (condition-case nil > + (progn > + (org-fontify-inline-src-blocks-1 limit) > + (org-fontify-inline-src-results limit)) org-fontify-inline-src-results is not defined in this patch. > + (font-lock-append-text-property lang-beg lang-end 'face 'org-meta-line) > + (font-lock-append-text-property beg lang-beg 'face 'shadow) > + (font-lock-append-text-property beg lang-end 'face 'org-inline-src-block) Is there some special reason why you apply both 'shadow and 'org-inline-src-block? What about 'org-meta-line face? Maybe 'org-meta-line should not be hard-coded? > + (setq pt (goto-char lang-end)) > + ;; `org-element--parse-paired-brackets' doesn't take a limit, so to > + ;; prevent it searching the entire rest of the buffer we temporarily > + ;; narrow the active region. > + (save-restriction > + (narrow-to-region beg (min (point-max) > + limit > + (+ lang-end org-inline-src-fontify-max-length))) > + (when (ignore-errors (org-element--parse-paired-brackets ?\[)) > + (font-lock-append-text-property pt (point) 'face 'org-inline-src-block) > + (setq pt (point))) > + (when (ignore-errors (org-element--parse-paired-brackets ?\{)) It looks like you are repeating the job of org-element-context here. Why don't you just get the proper object? > + (remove-text-properties pt (point) '(face nil)) > + (font-lock-append-text-property pt (1+ pt) 'face '(org-block shadow)) Do you really intend to use 'org-block and 'shadow faces here? Not 'org-inline-src-block? > +(defcustom org-inline-src-prettify-results t Looks like a stray defcustom. At least, it is not mentioned in the commit message and not used within the patch. Best, Ihor
[-- Attachment #1: Type: text/plain, Size: 3725 bytes --] Hi Ihor, > I have some comments. See below. Thanks for going through this, and for all your help previously. I appreciate it :) >> (org-inline-src-fontify-max-length): Create a variable to limit the >> maximum length of an inline-src block fontified, to protect from lag >> spikes (e.g. when typing out src_lang{ and half of the buffer is >> fontified). > > I do not like this. Even with this variable, some part of buffer may be > spuriously fontified. Maybe you just verify that you are at actual > inline-src block by examining org-element-context? The description may need updating, as that’s a tad inaccurate. That value actually limits how far forwards a paired paren is searched for. There’s no spurious fontification. >> +(defun org-fontify-inline-src-blocks (limit) >> + “Try to apply `org-fontify-inline-src-blocks-1’.” >> + (condition-case nil >> + (progn >> + (org-fontify-inline-src-blocks-1 limit) >> + (org-fontify-inline-src-results limit)) > > org-fontify-inline-src-results is not defined in this patch. Ah. Thanks for catching this! >> + (font-lock-append-text-property lang-beg lang-end ’face ’org-meta-line) >> + (font-lock-append-text-property beg lang-beg ’face ’shadow) >> + (font-lock-append-text-property beg lang-end ’face ’org-inline-src-block) > > Is there some special reason why you apply both ’shadow and > ’org-inline-src-block? What about ’org-meta-line face? Maybe > ’org-meta-line should not be hard-coded? I think there’s an argument for more faces that can be made because of element like this, but it comes down to the idea that in a `src_lang[options]{content}' construct `src_' is effectively visual noise, particularly once fortification occurs and it’s obvious that it’s inline code even without it. So, I find it nicest if it’s faded, which `shadow' does. Also applying `org-inline-src-block' allows for a consistent background colour across the whole construct. >> + (setq pt (goto-char lang-end)) >> + ;; `org-element–parse-paired-brackets’ doesn’t take a limit, so to >> + ;; prevent it searching the entire rest of the buffer we temporarily >> + ;; narrow the active region. >> + (save-restriction >> + (narrow-to-region beg (min (point-max) >> + limit >> + (+ lang-end org-inline-src-fontify-max-length))) >> + (when (ignore-errors (org-element–parse-paired-brackets ?\[)) >> + (font-lock-append-text-property pt (point) ’face ’org-inline-src-block) >> + (setq pt (point))) >> + (when (ignore-errors (org-element–parse-paired-brackets ?\{)) > > It looks like you are repeating the job of org-element-context here. Why > don’t you just get the proper object? IIRC `org-element-context' doesn’t separate out the `src_', `lang', `[options]', and `{content}' of an inline source code block (which we want). >> + (remove-text-properties pt (point) ’(face nil)) >> + (font-lock-append-text-property pt (1+ pt) ’face ’(org-block shadow)) > > Do you really intend to use ’org-block and ’shadow faces here? Not > ’org-inline-src-block? Ah, that was an oversight. Thanks for catching that, changed to `(org-inline-src-block shadow)'. >> +(defcustom org-inline-src-prettify-results t > > Looks like a stray defcustom. At least, it is not mentioned in the > commit message and not used within the patch. Removed. > Best, > Ihor Thanks again! See an updated patch attached. All the best, Timothy [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-org-src-Implement-native-inline-src-fontification.patch --] [-- Type: text/x-patch, Size: 5474 bytes --] From 08fff19eb6242339f9fe5549de0bc54520a3d603 Mon Sep 17 00:00:00 2001 From: TEC <tec@tecosaur.com> Date: Tue, 13 Jul 2021 02:43:29 +0800 Subject: [PATCH] org-src: Implement native inline src fontification * lisp/org-src.el (org-fontify-inline-src-blocks, org-fontify-inline-src-blocks-1): Create a function to search the buffer up to a limit for inline src blocks. Light fontification is applied to matched inline src blocks. When `org-src-fontify-natively' is set, `org-src-font-lock-fontify-block' is applied to the content. * lisp/org.el (org-set-font-lock-defaults): Add `org-fontify-inline-src-blocks' to `org-font-lock-extra-keywords', which is locally bound inside `org-set-font-lock-defaults'. (org-inline-src-fontify-max-length): Create a variable to limit the maximum length of an inline-src block fontified, to protect from lag spikes (e.g. when typing out src_lang{ and half of the buffer is fontified). * lisp/org-faces.el: Introduce a new face `org-inline-src-block' which inherits from `org-block' by default. --- lisp/org-faces.el | 4 ++++ lisp/org-src.el | 44 ++++++++++++++++++++++++++++++++++++++++++++ lisp/org.el | 9 +++++++++ 3 files changed, 57 insertions(+) diff --git a/lisp/org-faces.el b/lisp/org-faces.el index b151045a9..272762789 100644 --- a/lisp/org-faces.el +++ b/lisp/org-faces.el @@ -459,6 +459,10 @@ (defface org-block-end-line '((t (:inherit org-block-begin-line))) "Face used for the line delimiting the end of source blocks." :group 'org-faces) +(defface org-inline-src-block '((t (:inherit org-block))) + "Face used for inline source blocks as a whole." + :group 'org-faces) + (defface org-verbatim '((t (:inherit (fixed-pitch shadow)))) "Face for fixed-with text like code snippets." :group 'org-faces diff --git a/lisp/org-src.el b/lisp/org-src.el index 51dde602d..fc9ddc27e 100644 --- a/lisp/org-src.el +++ b/lisp/org-src.el @@ -654,6 +654,50 @@ (defun org-src-font-lock-fontify-block (lang start end) '(font-lock-fontified t fontified t font-lock-multiline t)) (set-buffer-modified-p modified))))) +(defun org-fontify-inline-src-blocks (limit) + "Try to apply `org-fontify-inline-src-blocks-1'." + (condition-case nil + (org-fontify-inline-src-blocks-1 limit) + (error (message "Org mode fontification error in %S at %d" + (current-buffer) + (line-number-at-pos))))) + +(defun org-fontify-inline-src-blocks-1 (limit) + "Fontify inline src_LANG blocks, from `point' up to LIMIT." + (let ((case-fold-search t) + (initial-point (point))) + (while (re-search-forward "\\_<src_\\([^ \t\n[{]+\\)[{[]?" limit t) ; copied from `org-element-inline-src-block-parser' + (let ((beg (match-beginning 0)) + (lang-beg (match-beginning 1)) + (lang-end (match-end 1)) + pt) + (font-lock-append-text-property lang-beg lang-end 'face 'org-meta-line) + (font-lock-append-text-property beg lang-beg 'face 'shadow) + (font-lock-append-text-property beg lang-end 'face 'org-inline-src-block) + (setq pt (goto-char lang-end)) + ;; `org-element--parse-paired-brackets' doesn't take a limit, so to + ;; prevent it searching the entire rest of the buffer we temporarily + ;; narrow the active region. + (save-restriction + (narrow-to-region beg (min (point-max) + limit + (+ lang-end org-inline-src-fontify-max-length))) + (when (ignore-errors (org-element--parse-paired-brackets ?\[)) + (font-lock-append-text-property pt (point) 'face 'org-inline-src-block) + (setq pt (point))) + (when (ignore-errors (org-element--parse-paired-brackets ?\{)) + (remove-text-properties pt (point) '(face nil)) + (font-lock-append-text-property pt (1+ pt) 'face '(org-inline-src-block shadow)) + (unless (= (1+ pt) (1- (point))) + (if org-src-fontify-natively + (org-src-font-lock-fontify-block + (buffer-substring-no-properties lang-beg lang-end) + (1+ pt) (1- (point))) + (font-lock-append-text-property (1+ pt) (1- (point)) 'face 'org-inline-src-block))) + (font-lock-append-text-property (1- (point)) (point)'face '(org-inline-src-block shadow)) + (setq pt (point))))) + t))) + \f ;;; Escape contents diff --git a/lisp/org.el b/lisp/org.el index 331bd9f65..637d2646c 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -5279,6 +5279,14 @@ (defcustom org-allow-promoting-top-level-subtree nil :version "24.1" :group 'org-appearance) +(defcustom org-inline-src-fontify-max-length 200 + "Maximum content length of an inline src block that will be fontified. +This is only relevant when `org-src-fontify-natively' is t." + :type 'integer + :package-version '(Org . "9.5") + :group 'org-appearance + :group 'org-babel) + (defun org-fontify-meta-lines-and-blocks (limit) (condition-case nil (org-fontify-meta-lines-and-blocks-1 limit) @@ -5785,6 +5793,7 @@ (defun org-set-font-lock-defaults () '(9 'org-special-keyword t)) ;; Blocks and meta lines '(org-fontify-meta-lines-and-blocks) + '(org-fontify-inline-src-blocks) ;; Citations '(org-cite-activate)))) (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords)) -- 2.33.1
Timothy <tecosaur@gmail.com> writes: >> I have some comments. See below. > > Thanks for going through this, and for all your help previously. > I appreciate it :) Welcome. >>> (org-inline-src-fontify-max-length): Create a variable to limit the >>> maximum length of an inline-src block fontified, to protect from lag >>> spikes (e.g. when typing out src_lang{ and half of the buffer is >>> fontified). >> >> I do not like this. Even with this variable, some part of buffer may be >> spuriously fontified. Maybe you just verify that you are at actual >> inline-src block by examining org-element-context? > > The description may need updating, as that’s a tad inaccurate. That value > actually limits how far forwards a paired paren is searched for. There’s no > spurious fontification. I can see the purpose. However, it still looks like overcomplication. org-element-context takes care about this issue simply by narrowing to current element (inline src block is an object and hence must end within current element). >>> + (font-lock-append-text-property lang-beg lang-end ’face ’org-meta-line) >>> + (font-lock-append-text-property beg lang-beg ’face ’shadow) >>> + (font-lock-append-text-property beg lang-end ’face ’org-inline-src-block) >> >> Is there some special reason why you apply both ’shadow and >> ’org-inline-src-block? What about ’org-meta-line face? Maybe >> ’org-meta-line should not be hard-coded? > > I think there’s an argument for more faces that can be made because of element > like this, but it comes down to the idea that in a `src_lang[options]{content}' > construct `src_' is effectively visual noise, particularly once fortification > occurs and it’s obvious that it’s inline code even without it. So, I find it > nicest if it’s faded, which `shadow' does. Also applying `org-inline-src-block' > allows for a consistent background colour across the whole construct. Makes sense. >> It looks like you are repeating the job of org-element-context here. Why >> don’t you just get the proper object? > > IIRC `org-element-context' doesn’t separate out the `src_', `lang', `[options]', and > `{content}' of an inline source code block (which we want). Sounds like an omission in org-element-context. At least, the parser could return :contents-begin and :contents-end. Then, you would also not need to re-implement the parser. Best, Ihor
[-- Attachment #1: Type: text/plain, Size: 1336 bytes --] Hi Ihor, >>>> org-inline-src-fontify-max-length >> The description may need updating, as that’s a tad inaccurate. That value >> actually limits how far forwards a paired paren is searched for. There’s no >> spurious fontification. > > I can see the purpose. However, it still looks like overcomplication. > org-element-context takes care about this issue simply by narrowing to > current element (inline src block is an object and hence must end within > current element). Well, one simple change we could do is just replace org-inline-src-fontify-max-length with the addition of `(save-excursion (search-forward "\n" limit nil) (point))' to the restriction. >>> It looks like you are repeating the job of org-element-context here. Why >>> don’t you just get the proper object? >> >> IIRC `org-element-context’ doesn’t separate out the `src_’, `lang’, `[options]’, and >> `{content}’ of an inline source code block (which we want). > > Sounds like an omission in org-element-context. At least, the parser > could return :contents-begin and :contents-end. Then, you would also not > need to re-implement the parser. Perhaps. However frankly I don’t think it would do that much to reduce the complexity, and what’s in this patch seems to work fairly nicely. All the best, Timothy
[-- Attachment #1: Type: text/plain, Size: 1191 bytes --] Hi Timothy, It seems a great work! I'm not familiar with this yet, just curious that if this "org-inline-src-block" could save this problem: the preview image of inline LaTeX has a different color from the normal text, which is ugly and annoying. And setting 'org-format-latex-options doesn't help because the problem is caused by the inline LaTeX using the 'org-fixed-width face which has a different color and when the preview image is not big enough the color will be shown. The attachment shows the problem where some preview LaTeX images have different colors surrounded. Regards, VitalyR On Sun, Nov 21, 2021 at 10:16 PM Timothy <tecosaur@gmail.com> wrote: > > Hi All, > > Since the contentious component of my previous patches has been the > `{{{results()}}}' prettification, I’ve prepared an alternate version that I’m > hoping everybody will be fairly happy with (fingers crossed!) that tosses out > the results prettification for now. > > I think Protesilaos’ comments on making some new faces deserve consideration, > but could easily be done subsequently, as I’m quite keen to get this merged for > now. > > All the best, > Timothy [-- Attachment #2: 2021-11-23_18-40.png --] [-- Type: image/png, Size: 127635 bytes --]
Timothy <tecosaur@gmail.com> writes: >> I can see the purpose. However, it still looks like overcomplication. >> org-element-context takes care about this issue simply by narrowing to >> current element (inline src block is an object and hence must end within >> current element). > > Well, one simple change we could do is just replace > org-inline-src-fontify-max-length with the addition of `(save-excursion > (search-forward "\n" limit nil) (point))' to the restriction. That's an option. Though you should also consider a paragraph ending at EOB. Searching for "\n" will fail with error then. >> Sounds like an omission in org-element-context. At least, the parser >> could return :contents-begin and :contents-end. Then, you would also not >> need to re-implement the parser. > > Perhaps. However frankly I don’t think it would do that much to reduce the > complexity, and what’s in this patch seems to work fairly nicely. I am mostly thinking in terms of https://list.orgmode.org/87tug8t8ql.fsf@gmail.com/T/#t Otherwise, your variant is fine for me. Best, Ihor
Hi Timothy,
Sorry for my stupid question. I have figured out the problem is not
relevant to
your work and I have fixed it. I'm really looking forward to your org-mode
asynchronous fragment compilation.
All the best,
VitalyR
On Tue, Nov 23, 2021 at 6:45 PM Vitaly Ankh <vitalyankh@gmail.com> wrote:
>
> Hi Timothy,
> It seems a great work! I'm not familiar with this yet, just curious
> that if this "org-inline-src-block"
> could save this problem: the preview image of inline LaTeX has a
> different color from
> the normal text, which is ugly and annoying. And setting
> 'org-format-latex-options
> doesn't help because the problem is caused by the inline LaTeX using
> the 'org-fixed-width face
> which has a different color and when the preview image is not big
> enough the color will be shown.
> The attachment shows the problem where some preview LaTeX images have
> different colors
> surrounded.
>
> Regards,
> VitalyR
>
>
> On Sun, Nov 21, 2021 at 10:16 PM Timothy <tecosaur@gmail.com> wrote:
> >
> > Hi All,
> >
> > Since the contentious component of my previous patches has been the
> > `{{{results()}}}' prettification, I’ve prepared an alternate version that I’m
> > hoping everybody will be fairly happy with (fingers crossed!) that tosses out
> > the results prettification for now.
> >
> > I think Protesilaos’ comments on making some new faces deserve consideration,
> > but could easily be done subsequently, as I’m quite keen to get this merged for
> > now.
> >
> > All the best,
> > Timothy
[-- Attachment #1: Type: text/plain, Size: 923 bytes --] Hi Ihor, > That’s an option. Though you should also consider a paragraph ending at > EOB. Searching for “” will fail with error then. Don’t worry, that’s just a snippet. The full logic is as follows ┌──── │ (min limit (or (save-excursion (and (search-forward "\n" limit t 2) (point))) │ (point-max))) └──── >> [use org-element] Ah right. We now also have the new thread about using org-element. I think that sounds like a great change overall, but am still keen for this patch to go through for the moment — just as a stop gap till org-element exposes all the necessary information and there are some nice examples of using it for fontification. I’ve attached the latest version of the patch. At this point I consider it fairly well-reviewed, so I’ll push it tomorrow if I don’t hear of any last-minute issues. All the best, Timothy [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-org-src-Implement-native-inline-src-fontification.patch --] [-- Type: text/x-patch, Size: 4781 bytes --] From 690718bd2a31f9293572aa7a583a31a0615d18c8 Mon Sep 17 00:00:00 2001 From: TEC <tec@tecosaur.com> Date: Tue, 13 Jul 2021 02:43:29 +0800 Subject: [PATCH] org-src: Implement native inline src fontification * lisp/org-src.el (org-fontify-inline-src-blocks, org-fontify-inline-src-blocks-1): Create a function to search the buffer up to a limit for inline src blocks. Light fontification is applied to matched inline src blocks. When `org-src-fontify-natively' is set, `org-src-font-lock-fontify-block' is applied to the content. * lisp/org.el (org-set-font-lock-defaults): Add `org-fontify-inline-src-blocks' to `org-font-lock-extra-keywords', which is locally bound inside `org-set-font-lock-defaults'. * lisp/org-faces.el: Introduce a new face `org-inline-src-block' which inherits from `org-block' by default. --- lisp/org-faces.el | 4 ++++ lisp/org-src.el | 44 ++++++++++++++++++++++++++++++++++++++++++++ lisp/org.el | 1 + 3 files changed, 49 insertions(+) diff --git a/lisp/org-faces.el b/lisp/org-faces.el index b151045a9..272762789 100644 --- a/lisp/org-faces.el +++ b/lisp/org-faces.el @@ -459,6 +459,10 @@ (defface org-block-end-line '((t (:inherit org-block-begin-line))) "Face used for the line delimiting the end of source blocks." :group 'org-faces) +(defface org-inline-src-block '((t (:inherit org-block))) + "Face used for inline source blocks as a whole." + :group 'org-faces) + (defface org-verbatim '((t (:inherit (fixed-pitch shadow)))) "Face for fixed-with text like code snippets." :group 'org-faces diff --git a/lisp/org-src.el b/lisp/org-src.el index 51dde602d..639a447e8 100644 --- a/lisp/org-src.el +++ b/lisp/org-src.el @@ -654,6 +654,50 @@ (defun org-src-font-lock-fontify-block (lang start end) '(font-lock-fontified t fontified t font-lock-multiline t)) (set-buffer-modified-p modified))))) +(defun org-fontify-inline-src-blocks (limit) + "Try to apply `org-fontify-inline-src-blocks-1'." + (condition-case nil + (org-fontify-inline-src-blocks-1 limit) + (error (message "Org mode fontification error in %S at %d" + (current-buffer) + (line-number-at-pos))))) + +(defun org-fontify-inline-src-blocks-1 (limit) + "Fontify inline src_LANG blocks, from `point' up to LIMIT." + (let ((case-fold-search t) + (initial-point (point))) + (while (re-search-forward "\\_<src_\\([^ \t\n[{]+\\)[{[]?" limit t) ; copied from `org-element-inline-src-block-parser' + (let ((beg (match-beginning 0)) + (lang-beg (match-beginning 1)) + (lang-end (match-end 1)) + pt) + (font-lock-append-text-property lang-beg lang-end 'face 'org-meta-line) + (font-lock-append-text-property beg lang-beg 'face 'shadow) + (font-lock-append-text-property beg lang-end 'face 'org-inline-src-block) + (setq pt (goto-char lang-end)) + ;; `org-element--parse-paired-brackets' doesn't take a limit, so to + ;; prevent it searching the entire rest of the buffer we temporarily + ;; narrow the active region. + (save-restriction + (narrow-to-region beg (min limit (or (save-excursion (and (search-forward "\n" limit t 2) (point))) + (point-max)))) + (message "buf: %S" (substring-no-properties (buffer-string))) + (when (ignore-errors (org-element--parse-paired-brackets ?\[)) + (font-lock-append-text-property pt (point) 'face 'org-inline-src-block) + (setq pt (point))) + (when (ignore-errors (org-element--parse-paired-brackets ?\{)) + (remove-text-properties pt (point) '(face nil)) + (font-lock-append-text-property pt (1+ pt) 'face '(org-inline-src-block shadow)) + (unless (= (1+ pt) (1- (point))) + (if org-src-fontify-natively + (org-src-font-lock-fontify-block + (buffer-substring-no-properties lang-beg lang-end) + (1+ pt) (1- (point))) + (font-lock-append-text-property (1+ pt) (1- (point)) 'face 'org-inline-src-block))) + (font-lock-append-text-property (1- (point)) (point)'face '(org-inline-src-block shadow)) + (setq pt (point))))) + t))) + \f ;;; Escape contents diff --git a/lisp/org.el b/lisp/org.el index 025513e7a..ec59ddf44 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -5785,6 +5785,7 @@ (defun org-set-font-lock-defaults () '(9 'org-special-keyword t)) ;; Blocks and meta lines '(org-fontify-meta-lines-and-blocks) + '(org-fontify-inline-src-blocks) ;; Citations '(org-cite-activate)))) (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords)) -- 2.33.1
[-- Attachment #1: Type: text/plain, Size: 40 bytes --] Pushed 🙂. All the best, Timothy
Timothy <tecosaur@gmail.com> writes:
>>> [use org-element]
>
> Ah right. We now also have the new thread about using org-element. I think that
> sounds like a great change overall, but am still keen for this patch to go
> through for the moment — just as a stop gap till org-element exposes all the
> necessary information and there are some nice examples of using it for
> fontification.
Agree. I plan to do some work on org-element-based fontification, but
probably not in near future.
Also, note that your patch has unused let-binding:
In org-fontify-inline-src-blocks-1:
org-src.el:669:70: Warning: Unused lexical variable `initial-point'
Best,
Ihor
Hi,
Timothy writes:
> Pushed 🙂.
Sorry for the late reply, but isn't there a =message= call leftover from
debugging ?
Regards,
--
Sébastien Miquel
[-- Attachment #1: Type: text/plain, Size: 252 bytes --] Hi Sebastien, > Sorry for the late reply, but isn’t there a `message' call leftover from > debugging ? Ooops! Time for a clean-up patch to fix the things you and Ihor’s just noticed. Thanks for mentioning this. All the best, Timothy
Timothy, I am happy to see the fontification of inline src blocks in org. Thank you! However, I am finding the result not very pleasing unfortunately. Specifically, I am not happy with the use of other pre-existing faces (shadow and org-meta-line) for this purpose. These other faces have their specific uses and the resulting combination for inline src blocks, for me, is ugly. I do not wish to modify those faces for this use case as it will affect their use everywhere else. Philosophically, the language element in an inline src block is not a /meta line/, at least not in my view: it's not even a line... 😉 Would it be possible to create new faces specifically for the various bits you want to differentiate, e.g. org-inline-src-block-language? I don't mind if they have the defaults to be the same as org-meta-line and org-shadow etc. but at least I can customise them separately. Thanks again, eric -- : Eric S Fraga, with org release_9.5.1-231-g6766c4 in Emacs 29.0.50 : Latest paper written in org: https://arxiv.org/abs/2106.05096
[-- Attachment #1: Type: text/plain, Size: 980 bytes --] Hi Eric, > However, I am finding the result not very pleasing unfortunately. > Specifically, I am not happy with the use of other pre-existing faces > (shadow and org-meta-line) for this purpose. These other faces have > their specific uses and the resulting combination for inline src blocks, > for me, is ugly. I do not wish to modify those faces for this use case > as it will affect their use everywhere else. Yep, I’ve been quite open to the prospect of adding faces, just not entirely sure how much / what I should do. Since I didn’t want that block this feature we’ve currently got the one-face version. The various elements that could have a face are: ⁃ the src_ prefix ⁃ the lang component ⁃ headers ⁃ the square brackets delimiting the headers / curly brackets delimiting the content ⁃ the content ⁃ the whole block (this is what currently has a dedicated face) Let me know what your thoughts are. All the best, Timothy
On Thursday, 2 Dec 2021 at 21:57, Timothy wrote: > Let me know what your thoughts are. I am not very picky (yeah, well, okay, maybe a little 😉). All I really care about is not having other faces, that have well defined meanings, being used. I would actually be happy with just the whole block having a face but maybe others, including yourself, would like to distinguish the various bits that make up an inline src block. thank you, eric -- : Eric S Fraga, with org release_9.5.1-231-g6766c4 in Emacs 29.0.50 : Latest paper written in org: https://arxiv.org/abs/2106.05096
[-- Attachment #1: Type: text/plain, Size: 701 bytes --] Hi Eric, > I am not very picky (yeah, well, okay, maybe a little 😉). All I really > care about is not having other faces, that have well defined meanings, > being used. I would actually be happy with just the whole block having > a face but maybe others, including yourself, would like to distinguish > the various bits that make up an inline src block. Stop me if I surprise you 😛 but I’m quite a fan of the fine highlighting detail that’s currently occurring. I’m inclined to try to make myself happy without forcing the same style on other people by adding faces, but something like 6 faces for inline source blocks just feels excessive to me. All the best, Timothy
On Thursday, 2 Dec 2021 at 23:56, Timothy wrote: > [...] but something like 6 faces for inline source blocks just feels > excessive to me. Why? It's just a number. I cannot imagine it would have any performance impact? If you think that level of granularity is useful, I suggest you go for it. Or at least define the 3 you seem to have implicitly chosen already (by using 2 existing ones and adding one new face)? -- : Eric S Fraga, with org release_9.5.1-231-g6766c4 in Emacs 29.0.50 : Latest paper written in org: https://arxiv.org/abs/2106.05096