Implement pretty display of sub- and superscripts.

* doc/org.texi (Subscripts and superscripts): Document that `C-c C-x \'
will also format sub and superscripts.
* doc/orgcard.tex: Document that `C-c C-x \'
will also format sub and superscripts.
* lisp/org.el (org-use-sub-superscripts):
(org-pretty-entities-include-sub-superscripts): Move here from
org-exp.el.
(org-set-regexps-and-options): Parse subscript option and set
`org-use-sub-superscripts' as a local variable.
(org-match-sexp-depth):
(org-create-multibrace-regexp):
(org-match-substring-regexp):
(org-match-substring-with-braces-regexp): Moved here from org-exp.el
(org-set-font-lock-defaults): Call `org-raise-scripts'.
(org-remove-font-lock-display-properties): New function.
(org-unfontify-region): Call
`org-remove-font-lock-display-properties'.
(org-script-display): New constant.
(org-raise-scripts): New function.

When turning on entity display with `C-c C-x \', sub- and superscripts
will also be displayed in a smaller font, and raised/lowered.
This commit is contained in:
Carsten Dominik 2010-06-02 16:35:44 +02:00
parent 32b58fad32
commit 70d24c5d03
4 changed files with 137 additions and 73 deletions

View File

@ -8783,6 +8783,12 @@ convention, or use, on a per-file basis:
#+OPTIONS: ^:@{@} #+OPTIONS: ^:@{@}
@end example @end example
@table @kbd
@kindex C-c C-x \
@item C-c C-x \
In addition to showing entities as UTF8 characters, this command will also
format sub- and superscripts in a WYSIWYM way.
@end table
@node LaTeX fragments, Previewing LaTeX fragments, Subscripts and superscripts, Embedded LaTeX @node LaTeX fragments, Previewing LaTeX fragments, Subscripts and superscripts, Embedded LaTeX
@subsection La@TeX{} fragments @subsection La@TeX{} fragments

View File

@ -704,7 +704,7 @@ some other place.
\key{export visible part only}{C-c C-e v} \key{export visible part only}{C-c C-e v}
\key{insert template of export options}{C-c C-e t} \key{insert template of export options}{C-c C-e t}
\key{toggle fixed width for entry or region}{C-c :} \key{toggle fixed width for entry or region}{C-c :}
\key{toggle display of entities as UTF8 chars}{C-c C-x {\tt\char`\\}} \key{toggle pretty display of scripts, entities}{C-c C-x {\tt\char`\\}}
%{\bf HTML formatting} %{\bf HTML formatting}

View File

@ -448,35 +448,6 @@ This option can also be set with the +OPTIONS line, e.g. \"f:nil\"."
:group 'org-export-translation :group 'org-export-translation
:type 'boolean) :type 'boolean)
(defcustom org-export-with-sub-superscripts t
"Non-nil means interpret \"_\" and \"^\" for export.
When this option is turned on, you can use TeX-like syntax for sub- and
superscripts. Several characters after \"_\" or \"^\" will be
considered as a single item - so grouping with {} is normally not
needed. For example, the following things will be parsed as single
sub- or superscripts.
10^24 or 10^tau several digits will be considered 1 item.
10^-12 or 10^-tau a leading sign with digits or a word
x^2-y^3 will be read as x^2 - y^3, because items are
terminated by almost any nonword/nondigit char.
x_{i^2} or x^(2-i) braces or parenthesis do grouping.
Still, ambiguity is possible - so when in doubt use {} to enclose the
sub/superscript. If you set this variable to the symbol `{}',
the braces are *required* in order to trigger interpretations as
sub/superscript. This can be helpful in documents that need \"_\"
frequently in plain text.
Not all export backends support this, but HTML does.
This option can also be set with the +OPTIONS line, e.g. \"^:nil\"."
:group 'org-export-translation
:type '(choice
(const :tag "Always interpret" t)
(const :tag "Only with braces" {})
(const :tag "Never interpret" nil)))
(defcustom org-export-with-TeX-macros t (defcustom org-export-with-TeX-macros t
"Non-nil means interpret simple TeX-like macros when exporting. "Non-nil means interpret simple TeX-like macros when exporting.
For example, HTML export converts \\alpha to α and \\AA to Å. For example, HTML export converts \\alpha to α and \\AA to Å.
@ -520,12 +491,6 @@ This option can also be set with the +OPTIONS line, e.g. \"::nil\"."
:group 'org-export-translation :group 'org-export-translation
:type 'boolean) :type 'boolean)
(defcustom org-match-sexp-depth 3
"Number of stacked braces for sub/superscript matching.
This has to be set before loading org.el to be effective."
:group 'org-export-translation
:type 'integer)
(defgroup org-export-tables nil (defgroup org-export-tables nil
"Options for exporting tables in Org-mode." "Options for exporting tables in Org-mode."
:tag "Org Export Tables" :tag "Org Export Tables"
@ -2734,41 +2699,6 @@ If yes remove the column and the special lines."
(setq s (replace-match "" t t s))) (setq s (replace-match "" t t s)))
s) s)
(defun org-create-multibrace-regexp (left right n)
"Create a regular expression which will match a balanced sexp.
Opening delimiter is LEFT, and closing delimiter is RIGHT, both given
as single character strings.
The regexp returned will match the entire expression including the
delimiters. It will also define a single group which contains the
match except for the outermost delimiters. The maximum depth of
stacked delimiters is N. Escaping delimiters is not possible."
(let* ((nothing (concat "[^" left right "]*?"))
(or "\\|")
(re nothing)
(next (concat "\\(?:" nothing left nothing right "\\)+" nothing)))
(while (> n 1)
(setq n (1- n)
re (concat re or next)
next (concat "\\(?:" nothing left next right "\\)+" nothing)))
(concat left "\\(" re "\\)" right)))
(defvar org-match-substring-regexp
(concat
"\\([^\\]\\)\\([_^]\\)\\("
"\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
"\\|"
"\\(" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)"
"\\|"
"\\(\\(?:\\*\\|[-+]?[^-+*!@#$%^_ \t\r\n,:\"?<>~;./{}=()]+\\)\\)\\)")
"The regular expression matching a sub- or superscript.")
(defvar org-match-substring-with-braces-regexp
(concat
"\\([^\\]\\)\\([_^]\\)\\("
"\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
"\\)")
"The regular expression matching a sub- or superscript, forcing braces.")
(defun org-get-text-property-any (pos prop &optional object) (defun org-get-text-property-any (pos prop &optional object)
(or (get-text-property pos prop object) (or (get-text-property pos prop object)

View File

@ -344,6 +344,39 @@ the following lines anywhere in the buffer:
(const :tag "Not" nil) (const :tag "Not" nil)
(const :tag "Globally (slow on startup in large files)" t))) (const :tag "Globally (slow on startup in large files)" t)))
(defcustom org-use-sub-superscripts t
"Non-nil means interpret \"_\" and \"^\" for export.
When this option is turned on, you can use TeX-like syntax for sub- and
superscripts. Several characters after \"_\" or \"^\" will be
considered as a single item - so grouping with {} is normally not
needed. For example, the following things will be parsed as single
sub- or superscripts.
10^24 or 10^tau several digits will be considered 1 item.
10^-12 or 10^-tau a leading sign with digits or a word
x^2-y^3 will be read as x^2 - y^3, because items are
terminated by almost any nonword/nondigit char.
x_{i^2} or x^(2-i) braces or parenthesis do grouping.
Still, ambiguity is possible - so when in doubt use {} to enclose the
sub/superscript. If you set this variable to the symbol `{}',
the braces are *required* in order to trigger interpretations as
sub/superscript. This can be helpful in documents that need \"_\"
frequently in plain text.
Not all export backends support this, but HTML does.
This option can also be set with the +OPTIONS line, e.g. \"^:nil\"."
:group 'org-startup
:group 'org-export-translation
:type '(choice
(const :tag "Always interpret" t)
(const :tag "Only with braces" {})
(const :tag "Never interpret" nil)))
(defvaralias 'org-export-with-sub-superscripts 'org-use-sub-superscripts)
(defcustom org-startup-with-beamer-mode nil (defcustom org-startup-with-beamer-mode nil
"Non-nil means turn on `org-beamer-mode' on startup. "Non-nil means turn on `org-beamer-mode' on startup.
This can also be configured on a per-file basis by adding one of This can also be configured on a per-file basis by adding one of
@ -3176,6 +3209,11 @@ When nil, the \\name form remains in the buffer."
:group 'org-appearance :group 'org-appearance
:type 'boolean) :type 'boolean)
(defcustom org-pretty-entities-include-sub-superscripts t
"Non-nil means, pretty entity display includes formatting sub/superscripts."
:group 'org-appearance
:type 'boolean)
(defvar org-emph-re nil (defvar org-emph-re nil
"Regular expression for matching emphasis. "Regular expression for matching emphasis.
After a match, the match groups contain these elements: After a match, the match groups contain these elements:
@ -4047,9 +4085,11 @@ means to push this value onto the list in the variable.")
(let ((re (org-make-options-regexp (let ((re (org-make-options-regexp
'("CATEGORY" "TODO" "COLUMNS" '("CATEGORY" "TODO" "COLUMNS"
"STARTUP" "ARCHIVE" "FILETAGS" "TAGS" "LINK" "PRIORITIES" "STARTUP" "ARCHIVE" "FILETAGS" "TAGS" "LINK" "PRIORITIES"
"CONSTANTS" "PROPERTY" "DRAWERS" "SETUPFILE" "LATEX_CLASS") "CONSTANTS" "PROPERTY" "DRAWERS" "SETUPFILE" "LATEX_CLASS"
"OPTIONS")
"\\(?:[a-zA-Z][0-9a-zA-Z_]*_TODO\\)")) "\\(?:[a-zA-Z][0-9a-zA-Z_]*_TODO\\)"))
(splitre "[ \t]+") (splitre "[ \t]+")
(scripts org-use-sub-superscripts)
kwds kws0 kwsa key log value cat arch tags const links hw dws kwds kws0 kwsa key log value cat arch tags const links hw dws
tail sep kws1 prio props ftags drawers beamer-p tail sep kws1 prio props ftags drawers beamer-p
ext-setup-or-nil setup-contents (start 0)) ext-setup-or-nil setup-contents (start 0))
@ -4122,6 +4162,9 @@ means to push this value onto the list in the variable.")
'(face t fontified t) arch)) '(face t fontified t) arch))
((equal key "LATEX_CLASS") ((equal key "LATEX_CLASS")
(setq beamer-p (equal value "beamer"))) (setq beamer-p (equal value "beamer")))
((equal key "OPTIONS")
(if (string-match "\\([ \t]\\|\\`\\)\\^:\\(t\\|nil\\|{}\\)" value)
(setq scripts (read (match-string 2 value)))))
((equal key "SETUPFILE") ((equal key "SETUPFILE")
(setq setup-contents (org-file-contents (setq setup-contents (org-file-contents
(expand-file-name (expand-file-name
@ -4134,6 +4177,7 @@ means to push this value onto the list in the variable.")
"\n" setup-contents "\n" "\n" setup-contents "\n"
(substring ext-setup-or-nil start))))) (substring ext-setup-or-nil start)))))
)))) ))))
(org-set-local 'org-use-sub-superscripts scripts)
(when cat (when cat
(org-set-local 'org-category (intern cat)) (org-set-local 'org-category (intern cat))
(push (cons "CATEGORY" cat) props)) (push (cons "CATEGORY" cat) props))
@ -4617,6 +4661,47 @@ Here is what the match groups contain after a match:
(defvar org-any-link-re nil (defvar org-any-link-re nil
"Regular expression matching any link.") "Regular expression matching any link.")
(defcustom org-match-sexp-depth 3
"Number of stacked braces for sub/superscript matching.
This has to be set before loading org.el to be effective."
:group 'org-export-translation ; ??????????????????????????/
:type 'integer)
(defun org-create-multibrace-regexp (left right n)
"Create a regular expression which will match a balanced sexp.
Opening delimiter is LEFT, and closing delimiter is RIGHT, both given
as single character strings.
The regexp returned will match the entire expression including the
delimiters. It will also define a single group which contains the
match except for the outermost delimiters. The maximum depth of
stacked delimiters is N. Escaping delimiters is not possible."
(let* ((nothing (concat "[^" left right "]*?"))
(or "\\|")
(re nothing)
(next (concat "\\(?:" nothing left nothing right "\\)+" nothing)))
(while (> n 1)
(setq n (1- n)
re (concat re or next)
next (concat "\\(?:" nothing left next right "\\)+" nothing)))
(concat left "\\(" re "\\)" right)))
(defvar org-match-substring-regexp
(concat
"\\([^\\]\\)\\([_^]\\)\\("
"\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
"\\|"
"\\(" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)"
"\\|"
"\\(\\(?:\\*\\|[-+]?[^-+*!@#$%^_ \t\r\n,:\"?<>~;./{}=()]+\\)\\)\\)")
"The regular expression matching a sub- or superscript.")
(defvar org-match-substring-with-braces-regexp
(concat
"\\([^\\]\\)\\([_^]\\)\\("
"\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
"\\)")
"The regular expression matching a sub- or superscript, forcing braces.")
(defun org-make-link-regexps () (defun org-make-link-regexps ()
"Update the link regular expressions. "Update the link regular expressions.
This should be called after the variable `org-link-types' has changed." This should be called after the variable `org-link-types' has changed."
@ -5249,6 +5334,7 @@ For plain list items, if they are matched by `outline-regexp', this returns
;; Specials ;; Specials
'(org-do-latex-and-special-faces) '(org-do-latex-and-special-faces)
'(org-fontify-entities) '(org-fontify-entities)
'(org-raise-scripts)
;; Code ;; Code
'(org-activate-code (1 'org-code t)) '(org-activate-code (1 'org-code t))
;; COMMENT ;; COMMENT
@ -5383,7 +5469,49 @@ If KWD is a number, get the corresponding match group."
org-no-flyspell t) org-no-flyspell t)
'(mouse-face t keymap t org-linked-text t '(mouse-face t keymap t org-linked-text t
invisible t intangible t invisible t intangible t
org-no-flyspell t))))) org-no-flyspell t)))
(org-remove-font-lock-display-properties beg end)))
(defun org-remove-font-lock-display-properties (beg end)
"Remove specific display properties that have been added by font lock.
The will remove the raise properties that are used to show superscripts
and subscriipts."
(let (next prop)
(while (< beg end)
(setq next (next-single-property-change beg 'display nil end)
prop (get-text-property beg 'display))
(if (member prop org-script-display)
(put-text-property beg next 'display nil))
(setq beg next))))
(defconst org-script-display '(((raise -0.3) (height 0.7))
((raise 0.3) (height 0.7)))
"Display properties for showing superscripts and subscripts.")
(defun org-raise-scripts (limit)
"Add raise properties to sub/superscripts."
(when (and org-pretty-entities org-pretty-entities-include-sub-superscripts)
(if (re-search-forward
(if (eq org-use-sub-superscripts t)
org-match-substring-regexp
org-match-substring-with-braces-regexp)
limit t)
(progn
(put-text-property (match-beginning 3) (match-end 0)
'display
(if (equal (char-after (match-beginning 2)) ?^)
(nth 1 org-script-display)
(car org-script-display)))
(put-text-property (match-beginning 2) (match-end 2)
'invisible t)
(if (and (eq (char-after (match-beginning 3)) ?{)
(eq (char-before (match-end 3)) ?}))
(progn
(put-text-property (match-beginning 3) (1+ (match-beginning 3))
'invisible t)
(put-text-property (1- (match-end 3)) (match-end 3)
'invisible t)))
t))))
;;;; Visibility cycling, including org-goto and indirect buffer ;;;; Visibility cycling, including org-goto and indirect buffer