Merge branch 'features/indexmacros'

This commit is contained in:
Juergen Spitzmueller 2022-10-31 19:32:52 +01:00
commit 4e50da3e65
34 changed files with 5424 additions and 503 deletions

View File

@ -1,5 +1,5 @@
#LyX 2.4 created this file. For more info see https://www.lyx.org/
\lyxformat 608
\lyxformat 609
\begin_document
\begin_header
\save_transient_properties true
@ -92,6 +92,8 @@ Index tests
\begin_layout Standard
Text
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
@ -102,6 +104,8 @@ Text
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
@ -112,6 +116,8 @@ SortedAs@Text
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
@ -122,6 +128,8 @@ Primary!Secondary
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
@ -132,6 +140,8 @@ SortedPrimary@Primary!Secondary
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
@ -143,5 +153,138 @@ Primary!Secondary!Tertiary
.
\end_layout
\begin_layout Standard
Text
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
Text
\end_layout
\end_inset
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
\begin_inset IndexMacro sortkey
status open
\begin_layout Plain Layout
SortedAs
\end_layout
\end_inset
Text
\end_layout
\end_inset
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
Primary
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
Secondary
\end_layout
\end_inset
\end_layout
\end_inset
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
\begin_inset IndexMacro sortkey
status open
\begin_layout Plain Layout
SortedPrimary
\end_layout
\end_inset
Primary
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
Secondary
\end_layout
\end_inset
\end_layout
\end_inset
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
Primary
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
Secondary
\end_layout
\end_inset
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
Tertiary
\end_layout
\end_inset
\end_layout
\end_inset
.
\end_layout
\begin_layout Standard
\begin_inset CommandInset index_print
LatexCommand printindex
type "idx"
name "Index"
\end_inset
\end_layout
\end_body
\end_document

View File

@ -3,5 +3,7 @@
See https://www.lyx.org/ for more information -->
<article xml:lang="en_US" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:xi="http://www.w3.org/2001/XInclude" version="5.2">
<title>Index tests</title>
<para><indexterm><primary>Primary</primary><secondary>Secondary</secondary></indexterm></para>
<para>Text<indexterm><primary>Text</primary></indexterm><indexterm><primary sortas='SortedAs'>Text</primary></indexterm><indexterm><primary>Primary</primary><secondary>Secondary</secondary></indexterm><indexterm><primary sortas='SortedPrimary'>Primary</primary><secondary>Secondary</secondary></indexterm><indexterm><primary>Primary</primary><secondary>Secondary</secondary><tertiary>Tertiary</tertiary></indexterm>.</para>
<para>Text<indexterm><primary>Text</primary></indexterm><indexterm><primary sortas='SortedAs'>Text</primary></indexterm><indexterm><primary>Primary</primary><secondary>Secondary</secondary></indexterm><indexterm><primary sortas='SortedPrimary'>Primary</primary><secondary>Secondary</secondary></indexterm><indexterm><primary>Primary</primary><secondary>Secondary</secondary><tertiary>Tertiary</tertiary></indexterm>.</para>
</article>

View File

@ -0,0 +1,174 @@
#LyX 2.4 created this file. For more info see https://www.lyx.org/
\lyxformat 609
\begin_document
\begin_header
\save_transient_properties true
\origin unavailable
\textclass article
\use_default_options true
\maintain_unincluded_children no
\language american
\language_package default
\inputencoding utf8
\fontencoding auto
\font_roman "default" "default"
\font_sans "default" "default"
\font_typewriter "default" "default"
\font_math "auto" "auto"
\font_default_family default
\use_non_tex_fonts false
\font_sc false
\font_roman_osf false
\font_sans_osf false
\font_typewriter_osf false
\font_sf_scale 100 100
\font_tt_scale 100 100
\use_microtype false
\use_dash_ligatures true
\graphics default
\default_output_format default
\output_sync 0
\bibtex_command default
\index_command default
\float_placement class
\float_alignment class
\paperfontsize default
\use_hyperref false
\papersize default
\use_geometry false
\use_package amsmath 1
\use_package amssymb 1
\use_package cancel 1
\use_package esint 1
\use_package mathdots 1
\use_package mathtools 1
\use_package mhchem 1
\use_package stackrel 1
\use_package stmaryrd 1
\use_package undertilde 1
\cite_engine basic
\cite_engine_type default
\use_bibtopic false
\use_indices false
\paperorientation portrait
\suppress_date false
\justification true
\use_refstyle 1
\use_minted 0
\use_lineno 0
\index Index
\shortcut idx
\color #008000
\end_index
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\paragraph_indentation default
\is_math_indent 0
\math_numbering_side default
\quotes_style english
\dynamic_quotes 0
\papercolumns 1
\papersides 1
\paperpagestyle default
\tablestyle default
\tracking_changes false
\output_changes false
\change_bars false
\postpone_fragile_content true
\html_math_output 0
\html_css_as_file 0
\html_be_strict false
\docbook_table_output 0
\docbook_mathml_prefix 1
\end_header
\begin_body
\begin_layout Title
Index tests
\end_layout
\begin_layout Standard
Text
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
Primary
\end_layout
\end_inset
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
Primary
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
Secondary
\end_layout
\end_inset
\end_layout
\end_inset
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
Primary
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
Secondary
\end_layout
\end_inset
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
Tertiary
\end_layout
\end_inset
\end_layout
\end_inset
.
\end_layout
\begin_layout Standard
\begin_inset CommandInset index_print
LatexCommand printindex
type "idx"
name "Index"
\end_inset
\end_layout
\end_body
\end_document

View File

@ -0,0 +1,248 @@
#LyX 2.4 created this file. For more info see https://www.lyx.org/
\lyxformat 609
\begin_document
\begin_header
\save_transient_properties true
\origin unavailable
\textclass article
\use_default_options true
\maintain_unincluded_children no
\language american
\language_package default
\inputencoding utf8
\fontencoding auto
\font_roman "default" "default"
\font_sans "default" "default"
\font_typewriter "default" "default"
\font_math "auto" "auto"
\font_default_family default
\use_non_tex_fonts false
\font_sc false
\font_roman_osf false
\font_sans_osf false
\font_typewriter_osf false
\font_sf_scale 100 100
\font_tt_scale 100 100
\use_microtype false
\use_dash_ligatures true
\graphics default
\default_output_format default
\output_sync 0
\bibtex_command default
\index_command default
\float_placement class
\float_alignment class
\paperfontsize default
\spacing single
\use_hyperref false
\papersize default
\use_geometry false
\use_package amsmath 1
\use_package amssymb 1
\use_package cancel 1
\use_package esint 1
\use_package mathdots 1
\use_package mathtools 1
\use_package mhchem 1
\use_package stackrel 1
\use_package stmaryrd 1
\use_package undertilde 1
\cite_engine basic
\cite_engine_type default
\biblio_style plain
\use_bibtopic false
\use_indices true
\paperorientation portrait
\suppress_date false
\justification true
\use_refstyle 1
\use_minted 0
\use_lineno 0
\index Index
\shortcut idx
\color #008000
\end_index
\index Secondary
\shortcut sec
\color #550000
\end_index
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\paragraph_indentation default
\is_math_indent 0
\math_numbering_side default
\quotes_style english
\dynamic_quotes 0
\papercolumns 1
\papersides 1
\paperpagestyle default
\tablestyle default
\tracking_changes false
\output_changes false
\change_bars false
\postpone_fragile_content true
\html_math_output 0
\html_css_as_file 0
\html_be_strict false
\docbook_table_output 0
\docbook_mathml_prefix 1
\end_header
\begin_body
\begin_layout Title
Multiple indices tests
\end_layout
\begin_layout Standard
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
A
\end_layout
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
A
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
B
\end_layout
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Index sec
range none
pageformat default
status open
\begin_layout Plain Layout
A
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
B
\end_layout
\end_inset
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
C
\end_layout
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Index sec
range none
pageformat default
status open
\begin_layout Plain Layout
A
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
D
\end_layout
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Index sec
range none
pageformat default
status open
\begin_layout Plain Layout
E
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
F
\end_layout
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard
\begin_inset CommandInset index_print
LatexCommand printindex
type "idx"
name "Index"
literal "false"
\end_inset
\end_layout
\begin_layout Standard
\begin_inset CommandInset index_print
LatexCommand printindex
type "sec"
name "Index"
literal "false"
\end_inset
\end_layout
\end_body
\end_document

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This DocBook file was created by LyX 2.4.0dev
See https://www.lyx.org/ for more information -->
<article xml:lang="en_US" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:xi="http://www.w3.org/2001/XInclude" version="5.2">
<title>Multiple indices tests</title>
<para><indexterm type="idx"><primary>A</primary></indexterm></para>
<para><indexterm type="idx"><primary>A</primary><secondary>B</secondary></indexterm></para>
<para><indexterm type="sec"><primary>A</primary><secondary>B</secondary><tertiary>C</tertiary></indexterm></para>
<para><indexterm type="sec"><primary>A</primary><secondary>D</secondary></indexterm></para>
<para><indexterm type="sec"><primary>E</primary><secondary>F</secondary></indexterm></para>
</article>

View File

@ -0,0 +1,229 @@
#LyX 2.4 created this file. For more info see https://www.lyx.org/
\lyxformat 609
\begin_document
\begin_header
\save_transient_properties true
\origin unavailable
\textclass article
\use_default_options true
\maintain_unincluded_children no
\language american
\language_package default
\inputencoding utf8
\fontencoding auto
\font_roman "default" "default"
\font_sans "default" "default"
\font_typewriter "default" "default"
\font_math "auto" "auto"
\font_default_family default
\use_non_tex_fonts false
\font_sc false
\font_roman_osf false
\font_sans_osf false
\font_typewriter_osf false
\font_sf_scale 100 100
\font_tt_scale 100 100
\use_microtype false
\use_dash_ligatures true
\graphics default
\default_output_format default
\output_sync 0
\bibtex_command default
\index_command default
\float_placement class
\float_alignment class
\paperfontsize default
\use_hyperref false
\papersize default
\use_geometry false
\use_package amsmath 1
\use_package amssymb 1
\use_package cancel 1
\use_package esint 1
\use_package mathdots 1
\use_package mathtools 1
\use_package mhchem 1
\use_package stackrel 1
\use_package stmaryrd 1
\use_package undertilde 1
\cite_engine basic
\cite_engine_type default
\use_bibtopic false
\use_indices false
\paperorientation portrait
\suppress_date false
\justification true
\use_refstyle 1
\use_minted 0
\use_lineno 0
\index Index
\shortcut idx
\color #008000
\end_index
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\paragraph_indentation default
\is_math_indent 0
\math_numbering_side default
\quotes_style english
\dynamic_quotes 0
\papercolumns 1
\papersides 1
\paperpagestyle default
\tablestyle default
\tracking_changes false
\output_changes false
\change_bars false
\postpone_fragile_content true
\html_math_output 0
\html_css_as_file 0
\html_be_strict false
\docbook_table_output 0
\docbook_mathml_prefix 1
\end_header
\begin_body
\begin_layout Title
Index nesting tests
\end_layout
\begin_layout Standard
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
A
\end_layout
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
A
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
B
\end_layout
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
A
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
B
\end_layout
\end_inset
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
C
\end_layout
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
A
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
D
\end_layout
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Index idx
range none
pageformat default
status open
\begin_layout Plain Layout
E
\begin_inset IndexMacro subentry
status open
\begin_layout Plain Layout
F
\end_layout
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard
\begin_inset CommandInset index_print
LatexCommand printindex
type "idx"
name "Index"
\end_inset
\end_layout
\end_body
\end_document

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This DocBook file was created by LyX 2.4.0dev
See https://www.lyx.org/ for more information -->
<article xml:lang="en_US" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:xi="http://www.w3.org/2001/XInclude" version="5.2">
<title>Index nesting tests</title>
<para><indexterm><primary>A</primary></indexterm></para>
<para><indexterm><primary>A</primary><secondary>B</secondary></indexterm></para>
<para><indexterm><primary>A</primary><secondary>B</secondary><tertiary>C</tertiary></indexterm></para>
<para><indexterm><primary>A</primary><secondary>D</secondary></indexterm></para>
<para><indexterm><primary>E</primary><secondary>F</secondary></indexterm></para>
</article>

View File

@ -7,6 +7,20 @@ changes happened in particular if possible. A good example would be
-----------------------
2022-10-29 Jürgen Spitzmüller <spitz@lyx.org>
* Format incremented to 610: InsetIndexMacros and new IndexInset params:
- \begin_inset IndexMacro [see|seealso|subentry|sortkey], relating to
\index{...|see{content}} -- see
\index{...|seealso{content}} -- seealso
\index{...!subentry} -- subentry
\index{sortkey@...} -- sortkey
see and see also are mutually exclusive
- \begin_inset Index
range start -- \index{...|(}
range end -- \index{...|)}
pageformat cmd -- \index{...|cmd}
pageformat and see[also] are mutually exclusive.
2022-02-11 Jürgen Spitzmüller <spitz@lyx.org>
* Format incremented to 609: \\begin_metadata ... \\end_metadata buffer param.
This takes a list of keyvals for the new \\DocumentMetadata command

File diff suppressed because it is too large Load Diff

View File

@ -431,6 +431,36 @@ InsetLayout Index
PassThruChars @|!
End
InsetLayout IndexMacro:see
LabelString See
Decoration classic
Font
Size Small
EndFont
LabelFont
Color indexlabel
Size Small
EndFont
MultiPar false
CustomPars false
ForcePlain true
End
InsetLayout IndexMacro:seealso
CopyStyle IndexMacro:see
LabelString "See also"
End
InsetLayout IndexMacro:sortkey
CopyStyle IndexMacro:see
LabelString "Sort as"
End
InsetLayout IndexMacro:subentry
CopyStyle IndexMacro:see
LabelString "Subentry"
End
InsetLayout Box
LabelFont
Color foreground

View File

@ -4414,6 +4414,7 @@ def revert_docbook_mathml_prefix(document):
return
del document.header[i]
def revert_document_metadata(document):
"""Revert document metadata"""
i = 0
@ -4427,6 +4428,124 @@ def revert_document_metadata(document):
break
document.header[i : j + 1] = []
def revert_index_macros(document):
" Revert inset index macros "
i = 0
while True:
i = find_token(document.body, '\\begin_inset Index', i+1)
if i == -1:
break
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Can't find end of index inset at line %d" % i)
continue
pl = find_token(document.body, '\\begin_layout Plain Layout', i, j)
if pl == -1:
document.warning("Malformed LyX document: Can't find plain layout in index inset at line %d" % i)
continue
# find, store and remove inset params
pr = find_token(document.body, 'range', i, pl)
prval = get_quoted_value(document.body, "range", pr)
pagerange = ""
if prval == "start":
pagerange = "("
elif prval == "end":
pagerange = ")"
pf = find_token(document.body, 'pageformat', i, pl)
pageformat = get_quoted_value(document.body, "pageformat", pf)
del document.body[pr:pf+1]
# Now re-find (potentially moved) inset end again, and search for subinsets
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Can't find end of index inset at line %d" % i)
continue
# We search for all possible subentries in turn, store their
# content and delete them
see = []
seealso = []
subentry = []
subentry2 = []
sortkey = []
# Two subentries are allowed, thus the duplication
imacros = ["seealso", "see", "subentry", "subentry", "sortkey"]
for imacro in imacros:
iim = find_token(document.body, "\\begin_inset IndexMacro %s" % imacro, i, j)
if iim == -1:
continue
iime = find_end_of_inset(document.body, iim)
if iime == -1:
document.warning("Malformed LyX document: Can't find end of index macro inset at line %d" % i)
continue
iimpl = find_token(document.body, '\\begin_layout Plain Layout', iim, iime)
if iimpl == -1:
document.warning("Malformed LyX document: Can't find plain layout in index macro inset at line %d" % i)
continue
iimple = find_end_of_layout(document.body, iimpl)
if iimple == -1:
document.warning("Malformed LyX document: Can't find end of index macro inset plain layout at line %d" % i)
continue
icont = document.body[iimpl:iimple]
if imacro == "seealso":
seealso = icont[1:]
elif imacro == "see":
see = icont[1:]
elif imacro == "subentry":
# subentries might hace their own sortkey!
xiim = find_token(document.body, "\\begin_inset IndexMacro sortkey", iimpl, iimple)
if xiim != -1:
xiime = find_end_of_inset(document.body, xiim)
if xiime == -1:
document.warning("Malformed LyX document: Can't find end of index macro inset at line %d" % i)
else:
xiimpl = find_token(document.body, '\\begin_layout Plain Layout', xiim, xiime)
if xiimpl == -1:
document.warning("Malformed LyX document: Can't find plain layout in index macro inset at line %d" % i)
else:
xiimple = find_end_of_layout(document.body, xiimpl)
if xiimple == -1:
document.warning("Malformed LyX document: Can't find end of index macro inset plain layout at line %d" % i)
else:
xicont = document.body[xiimpl:xiimple]
xxicont = document.body[iimpl:xiimpl] + document.body[xiimple+1:iimple]
icont = xicont + put_cmd_in_ert("@") + xxicont[1:]
if len(subentry) > 0:
subentry2 = icont[1:]
else:
subentry = icont[1:]
elif imacro == "sortkey":
sortkey = icont
# Everything stored. Delete subinset.
del document.body[iim:iime+1]
# Again re-find (potentially moved) index inset end
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Can't find end of index inset at line %d" % i)
continue
# Now insert all stuff, starting from the inset end
pl = find_token(document.body, '\\begin_layout Plain Layout', i, j)
if pl == -1:
document.warning("Malformed LyX document: Can't find plain layout in index inset at line %d" % i)
continue
ple = find_end_of_layout(document.body, pl)
if ple == -1:
document.warning("Malformed LyX document: Can't find end of index macro inset plain layout at line %d" % i)
continue
if len(see) > 0:
document.body[ple:ple] = put_cmd_in_ert("|" + pagerange + "see{") + see + put_cmd_in_ert("}")
elif len(seealso) > 0:
document.body[ple:ple] = put_cmd_in_ert("|" + pagerange + "seealso{") + seealso + put_cmd_in_ert("}")
elif pageformat != "default":
document.body[ple:ple] = put_cmd_in_ert("|" + pagerange + pageformat)
if len(subentry2) > 0:
document.body[ple:ple] = put_cmd_in_ert("!") + subentry2
if len(subentry) > 0:
document.body[ple:ple] = put_cmd_in_ert("!") + subentry
if len(sortkey) > 0:
document.body[pl:pl+1] = document.body[pl:pl] + sortkey + put_cmd_in_ert("@")
##
# Conversion hub
#
@ -4497,10 +4616,12 @@ convert = [
[606, [convert_koma_frontispiece]],
[607, []],
[608, []],
[609, []]
[609, []],
[610, []]
]
revert = [[608, [revert_document_metadata]],
revert = [[609, [revert_index_macros]],
[608, [revert_document_metadata]],
[607, [revert_docbook_mathml_prefix]],
[606, [revert_spellchecker_ignore]],
[605, [revert_koma_frontispiece]],

View File

@ -632,6 +632,23 @@ Menuset
IndicesContext
End
Menu "context-edit-index"
OptItem "Insert Subentry|b" "indexmacro-insert subentry"
OptItem "Insert Sortkey|k" "indexmacro-insert sortkey"
OptItem "Insert See Reference|e" "indexmacro-insert see"
OptItem "Insert See also Reference|a" "indexmacro-insert seealso"
End
#
# IndexMacro context menu
#
Menu "context-indexmacro"
OptItem "See|e" "inset-modify changetype see"
OptItem "See also|a" "inset-modify changetype seealso"
End
#
# Index Lists context menu
#

View File

@ -391,6 +391,7 @@ Menuset
Item "Label...|L" "label-insert"
Captions
Indices
OptSubmenu "Index Properties" "index_properties"
Item "Nomenclature Entry...|y" "nomencl-insert"
Separator
Item "Table...|T" "tabular-insert"
@ -532,6 +533,13 @@ Menuset
Item "Double Frame|u" "box-insert Doublebox"
End
Menu "index_properties"
OptItem "Subentry|b" "indexmacro-insert subentry"
OptItem "Sortkey|k" "indexmacro-insert sortkey"
OptItem "See|e" "indexmacro-insert see"
OptItem "See also|a" "indexmacro-insert seealso"
End
Menu "insert_note"
Item "LyX Note|N" "note-insert Note"
Item "Comment|C" "note-insert Comment"

View File

@ -501,6 +501,8 @@ enum FuncCode
// 390
LFUN_SPELLING_REMOVE_LOCAL, // jspitzm 20210307
LFUN_BRANCH_SYNC_ALL, // sanda 20220415
LFUN_INDEXMACRO_INSERT, // spitz 20220220
// 395
LFUN_LASTACTION // end of the table
};

View File

@ -2307,6 +2307,16 @@ void LyXAction::init()
*/
{ LFUN_IN_MATHMACROTEMPLATE, "in-mathmacrotemplate", Noop, Math },
/*!
* \var lyx::FuncCode lyx::LFUN_INDEXMACRO_INSERT
* \li Action: Inserts special Index macros into the document.
* \li Syntax: indexmacro-insert <type>
* \li Params: <type>: see, seealso, subentry, sortkey.
* \li Origin: spitz, 20 Feb 2022
* \endvar
*/
{ LFUN_INDEXMACRO_INSERT, "indexmacro-insert", Noop, Edit },
/*!
* \var lyx::FuncCode lyx::LFUN_IPAMACRO_INSERT

View File

@ -565,6 +565,7 @@ SOURCEFILESINSETS = \
insets/InsetHyperlink.cpp \
insets/InsetInclude.cpp \
insets/InsetIndex.cpp \
insets/InsetIndexMacro.cpp \
insets/InsetInfo.cpp \
insets/InsetIPA.cpp \
insets/InsetIPAMacro.cpp \

View File

@ -58,6 +58,7 @@
#include "insets/InsetGraphics.h"
#include "insets/InsetGraphicsParams.h"
#include "insets/InsetInfo.h"
#include "insets/InsetIndexMacro.h"
#include "insets/InsetIPAMacro.h"
#include "insets/InsetNewline.h"
#include "insets/InsetQuotes.h"
@ -2090,6 +2091,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
case LFUN_BRANCH_INSERT:
case LFUN_PHANTOM_INSERT:
case LFUN_ERT_INSERT:
case LFUN_INDEXMACRO_INSERT:
case LFUN_LISTING_INSERT:
case LFUN_MARGINALNOTE_INSERT:
case LFUN_ARGUMENT_INSERT:
@ -3275,6 +3277,14 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
}
code = HYPERLINK_CODE;
break;
case LFUN_INDEXMACRO_INSERT: {
string const arg = cmd.getArg(0);
if (arg == "sortkey")
code = INDEXMACRO_SORTKEY_CODE;
else
code = INDEXMACRO_CODE;
break;
}
case LFUN_IPAMACRO_INSERT: {
string const arg = cmd.getArg(0);
if (arg == "deco")

View File

@ -34,6 +34,7 @@
#include "insets/InsetHyperlink.h"
#include "insets/InsetInclude.h"
#include "insets/InsetIndex.h"
#include "insets/InsetIndexMacro.cpp"
#include "insets/InsetInfo.h"
#include "insets/InsetIPA.h"
#include "insets/InsetIPAMacro.h"
@ -159,6 +160,16 @@ Inset * createInsetHelper(Buffer * buf, FuncRequest const & cmd)
return new InsetIPADeco(buf, arg2);
}
case LFUN_INDEXMACRO_INSERT: {
string const arg = cmd.getArg(0);
if (arg != "see" && arg != "seealso"
&& arg != "subentry" && arg != "sortkey") {
LYXERR0("LFUN_INDEXMACRO_INSERT: wrong argument");
return nullptr;
}
return new InsetIndexMacro(buf, arg);
}
case LFUN_ERT_INSERT:
return new InsetERT(buf);
@ -667,6 +678,9 @@ Inset * readInset(Lexer & lex, Buffer * buf)
inset.reset(new InsetCaption(buf, s));
} else if (tmptok == "Index") {
inset.reset(new InsetIndex(buf, InsetIndexParams()));
} else if (tmptok == "IndexMacro") {
string s = lex.getString();
inset.reset(new InsetIndexMacro(buf, s));
} else if (tmptok == "FloatList") {
inset.reset(new InsetFloatList(buf));
} else if (tmptok == "Info") {

View File

@ -20,6 +20,7 @@
#include "BufferParams.h"
#include "FuncRequest.h"
#include "IndicesList.h"
#include "insets/InsetIndex.h"
#include <QPushButton>
@ -37,6 +38,18 @@ GuiIndex::GuiIndex(GuiView & lv)
this, SLOT(slotButtonBox(QAbstractButton *)));
connect(indicesCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
rangeCO->addItem(qt_("None"), InsetIndexParams::None);
rangeCO->addItem(qt_("Start"), InsetIndexParams::Start);
rangeCO->addItem(qt_("End"), InsetIndexParams::End);
connect(rangeCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
pageFormatCO->addItem(qt_("Default"), toqstr("default"));
pageFormatCO->addItem(qt_("Bold"), toqstr("textbf"));
pageFormatCO->addItem(qt_("Italic"), toqstr("textit"));
pageFormatCO->addItem(qt_("Emphasized"), toqstr("emph"));
pageFormatCO->addItem(qt_("Custom"), toqstr("custom"));
connect(pageFormatCO, SIGNAL(activated(int)), this, SLOT(pageFormatChanged(int)));
bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
@ -49,11 +62,26 @@ void GuiIndex::change_adaptor()
}
void GuiIndex::pageFormatChanged(int i)
{
QString const pf = pageFormatCO->itemData(i).toString();
pageFormatLE->setEnabled(pf == "custom");
change_adaptor();
}
void GuiIndex::updateContents()
{
typedef IndicesList::const_iterator const_iterator;
IndicesList const & indiceslist = buffer().params().indiceslist();
BufferParams const & bp = buffer().masterBuffer()->params();
indicesGB->setEnabled(bp.use_indices);
QString const pf = pageFormatCO->itemData(
pageFormatCO->currentIndex()).toString();
pageFormatLE->setEnabled(pf == "custom");
IndicesList const & indiceslist = bp.indiceslist();
docstring const cur_index = params_.index;
indicesCO->clear();
@ -64,8 +92,19 @@ void GuiIndex::updateContents()
indicesCO->addItem(toqstr(it->index()),
QVariant(toqstr(it->shortcut())));
int const pos = indicesCO->findData(toqstr(cur_index));
int pos = indicesCO->findData(toqstr(cur_index));
indicesCO->setCurrentIndex(pos);
pos = pageFormatCO->findData(toqstr(params_.pagefmt));
if (pos == -1) {
pos = pageFormatCO->findData("custom");
pageFormatLE->setText(toqstr(params_.pagefmt));
} else
pageFormatLE->clear();
pageFormatCO->setCurrentIndex(pos);
pos = rangeCO->findData(params_.range);
rangeCO->setCurrentIndex(pos);
}
@ -73,7 +112,15 @@ void GuiIndex::applyView()
{
QString const index = indicesCO->itemData(
indicesCO->currentIndex()).toString();
int const range = rangeCO->itemData(
rangeCO->currentIndex()).toInt();
QString const pagefmt = pageFormatCO->itemData(
pageFormatCO->currentIndex()).toString();
params_.index = qstring_to_ucs4(index);
params_.range = InsetIndexParams::PageRange(range);
params_.pagefmt = (pagefmt == "custom")
? fromqstr(pageFormatLE->text())
: fromqstr(pagefmt);
}

View File

@ -31,6 +31,7 @@ public:
private Q_SLOTS:
void change_adaptor();
void pageFormatChanged(int);
private:
/// Apply changes

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>262</width>
<height>121</height>
<width>384</width>
<height>288</height>
</rect>
</property>
<property name="windowTitle">
@ -16,50 +16,119 @@
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QGroupBox" name="indicesGB">
<property name="title">
<string>Available I&amp;ndexes</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="indicesLA">
<property name="text">
<string>Available I&amp;ndexes:</string>
</property>
<property name="buddy">
<cstring>indicesCO</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="indicesCO">
<property name="toolTip">
<string>Select the index this entry should be listed in.</string>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="paginationGB">
<property name="title">
<string>&amp;Pagination</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="rangeLA">
<property name="text">
<string>Page &amp;Range:</string>
</property>
<property name="buddy">
<cstring>rangeCO</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="rangeCO">
<property name="toolTip">
<string>If the entry spans multiple pages, you can start or end the range here</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>112</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="pageFormatLA">
<property name="text">
<string>&amp;Format:</string>
</property>
<property name="buddy">
<cstring>pageFormatCO</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="pageFormatCO">
<property name="toolTip">
<string>Customize the format of the page number here. Note that the format is not used with &quot;See&quot; and &quot;See also&quot; references.</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="pageFormatLE">
<property name="toolTip">
<string>Enter custom command here (without leading backslash).</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<tabstops>

View File

@ -239,6 +239,10 @@ enum InsetCode {
///
COUNTER_CODE,
///
INDEXMACRO_CODE, // 110
///
INDEXMACRO_SORTKEY_CODE,
///
INSET_CODE_SIZE
};

View File

@ -322,7 +322,7 @@ void InsetCommandParams::Read(Lexer & lex, Buffer const * buffer)
preview_ = lex.getBool();
continue;
}
if (info_.hasParam(token)) {
if (hasParam(token)) {
lex.next(true);
docstring data = lex.getDocString();
if (buffer && token == "filename") {
@ -604,10 +604,24 @@ docstring InsetCommandParams::getFirstNonOptParam() const
}
bool InsetCommandParams::hasParam(std::string const & name) const
{
return info_.hasParam(name);
}
docstring const & InsetCommandParams::getParamOr(std::string const & name, docstring const & defaultValue) const
{
if (hasParam(name))
return (*this)[name];
return defaultValue;
}
docstring const & InsetCommandParams::operator[](string const & name) const
{
static const docstring dummy;
LASSERT(info_.hasParam(name), return dummy);
LASSERT(hasParam(name), return dummy);
ParamMap::const_iterator data = params_.find(name);
if (data == params_.end() || data->second.empty())
return dummy;
@ -620,7 +634,7 @@ docstring const & InsetCommandParams::operator[](string const & name) const
docstring & InsetCommandParams::operator[](string const & name)
{
LATTEST(info_.hasParam(name));
LATTEST(hasParam(name));
// this will add the name in release mode
ParamInfo::ParamData const & param = info_[name];
if (param.ignore())

View File

@ -146,6 +146,10 @@ public:
/// FIXME Would be better removed, but is used in BufferView.cpp in
/// ways that make removal hard.
docstring getFirstNonOptParam() const;
/// Determine whether a parameter is set
bool hasParam(std::string const & name) const;
/// Get the parameter \p name if it is set, \p defaultValue otherwise
docstring const & getParamOr(std::string const & name, docstring const & defaultValue) const;
/// get parameter \p name
/// LyX will assert if name is not a valid parameter.
docstring const & operator[](std::string const & name) const;

File diff suppressed because it is too large Load Diff

View File

@ -19,17 +19,28 @@
namespace lyx {
class IndexEntry;
class InsetIndexParams {
public:
enum PageRange {
None,
Start,
End
};
///
explicit InsetIndexParams(docstring const & b = docstring())
: index(b) {}
: index(b), range(None), pagefmt("default") {}
///
void write(std::ostream & os) const;
///
void read(Lexer & lex);
///
docstring index;
///
PageRange range;
///
std::string pagefmt;
};
@ -44,6 +55,8 @@ public:
///
static void string2params(std::string const &, InsetIndexParams &);
///
const InsetIndexParams& params() const { return params_; }
///
int rowFlags() const override { return CanBreakBefore | CanBreakAfter; }
private:
///
@ -65,6 +78,9 @@ private:
///
void latex(otexstream &, OutputParams const &) const override;
///
void processLatexSorting(otexstream &, OutputParams const &,
docstring const, docstring const) const;
///
bool showInsetDialog(BufferView *) const override;
///
bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const override;
@ -82,15 +98,46 @@ private:
/// Updates needed features for this inset.
void validate(LaTeXFeatures & features) const override;
///
void getSortkey(otexstream &, OutputParams const &) const;
///
docstring getSortkeyAsText(OutputParams const &) const;
///
void getSubentries(otexstream &, OutputParams const &) const;
///
std::vector<docstring> getSubentriesAsText(OutputParams const &,
bool const asLabel = false) const;
///
docstring getMainSubentryAsText(OutputParams const & runparams) const;
///
void getSeeRefs(otexstream &, OutputParams const &) const;
///
docstring getSeeAsText(OutputParams const & runparams) const;
///
std::vector<docstring> getSeeAlsoesAsText(OutputParams const & runparams) const;
///
bool hasSubentries() const;
///
bool hasSeeRef() const;
///
bool hasSortKey() const;
///
bool macrosPossible(std::string const type) const;
///
std::string contextMenuName() const override;
///
std::string contextMenu(BufferView const &, int, int) const override;
///
Inset * clone() const override { return new InsetIndex(*this); }
/// Is the content of this inset part of the immediate text sequence?
bool isPartOfTextSequence() const override { return false; }
///
bool insetAllowed(InsetCode code) const override;
///
friend class InsetIndexParams;
///
friend class IndexEntry;
///
InsetIndexParams params_;
};

View File

@ -0,0 +1,384 @@
/**
* \file InsetIndexMacro.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Jürgen Spitzmüller
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "InsetIndexMacro.h"
#include "Buffer.h"
#include "BufferParams.h"
#include "Cursor.h"
#include "Dimension.h"
#include "Encoding.h"
#include "ErrorList.h"
#include "FontInfo.h"
#include "FuncRequest.h"
#include "FuncStatus.h"
#include "InsetLayout.h"
#include "InsetList.h"
#include "LaTeX.h"
#include "LaTeXFeatures.h"
#include "Lexer.h"
#include "MetricsInfo.h"
#include "xml.h"
#include "texstream.h"
#include "frontends/alert.h"
#include "support/debug.h"
#include "support/docstream.h"
#include "support/gettext.h"
#include "support/lstrings.h"
#include "support/Translator.h"
using namespace std;
using namespace lyx::support;
namespace lyx {
namespace {
typedef Translator<string, InsetIndexMacroParams::Type> InsetIndexMacroTranslator;
typedef Translator<docstring, InsetIndexMacroParams::Type> InsetIndexMacroTranslatorLoc;
InsetIndexMacroTranslator const init_insetindexmacrotranslator()
{
InsetIndexMacroTranslator translator("see", InsetIndexMacroParams::See);
translator.addPair("seealso", InsetIndexMacroParams::Seealso);
translator.addPair("subentry", InsetIndexMacroParams::Subentry);
translator.addPair("sortkey", InsetIndexMacroParams::Sortkey);
return translator;
}
InsetIndexMacroTranslatorLoc const init_insetindexmacrotranslator_loc()
{
InsetIndexMacroTranslatorLoc translator(_("See"), InsetIndexMacroParams::See);
translator.addPair(_("See also"), InsetIndexMacroParams::Seealso);
translator.addPair(_("Subentry"), InsetIndexMacroParams::Subentry);
translator.addPair(_("Sort as"), InsetIndexMacroParams::Sortkey);
return translator;
}
InsetIndexMacroTranslator const & insetindexmacrotranslator()
{
static InsetIndexMacroTranslator const macrotranslator =
init_insetindexmacrotranslator();
return macrotranslator;
}
InsetIndexMacroTranslatorLoc const & insetindexmacrotranslator_loc()
{
static InsetIndexMacroTranslatorLoc const translator =
init_insetindexmacrotranslator_loc();
return translator;
}
} // namespace
InsetIndexMacroParams::InsetIndexMacroParams()
: type(See)
{}
void InsetIndexMacroParams::write(ostream & os) const
{
string const label = insetindexmacrotranslator().find(type);
os << "IndexMacro " << label << "\n";
}
void InsetIndexMacroParams::read(Lexer & lex)
{
string label;
lex >> label;
if (lex)
type = insetindexmacrotranslator().find(label);
}
/////////////////////////////////////////////////////////////////////
//
// InsetIndexMacro
//
/////////////////////////////////////////////////////////////////////
InsetIndexMacro::InsetIndexMacro(Buffer * buf, string const & label)
: InsetCollapsible(buf)
{
setDrawFrame(true);
setFrameColor(Color_insetframe);
params_.type = insetindexmacrotranslator().find(label);
}
InsetIndexMacro::~InsetIndexMacro()
{}
docstring InsetIndexMacro::layoutName() const
{
return from_ascii("IndexMacro:" + insetindexmacrotranslator().find(params_.type));
}
InsetCode InsetIndexMacro::lyxCode() const
{
return params_.type == InsetIndexMacroParams::Sortkey
? INDEXMACRO_SORTKEY_CODE
: INDEXMACRO_CODE;
}
void InsetIndexMacro::write(ostream & os) const
{
params_.write(os);
InsetCollapsible::write(os);
}
void InsetIndexMacro::read(Lexer & lex)
{
params_.read(lex);
InsetCollapsible::read(lex);
}
void InsetIndexMacro::getLatex(otexstream & os, OutputParams const & runparams) const
{
if (params_.type == InsetIndexMacroParams::Subentry) {
if (hasSortKey()) {
getSortkey(os, runparams);
os << "@";
} else {
odocstringstream ourlatex;
otexstream ots(ourlatex);
InsetText::latex(ots, runparams);
odocstringstream ourplain;
InsetText::plaintext(ourplain, runparams);
// These are the LaTeX and plaintext representations
docstring latexstr = ourlatex.str();
docstring plainstr = ourplain.str();
processLatexSorting(os, runparams, latexstr, plainstr);
}
return;
}
if (params_.type == InsetIndexMacroParams::See)
os << "see{";
else if (params_.type == InsetIndexMacroParams::Seealso)
os << "seealso{";
InsetCollapsible::latex(os, runparams);
if (params_.type == InsetIndexMacroParams::See
|| params_.type == InsetIndexMacroParams::Seealso)
os << "}";
}
int InsetIndexMacro::getPlaintext(odocstringstream & os,
OutputParams const & runparams, size_t max_length) const
{
return InsetText::plaintext(os, runparams, max_length);
}
void InsetIndexMacro::getDocbook(XMLStream & xs, OutputParams const & runparams) const
{
InsetText::docbook(xs, runparams);
}
docstring InsetIndexMacro::getXhtml(XMLStream & xs, OutputParams const & runparams) const
{
return InsetText::xhtml(xs, runparams);
}
void InsetIndexMacro::doDispatch(Cursor & cur, FuncRequest & cmd)
{
switch (cmd.action()) {
case LFUN_INSET_MODIFY: {
if (cmd.getArg(0) == "changetype") {
cur.recordUndoInset(this);
params_.type = insetindexmacrotranslator().find(cmd.getArg(1));
break;
}
InsetCollapsible::doDispatch(cur, cmd);
break;
}
default:
InsetCollapsible::doDispatch(cur, cmd);
break;
}
}
bool InsetIndexMacro::getStatus(Cursor & cur, FuncRequest const & cmd,
FuncStatus & flag) const
{
switch (cmd.action()) {
case LFUN_INSET_MODIFY:
if (cmd.getArg(0) == "changetype") {
docstring const newtype = from_utf8(cmd.getArg(1));
bool const enabled = (params_.type == InsetIndexMacroParams::See
|| params_.type == InsetIndexMacroParams::Seealso)
&& (newtype == "see" || newtype == "seealso");
flag.setEnabled(enabled);
flag.setOnOff(
newtype == from_ascii(insetindexmacrotranslator().find(params_.type)));
return true;
}
return InsetCollapsible::getStatus(cur, cmd, flag);
default:
return InsetCollapsible::getStatus(cur, cmd, flag);
}
}
void InsetIndexMacro::processLatexSorting(otexstream & os, OutputParams const & runparams,
docstring const latex, docstring const plain) const
{
if (contains(latex, '\\') && !contains(latex, '@')) {
// Plaintext might return nothing (e.g. for ERTs).
// In that case, we use LaTeX.
docstring const spart = (plain.empty()) ? latex : plain;
// Now we need to validate that all characters in
// the sorting part are representable in the current
// encoding. If not try the LaTeX macro which might
// or might not be a good choice, and issue a warning.
pair<docstring, docstring> spart_latexed =
runparams.encoding->latexString(spart, runparams.dryrun);
if (!spart_latexed.second.empty())
LYXERR0("Uncodable character in index entry. Sorting might be wrong!");
if (spart != spart_latexed.first && !runparams.dryrun) {
TeXErrors terr;
ErrorList & errorList = buffer().errorList("Export");
docstring const s = bformat(_("LyX's automatic index sorting algorithm faced "
"problems with the sub-entry '%1$s'.\n"
"Please specify the sorting of this entry manually, as "
"explained in the User Guide."), spart);
Paragraph const & par = buffer().paragraphs().front();
errorList.push_back(ErrorItem(_("Index sorting failed"), s,
{par.id(), 0}, {par.id(), -1}));
buffer().bufferErrors(terr, errorList);
}
// Remove remaining \'s from the sort key
docstring ppart = subst(spart_latexed.first, from_ascii("\\"), docstring());
// Plain quotes need to be escaped, however (#10649), as this
// is the default escape character
ppart = subst(ppart, from_ascii("\""), from_ascii("\\\""));
// Now insert the sortkey, separated by '@'.
os << ppart;
os << '@';
}
// Insert the actual level text
os << latex;
}
docstring InsetIndexMacro::toolTip(BufferView const &, int, int) const
{
return insetindexmacrotranslator_loc().find(params_.type);
}
string InsetIndexMacro::params2string(InsetIndexMacroParams const & params)
{
ostringstream data;
data << "IndexMacro" << ' ';
params.write(data);
return data.str();
}
void InsetIndexMacro::string2params(string const & in, InsetIndexMacroParams & params)
{
params = InsetIndexMacroParams();
if (in.empty())
return;
istringstream data(in);
Lexer lex;
lex.setStream(data);
lex.setContext("InsetIndexMacro::string2params");
lex >> "IndexMacro" >> "see";
params.read(lex);
}
bool InsetIndexMacro::hasSortKey() const
{
Paragraph const & par = paragraphs().front();
InsetList::const_iterator it = par.insetList().begin();
for (; it != par.insetList().end(); ++it) {
Inset & inset = *it->inset;
if (inset.lyxCode() == INDEXMACRO_SORTKEY_CODE)
return true;
}
return false;
}
void InsetIndexMacro::getSortkey(otexstream & os, OutputParams const & runparams) const
{
Paragraph const & par = paragraphs().front();
InsetList::const_iterator it = par.insetList().begin();
for (; it != par.insetList().end(); ++it) {
Inset & inset = *it->inset;
if (inset.lyxCode() == INDEXMACRO_SORTKEY_CODE) {
InsetIndexMacro const & iim =
static_cast<InsetIndexMacro const &>(inset);
iim.getLatex(os, runparams);
return;
}
}
}
string InsetIndexMacro::contextMenuName() const
{
return "context-indexmacro";
}
string InsetIndexMacro::contextMenu(BufferView const & bv, int x, int y) const
{
// We override the implementation of InsetCollapsible,
// because we have eytra entries.
string owncm = "context-edit-index;";
return owncm + InsetCollapsible::contextMenu(bv, x, y);
}
bool InsetIndexMacro::insetAllowed(InsetCode code) const
{
switch (code) {
case INDEX_CODE:
return false;
case INDEXMACRO_SORTKEY_CODE:
return (params_.type == InsetIndexMacroParams::Subentry
&& !hasSortKey());
default:
return InsetCollapsible::insetAllowed(code);
}
}
} // namespace lyx

View File

@ -0,0 +1,125 @@
// -*- C++ -*-
/**
* \file InsetIndexMacro.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Jürgen Spitzmüller
*
* Full author contact details are available in file CREDITS.
*/
#ifndef INSET_INSETMACRO_H
#define INSET_INSETMACRO_H
#include "Inset.h"
#include "InsetCollapsible.h"
namespace lyx {
class LaTeXFeatures;
class InsetIndexMacroParams
{
public:
enum Type {
See,
Seealso,
Subentry,
Sortkey
};
///
InsetIndexMacroParams();
///
void write(std::ostream & os) const;
///
void read(Lexer & lex);
///
Type type;
};
/////////////////////////////////////////////////////////////////////////
//
// InsetIndexMacro
//
/////////////////////////////////////////////////////////////////////////
/// Used to insert index references
class InsetIndexMacro : public InsetCollapsible
{
public:
///
InsetIndexMacro(Buffer *, std::string const &);
///
~InsetIndexMacro();
///
static std::string params2string(InsetIndexMacroParams const &);
///
static void string2params(std::string const &, InsetIndexMacroParams &);
///
InsetIndexMacroParams const & params() const { return params_; }
///
void getLatex(otexstream &, OutputParams const &) const;
///
int getPlaintext(odocstringstream &, OutputParams const &, size_t) const;
///
void getDocbook(XMLStream &, OutputParams const &) const;
private:
///
InsetCode lyxCode() const override;
///
docstring layoutName() const override;
///
void write(std::ostream &) const override;
///
void read(Lexer & lex) override;
///
bool neverIndent() const override { return true; }
/// We do not output anything directly to the stream
void latex(otexstream &, OutputParams const &) const override {};
/// We do not output anything directly to the stream
int plaintext(odocstringstream &, OutputParams const &, size_t) const override { return 0; };
/// We do not output anything directly to the stream
void docbook(XMLStream &, OutputParams const &) const override {};
/// We do not output anything directly to the stream
docstring xhtml(XMLStream &, OutputParams const &) const override { return docstring(); };
///
docstring getXhtml(XMLStream &, OutputParams const &) const;
///
bool allowSpellCheck() const override { return false; }
///
bool insetAllowed(InsetCode code) const override;
///
bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const override;
///
void doDispatch(Cursor & cur, FuncRequest & cmd) override;
///
docstring toolTip(BufferView const & bv, int x, int y) const override;
///
void processLatexSorting(otexstream &, OutputParams const &,
docstring const, docstring const) const;
///
bool hasSortKey() const;
///
void getSortkey(otexstream &, OutputParams const &) const;
///
std::string contextMenuName() const override;
///
std::string contextMenu(BufferView const &, int, int) const override;
///
Inset * clone() const override { return new InsetIndexMacro(*this); }
/// used by the constructors
void init();
///
friend class InsetIndexMacroParams;
///
InsetIndexMacroParams params_;
};
} // namespace lyx
#endif

View File

@ -1040,6 +1040,10 @@ bool InsetText::insetAllowed(InsetCode code) const
case QUOTE_CODE:
case COUNTER_CODE:
return true;
// These are only allowed in index insets
case INDEXMACRO_CODE:
case INDEXMACRO_SORTKEY_CODE:
return false;
default:
return !isPassThru();
}

View File

@ -487,7 +487,40 @@ bool Parser::hasOpt(string const & l)
}
Parser::Arg Parser::getFullArg(char left, char right, bool allow_escaping)
bool Parser::hasIdxMacros(string const & c, string const & e)
{
// Check for index entry separator (! or @),
// consider escaping via "
// \p e marks a terminating delimiter¸
// remember current position
unsigned int oldpos = pos_;
// skip spaces and comments
bool retval = false;
while (good()) {
get_token();
if (isParagraph()) {
putback();
break;
}
if (curr_token().cat() == catEnd)
break;
if (!e.empty() && curr_token().asInput() == e
&& prev_token().asInput() != "\"")
break;
if (curr_token().asInput() == c
&& prev_token().asInput() != "\"") {
retval = true;
break;
}
continue;
}
pos_ = oldpos;
return retval;
}
Parser::Arg Parser::getFullArg(char left, char right, bool allow_escaping, char e)
{
skip_spaces(true);
@ -496,24 +529,27 @@ Parser::Arg Parser::getFullArg(char left, char right, bool allow_escaping)
if (! good())
return make_pair(false, string());
int group_level = 0;
int group_level = (left == '{') ? 1 : 0;
string result;
Token t = get_token();
if (t.cat() == catComment || t.cat() == catEscape ||
t.character() != left) {
if (left != char()
&& (t.cat() == catComment || t.cat() == catEscape
|| t.character() != left)) {
putback();
return make_pair(false, string());
} else {
while (good()) {
t = get_token();
// honor grouping
if (left != '{' && t.cat() == catBegin) {
if (t.cat() == catBegin) {
++group_level;
if (left != '{')
continue;
}
if (left != '{' && t.cat() == catEnd) {
if (group_level > 0 && t.cat() == catEnd) {
--group_level;
if (left != '{')
continue;
}
// Ignore comments
@ -526,6 +562,10 @@ Parser::Arg Parser::getFullArg(char left, char right, bool allow_escaping)
if (t.cat() != catEscape && t.character() == right
&& group_level == 0)
break;
} else if (e != char()) {
if (prev_token().character() != e && t.character() == right
&& group_level == 0)
break;
} else {
if (t.character() == right) {
if (t.cat() == catEscape)
@ -541,9 +581,9 @@ Parser::Arg Parser::getFullArg(char left, char right, bool allow_escaping)
}
string Parser::getArg(char left, char right, bool allow_escaping)
string Parser::getArg(char left, char right, bool allow_escaping, char e)
{
return getFullArg(left, right, allow_escaping).second;
return getFullArg(left, right, allow_escaping, e).second;
}

View File

@ -215,17 +215,22 @@ public:
/// Does an optional argument follow after the current token?
bool hasOpt(std::string const & l = "[");
/// Does this index entry has levels?
bool hasIdxMacros(std::string const & c,
std::string const & e = std::string());
///
typedef std::pair<bool, std::string> Arg;
/*!
* Get an argument enclosed by \p left and \p right.
* If \p allow_escaping is true, a right delimiter escaped by a
* backslash does not count as delimiter, but is included in the
* argument.
* argument. The \p e allows for a different escape character
* (used in index insets)
* \returns whether an argument was found in \p Arg.first and the
* argument in \p Arg.second. \see getArg().
*/
Arg getFullArg(char left, char right, bool allow_escaping = true);
Arg getFullArg(char left, char right, bool allow_escaping = true,
char e = char());
/*!
* Get an argument enclosed by \p left and \p right.
* If \p allow_escaping is true, a right delimiter escaped by a
@ -236,7 +241,8 @@ public:
* getFullArg() if you need to know whether there was an empty
* argument or no argument at all.
*/
std::string getArg(char left, char right, bool allow_escaping = true);
std::string getArg(char left, char right, bool allow_escaping = true,
char e = char());
/*!
* Like getOpt(), but distinguishes between a missing argument ""
* and an empty argument "[]".

View File

@ -48,7 +48,8 @@ extern std::string rgbcolor2code(std::string const & name);
std::string translate_len(std::string const &);
void parse_text(Parser & p, std::ostream & os, unsigned flags, bool outer,
Context & context, std::string const & rdelim = "");
Context & context, std::string const & rdelim = "",
std::string const & rdelimesc = "");
void check_comment_bib(std::ostream & os, Context & context);
void fix_child_filename(std::string & name);
@ -68,7 +69,8 @@ std::string find_file(std::string const & name, std::string const & path,
void parse_text_in_inset(Parser & p, std::ostream & os, unsigned flags,
bool outer, Context & context,
InsetLayout const * layout = nullptr,
std::string const & rdelim = "");
std::string const & rdelim = "",
std::string const & rdelimesc = "");
/// Guess document language from \p p if CJK is used.
/// \p lang is used for all non-CJK contents.

View File

@ -55,7 +55,7 @@ void output_arguments(ostream &, Parser &, bool, bool, const string &, Context &
void parse_text_in_inset(Parser & p, ostream & os, unsigned flags, bool outer,
Context & context, InsetLayout const * layout,
string const & rdelim)
string const & rdelim, string const & rdelimesc)
{
bool const forcePlainLayout =
layout ? layout->forcePlainLayout() : false;
@ -78,7 +78,7 @@ void parse_text_in_inset(Parser & p, ostream & os, unsigned flags, bool outer,
parse_text(p, oss, FLAG_RDELIM, outer, dummy,
string(1, context.latexparam.back()));
}
parse_text(p, os, flags, outer, newcontext, rdelim);
parse_text(p, os, flags, outer, newcontext, rdelim, rdelimesc);
if (layout)
output_arguments(os, p, outer, false, "post", newcontext,
layout->postcommandargs());
@ -91,7 +91,8 @@ namespace {
void parse_text_in_inset(Parser & p, ostream & os, unsigned flags, bool outer,
Context const & context, string const & name,
string const & rdelim = string())
string const & rdelim = string(),
string const & rdelimesc = string())
{
InsetLayout const * layout = 0;
DocumentClass::InsetLayouts::const_iterator it =
@ -99,17 +100,18 @@ void parse_text_in_inset(Parser & p, ostream & os, unsigned flags, bool outer,
if (it != context.textclass.insetLayouts().end())
layout = &(it->second);
Context newcontext = context;
parse_text_in_inset(p, os, flags, outer, newcontext, layout, rdelim);
parse_text_in_inset(p, os, flags, outer, newcontext, layout, rdelim, rdelimesc);
}
/// parses a paragraph snippet, useful for example for \\emph{...}
void parse_text_snippet(Parser & p, ostream & os, unsigned flags, bool outer,
Context & context)
Context & context, string const & rdelim = string(),
string const & rdelimesc = string())
{
Context newcontext(context);
// Don't inherit the paragraph-level extra stuff
newcontext.par_extra_stuff.clear();
parse_text(p, os, flags, outer, newcontext);
parse_text(p, os, flags, outer, newcontext, rdelim, rdelimesc);
// Make sure that we don't create invalid .lyx files
context.need_layout = newcontext.need_layout;
context.need_end_layout = newcontext.need_end_layout;
@ -1506,6 +1508,218 @@ void parse_outer_box(Parser & p, ostream & os, unsigned flags, bool outer,
}
void parse_index_entry(Parser & p, ostream & os, Context & context, string const & kind)
{
// write inset header
begin_inset(os, "Index ");
os << kind;
// Parse for post argument (|...)
p.pushPosition();
string const marg = p.getArg('{', '}');
p.popPosition();
char lc = char();
bool inpost = false;
bool startrange = false;
bool endrange = false;
string post;
for (string::const_iterator it = marg.begin(), et = marg.end(); it != et; ++it) {
char c = *it;
if (inpost) {
if (post.empty() && c == '(')
startrange = true;
else if (post.empty() && c == ')')
endrange = true;
else
post += c;
}
if (!inpost && (c == '|' && lc != '"'))
inpost = true;
lc = c;
}
if (startrange)
os << "\nrange start";
else if (endrange)
os << "\nrange end";
else
os << "\nrange none";
bool const see = prefixIs(post, "see{");
bool const seealso = prefixIs(post, "seealso{");
if (!post.empty() && !see && !seealso)
os << "\npageformat " << post;
else
os << "\npageformat default";
os << "\nstatus collapsed\n";
bool main = true;
// save position
p.pushPosition();
// Check for levels
if (p.hasIdxMacros("!")) {
// Index entry with levels
while (p.hasIdxMacros("!")) {
if (main) {
// swallow brace
p.get_token();
os << "\\begin_layout Plain Layout\n";
} else {
begin_inset(os, "IndexMacro subentry");
os << "\nstatus collapsed\n";
}
// Check for (level-specific) sortkey
if (p.hasIdxMacros("@", "!")) {
if (!main)
os << "\\begin_layout Plain Layout\n";
begin_inset(os, "IndexMacro sortkey");
os << "\nstatus collapsed\n";
parse_text_in_inset(p, os, FLAG_RDELIM, false, context, "IndexMacro sortkey", "@", "\"");
end_inset(os);
}
parse_text_snippet(p, os, FLAG_RDELIM, false, context, "!", "\"");
if (!main) {
os << "\n\\end_layout\n";
end_inset(os);
}
main = false;
}
if (!main) {
begin_inset(os, "IndexMacro subentry");
os << "\nstatus collapsed\n";
}
// Final level
// Check for (level-specific) sortkey
if (p.hasIdxMacros("@", "!")) {
if (main) {
// swallow brace
p.get_token();
}
os << "\\begin_layout Plain Layout\n";
begin_inset(os, "IndexMacro sortkey");
os << "\nstatus collapsed\n";
parse_text_in_inset(p, os, FLAG_RDELIM, false, context, "IndexMacro sortkey", "@", "\"");
end_inset(os);
if (post.empty() && !startrange && !endrange) {
parse_text_snippet(p, os, FLAG_BRACE_LAST, false, context);
p.dropPosition();
} else {
// Handle post-argument
parse_text_snippet(p, os, FLAG_RDELIM, false, context, "|", "\"");
if (see || seealso) {
while (p.next_token().character() != '{' && p.good())
p.get_token();
// this ends the subinset, as the see[also] insets
// must come at main index inset
os << "\n\\end_layout\n";
end_inset(os);
if (see)
begin_inset(os, "IndexMacro see");
else
begin_inset(os, "IndexMacro seealso");
os << "\nstatus collapsed\n";
os << "\\begin_layout Plain Layout\n";
parse_text_snippet(p, os, FLAG_ITEM, false, context);
}
p.popPosition();
// swallow argument
p.getArg('{', '}');
}
os << "\n\\end_layout\n";
} else {
if (post.empty() && !startrange && !endrange) {
parse_text_in_inset(p, os, FLAG_BRACE_LAST, false, context, "IndexMacro subentry");
p.dropPosition();
} else {
// Handle post-argument
if (see || seealso) {
os << "\\begin_layout Plain Layout\n";
parse_text_snippet(p, os, FLAG_RDELIM, false, context, "|", "\"");
while (p.next_token().character() != '{' && p.good())
p.get_token();
// this ends the subinset, as the see[also] insets
// must come at main index inset
os << "\n\\end_layout\n";
end_inset(os);
if (see)
begin_inset(os, "IndexMacro see");
else
begin_inset(os, "IndexMacro seealso");
os << "\nstatus collapsed\n";
parse_text_in_inset(p, os, FLAG_ITEM, false, context, "IndexMacro see");
} else
parse_text_in_inset(p, os, FLAG_RDELIM, false, context, "Index", "|", "\"");
p.popPosition();
// swallow argument
p.getArg('{', '}');
}
}
if (!main)
end_inset(os);
os << "\n\\end_layout\n";
} else {
// Index without any levels
// Check for sortkey
if (p.hasIdxMacros("@", "!")) {
// swallow brace
p.get_token();
os << "\\begin_layout Plain Layout\n";
begin_inset(os, "IndexMacro sortkey");
os << "\nstatus collapsed\n";
parse_text_in_inset(p, os, FLAG_RDELIM, false, context, "IndexMacro sortkey", "@", "\"");
end_inset(os);
if (post.empty() && !startrange && !endrange) {
parse_text_snippet(p, os, FLAG_BRACE_LAST, false, context);
p.dropPosition();
} else {
parse_text_snippet(p, os, FLAG_RDELIM, false, context, "|", "\"");
if (see || seealso) {
while (p.next_token().character() != '{' && p.good())
p.get_token();
if (see)
begin_inset(os, "IndexMacro see");
else
begin_inset(os, "IndexMacro seealso");
os << "\nstatus collapsed\n";
parse_text_in_inset(p, os, FLAG_ITEM, false, context, "IndexMacro see");
end_inset(os);
}
p.popPosition();
// swallow argument
p.getArg('{', '}');
}
os << "\n\\end_layout\n";
} else {
if (post.empty() && !startrange && !endrange) {
parse_text_in_inset(p, os, FLAG_ITEM, false, context, "Index");
p.dropPosition();
} else {
// Handle post-argument
// swallow brace
p.get_token();
if (see || seealso) {
os << "\\begin_layout Plain Layout\n";
parse_text_snippet(p, os, FLAG_RDELIM, false, context, "|", "\"");
while (p.next_token().character() != '{' && p.good())
p.get_token();
if (see)
begin_inset(os, "IndexMacro see");
else
begin_inset(os, "IndexMacro seealso");
os << "\nstatus collapsed\n";
parse_text_in_inset(p, os, FLAG_ITEM, false, context, "IndexMacro see");
end_inset(os);
os << "\n\\end_layout\n";
} else
parse_text_in_inset(p, os, FLAG_RDELIM, false, context, "Index", "|", "\"");
p.popPosition();
// swallow argument
p.getArg('{', '}');
}
}
}
end_inset(os);
}
void parse_listings(Parser & p, ostream & os, Context & parent_context,
bool in_line, bool use_minted)
{
@ -2901,7 +3115,7 @@ void fix_child_filename(string & name)
void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
Context & context, string const & rdelim)
Context & context, string const & rdelim, string const & rdelimesc)
{
Layout const * newlayout = 0;
InsetLayout const * newinsetlayout = 0;
@ -2990,7 +3204,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
if (rdelim.size() > 1)
tok += p.next_token().asInput();
if (t.cat() != catEscape && !rdelim.empty()
&& tok == rdelim && (flags & FLAG_RDELIM)) {
&& tok == rdelim && (flags & FLAG_RDELIM)
&& (rdelimesc.empty() || p.prev_token().asInput() != rdelimesc)) {
if (rdelim.size() > 1)
p.get_token(); // eat rdelim
return;
@ -4712,10 +4927,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
string const arg = (t.cs() == "sindex" && p.hasOpt()) ?
p.getArg('[', ']') : "";
string const kind = arg.empty() ? "idx" : arg;
begin_inset(os, "Index ");
os << kind << "\nstatus collapsed\n";
parse_text_in_inset(p, os, FLAG_ITEM, false, context, "Index");
end_inset(os);
parse_index_entry(p, os, context, kind);
if (kind != "idx")
preamble.registerAutomaticallyLoadedPackage("splitidx");
continue;

View File

@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
#define LYX_FORMAT_LYX 609 // spitz: document metadata
#define LYX_FORMAT_TEX2LYX 609
#define LYX_FORMAT_LYX 610 // spitz: inset index macros
#define LYX_FORMAT_TEX2LYX 610
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER