From 8319b3e9d615adc6b4b49a67308884400d20373f Mon Sep 17 00:00:00 2001 From: Juergen Spitzmueller Date: Sun, 8 Jan 2017 09:39:46 +0100 Subject: [PATCH] Biblatex support File format change --- development/FORMAT | 17 + lib/Makefile.am | 2 + lib/chkconfig.ltx | 1 + lib/citeengines/basic.citeengine | 2 +- lib/citeengines/biblatex-natbib.citeengine | 321 +++++++++++++++++++ lib/citeengines/biblatex.citeengine | 302 ++++++++++++++++++ lib/citeengines/jurabib.citeengine | 2 +- lib/citeengines/natbib.citeengine | 2 +- lib/lyx2lyx/lyx_2_3.py | 201 +++++++++++- src/Buffer.cpp | 118 ++++++- src/Buffer.h | 12 + src/BufferParams.cpp | 69 ++++- src/BufferParams.h | 10 + src/frontends/qt4/GuiBibtex.cpp | 64 ++-- src/frontends/qt4/GuiBibtex.h | 2 + src/frontends/qt4/GuiDocument.cpp | 233 +++++++++++--- src/frontends/qt4/GuiDocument.h | 11 +- src/frontends/qt4/ui/BiblioUi.ui | 235 +++++++++++--- src/frontends/qt4/ui/BibtexUi.ui | 341 +++++++++++---------- src/insets/InsetBibtex.cpp | 292 ++++++++---------- src/insets/InsetBibtex.h | 2 + src/tex2lyx/TODO.txt | 28 ++ src/version.h | 4 +- 23 files changed, 1835 insertions(+), 436 deletions(-) create mode 100644 lib/citeengines/biblatex-natbib.citeengine create mode 100644 lib/citeengines/biblatex.citeengine diff --git a/development/FORMAT b/development/FORMAT index bc5ba478d6..37b8eba942 100644 --- a/development/FORMAT +++ b/development/FORMAT @@ -7,6 +7,23 @@ changes happened in particular if possible. A good example would be ----------------------- +2017-01-08 Jürgen Spitzmüller + * Format incremented to 528: Biblatex support + - New buffer param options: + \cite_engine biblatex | biblatex-natbib + - New buffer params: + \biblatex_bibstyle > biblatex bibliography style + (package option bibstyle=) + \biblatex_citestyle > biblatex citation style + (package option citestyle=) + \biblio_options > further biblatex package options + - \begin_inset CommandInset bibtex: + New param "biblatexopts" > options to \printbibliography + - \begin_inset CommandInset citation + New LatexCommand values: citebyear[][], Footcite[][], + Autocite[][], citetitle*[][], footfullcite[][], + supercite, Citeauthor*[][] + 2017-01-02 Richard Heck * Format incremented to 526: Support plural and capitalize options for refstyle-based references diff --git a/lib/Makefile.am b/lib/Makefile.am index 36c9c0c297..a0fcd9315b 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -2302,6 +2302,8 @@ dist_layouts_DATA =\ citeenginesdir = $(pkgdatadir)/citeengines dist_citeengines_DATA = \ citeengines/basic.citeengine \ + citeengines/biblatex.citeengine \ + citeengines/biblatex-natbib.citeengine \ citeengines/jurabib.citeengine \ citeengines/natbib.citeengine diff --git a/lib/chkconfig.ltx b/lib/chkconfig.ltx index 9daca8fc97..6c98afc97f 100644 --- a/lib/chkconfig.ltx +++ b/lib/chkconfig.ltx @@ -283,6 +283,7 @@ \TestPackage{authordate1-4} \TestPackage{babel} \TestPackage{beamerposter} +\TestPackage{biblatex} \TestPackage{bibtopic} \TestPackage{bicaption} \TestPackage{bidi} diff --git a/lib/citeengines/basic.citeengine b/lib/citeengines/basic.citeengine index f8d5c5baef..ae4a603986 100644 --- a/lib/citeengines/basic.citeengine +++ b/lib/citeengines/basic.citeengine @@ -3,7 +3,7 @@ # The basic citation capabilities provided by BibTeX. # Mainly simple numeric styles primarily suitable for science and maths. # DescriptionEnd -# Excludes: jurabib | natbib | biblatex +# Excludes: jurabib | natbib | biblatex | biblatex-natbib # Author: Julien Rioux diff --git a/lib/citeengines/biblatex-natbib.citeengine b/lib/citeengines/biblatex-natbib.citeengine new file mode 100644 index 0000000000..54c4356733 --- /dev/null +++ b/lib/citeengines/biblatex-natbib.citeengine @@ -0,0 +1,321 @@ +# \DeclareLyXCiteEngine[biblatex.sty]{Biblatex (natbib mode)} +# DescriptionBegin +# This Biblatex variety emulates the Natbib citation commands and +# thus is best suited for switching from Natbib (or the pre-LyX 2.3 +# Biblatex workaround) to Biblatex. +# The natbib mode supports slightly different and a few more styles +# than normal Biblatex. As with normal Biblatex, the use of 'biber' +# as Bibliography processor is advised. +# DescriptionEnd +# Excludes: basic | jurabib | biblatex | natbib + +# Author: Jürgen Spitzmüller + +Format 63 + +Requires biblatex + +PackageOptions biblatex natbib=true + +# The framework (biblatex|bibtex) +CiteFramework biblatex + +# Cite style variants (default|authoryear|natbib) +# We provide both authoryear and numerical citations +CiteEngineType authoryear|numerical + +# Default style files for either engine type +DefaultBiblio authoryear:authoryear|numerical:numeric + +# Maximum number of names before "et al." chimes in +MaxCiteNames 3 + + +# The syntax of the cite command definitions below is: +# LyXName|alias*[][]=latexcmd +# +# * LyXName: The LyX name as output in the LyX file. For +# portability reasons, we try to use the same +# name for same-formatted commands in the +# different engines (thus many names stem from +# natbib). +# * Alias: A (comma-separated) list of commands that fall +# back to the given LyX name in the current engine. +# This is a bit like "ObsoletedBy" in the layouts. +# * latexcmd: The actual LaTeX command that is output. +# +# Alias and latexcmd are optional. If no latexcmd is given, the +# LyXName will be output to LaTeX. +# +# Note further: +# +# * Capitalization indicates that the command also has a capitalized +# form (\Latexcmd vs. \latexcmd). These usually enforce upcasing of +# name prefixes (von Goethe => Von Goethe). +# * Brackets [] indicate the number of optional arguments (0, 1, 2). +# * The star * indicates there is a starred version of the command +# (\latexcmd* vs. \latexcmd). By default, the starred version means: +# Expand the author list even if the maxnames setting would cause +# BibTeX/Biber to shorten it with "et al.". +# If the star has a different meaning for a command, it can be +# specified in angle brackets: . +# Maximal two translatable macro keywords, marked by the prefix '!_', +# can be given. The first points to the string that replaces the +# "Full aut&hor list" checkbox label in the Citation dialog, the +# second one an optional tooltip for this checkbox. Note that these +# two macros have to be defined in the CiteFormat section (see below), +# dropping the '!' from the prefix (see below), e.g.: +# _stardesc Starred command label +# _stardesctooltip Tooltip for the starred command checkbox. + +# +# CITE COMMAND DEFINITIONS for either engine type +# +# We support the same cite command as natbib +# and add biblatex citation commands on top. + +CiteEngine authoryear + Citet|textcite*[][] + Citep|parencite*[][] + Citealt|cite*[][] + Citealp*[][] + Citeauthor*[][] + citeyearpar[][] + citeyear=cite* + citebyear[][]=citeyear + Footcite[][]=smartcite + Autocite[][] + citetitle*[][] + fullcite[][] + footfullcite[][] + nocite +End + +CiteEngine numerical + Citep|citealp,citealt*[][] + Citet|textcite*[][] + supercite + Footcite[][]=smartcite + Autocite[][] + Citeauthor[][]* + citeyearpar[][] + citeyear|citebyear[][] + citetitle*[][] + fullcite[][] + footfullcite[][] + nocite +End + + +# +# CITE FORMAT +# + +# The following defines how the commands are represented in the GUI +# (inset button and citation dialog) as well as in XHTML, docbook and +# plain text output. +# +# There are common definitions (default) and specific definitions for +# either cite engine type (which overwrite existing defaults. +# +CiteFormat default + # + # MACROS + # + # 1. Translatable bits (need to be marked by _ prefix) + # Note that preceding and trailing spaces matter. + # + _notcited not cited + _addtobib Add to bibliography only. + _finaland , and + _footnote Footnote + _foot Foot + _fullcite bibliography entry + _bibentry Full bibliography entry. + _autocite Autocite + _auto Auto + # GUI strings for the starred commands + _citetitlestar F&orce full title[[Possible substitute to All aut&hors]] + _citetitlestartooltip Use full title even if shorttitle exists + # The following are handled by BiblioInfo + _etal et al. + _namesep , [[separate author names in citation, except for last name]] + _lastnamesep , and [[separate name of last author in citation]] + _pairnamesep and [[separate two authors in citation]] + + # + # 2. Macros re-used in the style definitions + # + # NOTE: Year is always in parens, also in numerical style + !yearopen ( + !yearclose ) + + # A dummy year modifier. This just indicates that a modifier might be output, + # to differentiate \cite* and \citeyear + !dummymod [a] + + # A link that lets us jump to the bibliography entry in LyXHTML + # %clean:key% will be substituted by the cite key to give a unique id + !startlink {!!} + !endlink {!!} + + # Add " , and " before the last item (but " and " if there are only two), else ", " + !smartsep {%second%[[{%next%[[%_namesep%]][[%_pairnamesep%]]}]][[{%next%[[%_namesep%]][[%_lastnamesep%]]}]]} + + # "Author et al." or "??" + !abbrvauthor {%abbrvauthor%[[%abbrvauthor%]][[??]]} + # "prenote " + !textbefore {%textbefore%[[%textbefore% ]]} + # ", postnote" + !textafter {%textafter%[[, %textafter%]]} + # Add a year if it exists (else "??") and possibly a modifier (as in 2017a) + !makeyear {%year%[[%year%]][[??]]}{%modifier%[[%modifier%]]} + # Add a year if it exists (else "??") and indicate a possible modifier (as in 2017[a]) + !myear {%year%[[%year%]][[??]]}{%modifier%[[%modifier%]][[{%export%[[]][[%!dummymod%]]}]]} + # Add a year if it exists (else "??") without any modifier at all + !byear {%year%[[%year%]][[??]]} + # Add a shorttitle or title if it exists (else "??") + !makeshorttitle {%shorttitle%[[%shorttitle%]][[{%title%[[%title%]][[??]]}]]} + # Add a title (or "??") + !maketitle {%ifstar%[[{%title%[[%title%]][[??]]}]][[%!makeshorttitle%]]} + # "cf. Key..." + !fullcite %bibentry%%!nextfullcite% + + # "...; Author..." + !nextauthor {%next%[[%!sep% %!startlink%%!abbrvauthor%%!endlink%%!nextauthor%]]} + # "..., CiteKey..." + !nextkey {%next%[[%!sep% %key%%!nextkey%]]} + # ".., Year..." (including extra label, as in 2017a) + !nextyear {%next%[[%!sep% %!startlink%%!makeyear%%!endlink%%!nextyear%]]} + # "...; Nextyear ..." (including emulated extra label, as in 2017[a]) + !nextmyear {%next%[[%!sep% %!startlink%%!myear%%!endlink%%!nextmyear%]]} + # "...; Nextyear ..." (without any extra label) + !nextbyear {%next%[[%!sep% %!startlink%%!byear%%!endlink%%!nextbyear%]]} + # "...; Nexttitle ..." + !makenexttitle {%next%[[%!sep% %!startlink%%!maketitle%%!endlink%%!makenexttitle%]]} + # "...; NextKey..." + !nextfullcite {%next%[[%!sep% %bibentry%%!nextfullcite%]]} + + # + # ACTUAL STYLE DEFINITIONS + # + # (identical in authoryear and numerical) + # + + # "cf. Author; NextAuthor, p. xx" + citeauthor %!textbefore%%!startlink%%!abbrvauthor%%!endlink%%!nextauthor%%!textafter% + # "cf. Year; NextYear, S. xx" [Authoryear] / "cf. Year, NextYear, S. xx" [Numerical] + citeyear %!textbefore%%!startlink%%!myear%%!endlink%%!nextmyear%%!textafter% + # "cf. Year; Nextyear, p. xx" (without any extra label) + citebyear %!textbefore%%!startlink%%!byear%%!endlink%%!nextbyear%%!textafter% + # "(cf. Year; NextYear, p. xx)" [Authoryear] / "(cf. Year, NextYear, p. xx)" [Numerical] + citeyearpar %!yearopen%%!textbefore%%!startlink%%!makeyear%%!endlink%%!nextyear%%!textafter%%!yearclose% + # "cf. Year; Nextyear, p. xx" (without any extra label) + citetitle %!textbefore%%!startlink%%!maketitle%%!endlink%%!makenexttitle%%!textafter% + # "Bibliography entry." (dialog) / "cf. Key; NextKey..., p. xx (bibliography entry)" (button) + fullcite {%dialog%[[%_bibentry%]][[%!textbefore%{%label%[[%!fullcite%]][[%key%%!nextkey% (%_fullcite%)]]}%!textafter%}]]} + # "Footnote: Full bibliography entry." (dialog) / "Foot: Key (bibliography entry)" + footfullcite {%dialog%[[%_footnote%]][[%_foot%]]}: {%dialog%[[%_bibentry%]][[{%label%[[%!fullcite%]][[%key%%!nextkey% (%_fullcite%)]]}]]} + # "Add to bibliography only." (dialog) / "[ID] (not cited)" (button) + nocite {%dialog%[[%_addtobib%]][[%key%%!nextkey% (%_notcited%)]]} +End + +CiteFormat authoryear + # + # MACROS + # + !open ( + !sep ; + !close ) + + # "Author et al. (cf. Year..." + !makecitet %!startlink%%!abbrvauthor%%!endlink% %!open%%!textbefore%%!makeyear%%!nextcitet% + # "cf. Author et al. Year..." + !makecitealt %!textbefore%%!startlink%%!abbrvauthor% %!makeyear%%!endlink%%!nextcitealt% + # "Author et al., Year..." + !makecitealp %!startlink%%!abbrvauthor%, %!makeyear%%!endlink%%!nextcitealp% + + # "...), [and] Nextauthor (Year..." + !nextcitet {%next%[[%!close%%!smartsep%%!startlink%%!abbrvauthor%%!endlink% %!open%%!makeyear%%!nextcitet%]]} + # "...; NextAuthor et al. Year..." + !nextcitealt {%next%[[%!sep% %!startlink%%!abbrvauthor% %!makeyear%%!endlink%%!nextcitealt%]]} + # "...; NextAuthor et al., Year..." + !nextcitealp {%next%[[%!sep% %!makecitealp%]]} + + # + # ACTUAL STYLE DEFINITIONS + # + # (additions and modifications to default) + # + + # "Author (cf. Year),[ and] NextAuthor (Year, p. xx)" + citet %!makecitet%%!textafter%%!close% + # "(cf. Author et al., Year; NextAuthor et al., Year, p. xx)" + citep %!open%%!textbefore%%!makecitealp%%!textafter%%!close% + # "cf. Author et al., Year; NextAuthor et al., Year, p. xx" + citealp %!textbefore%%!makecitealp%%!textafter% + # "cf. Author Year; NextAuthor Year, p. xx" [NB: textbefore position differs from real natbib!] + citealt %!makecitealt%%!textafter% + # "Footnote: cf. Author A Year; Author B Year, p. xx." + footcite {%dialog%[[%_footnote%]][[%_foot%]]}: %!textbefore%%!makecitealp%%!textafter%. + # "Auto: (cf. Author A Year; Author B Year, p. xx)" + autocite {%dialog%[[%_autocite%]][[%_auto%]]}: %!open%%!textbefore%%!makecitealp%%!textafter%%!close% + + # Fallback style: "Author A (cf. Year),[ and] Author B (Year, p. xx)" + cite %!makecitet%%!textafter%%!close% +End + +CiteFormat numerical + # + # MACROS + # + # 1. Translatable bits (need to be marked by _ prefix) + # + _super Super + _superscript Superscript + + # + # 2. Macros re-used in the style definitions + # + !open [ + !sep , + !close ] + + # "Author [cf. ID..." + !makecitet %!abbrvauthor% %!open%%!textbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitet% + # "ID..." + !makecitealt {%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitealt% + # "ID..." + !hashkey {%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%%!nexthashkey%]]} + + # "...], [and] NextAuthor [ID..." + !nextcitet {%next%[[%!close%%!smartsep%%!abbrvauthor% %!open%%!textbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitet%]]} + # "..., ID..." + !nextcitealt {%next%[[%!sep% %!makecitealt%]]} + # FIXME: What is this? + !nexthashid {%next%[[%!sep% #ID%!nexthashid%]]} + # "..., NextID..." + !nexthashkey {%next%[[%!sep% %!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%%!nexthashkey%]]} + # "...); Nextauthor [ID..." + !nextcitet {%next%[[%!close%%!smartsep%%!abbrvauthor% %!open%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nextcitet%]]} + + # + # ACTUAL STYLE DEFINITIONS + # + # (additions and modifications to default) + # + + # "[cf. ID, NextID, p. xx]" + citep %!open%%!textbefore%%!hashkey%%!textafter%%!close% + # "Author [cf. ID],[ and] Nextauthor [NextID, p. xx]" + citet %!makecitet%%!textafter%%!close% + # "Footnote: cf. ID, NextID, p. xx." + footcite {%dialog%[[%_footnote%]][[%_foot%]]}: %!textbefore%%!makekey%%!textafter%. + # "Auto: (cf. Author A Year; Author B Year, p. xx)" + autocite {%dialog%[[%_autocite%]][[%_auto%]]}: %!open%%!textbefore%%!makekey%%!textafter%%!close% + # "Superscript: ID" (dialog) / "Super: ID" (button) + supercite {%dialog%[[%_superscript%]][[%_super%]]}: %!makekey% + + # Fallback style: "[cf. ID, NextID..., p. xx]" + cite %!open%%!textbefore%%!hashkey%%!textafter%%!close% +End diff --git a/lib/citeengines/biblatex.citeengine b/lib/citeengines/biblatex.citeengine new file mode 100644 index 0000000000..957fba0116 --- /dev/null +++ b/lib/citeengines/biblatex.citeengine @@ -0,0 +1,302 @@ +# \DeclareLyXCiteEngine[biblatex.sty]{Biblatex} +# DescriptionBegin +# Biblatex supports many author-year and numerical styles. It is mainly +# aimed at the Humanities. It is highly customizable, fully localized +# and provides many features that are not possible with BibTeX. +# The use of 'biber' as bibliography processor is advised. +# DescriptionEnd +# Excludes: basic | jurabib | natbib | biblatex-natbib + +# Author: Jürgen Spitzmüller + +Format 63 + +Requires biblatex + +# The framework (biblatex|bibtex) +CiteFramework biblatex + +# Cite style variants (default|authoryear|natbib) +# We provide both authoryear and numerical citations +CiteEngineType authoryear|numerical + +# Default style files for either engine type +DefaultBiblio authoryear:authoryear|numerical:numeric + +# Maximum number of names before "et al." chimes in +MaxCiteNames 3 + + +# The syntax of the cite command definitions below is: +# LyXName|alias*[][]=latexcmd +# +# * LyXName: The LyX name as output in the LyX file. For +# portability reasons, we try to use the same +# name for same-formatted commands in the +# different engines (thus many names stem from +# natbib). +# * Alias: A (comma-separated) list of commands that fall +# back to the given LyX name in the current engine. +# This is a bit like "ObsoletedBy" in the layouts. +# * latexcmd: The actual LaTeX command that is output. +# +# Alias and latexcmd are optional. If no latexcmd is given, the +# LyXName will be output to LaTeX. +# +# Note further: +# +# * Capitalization indicates that the command also has a capitalized +# form (\Latexcmd vs. \latexcmd). These usually enforce upcasing of +# name prefixes (von Goethe => Von Goethe). +# * Brackets [] indicate the number of optional arguments (0, 1, 2). +# * The star * indicates there is a starred version of the command +# (\latexcmd* vs. \latexcmd). By default, the starred version means: +# Expand the author list even if the maxnames setting would cause +# BibTeX/Biber to shorten it with "et al.". +# If the star has a different meaning for a command, it can be +# specified in angle brackets: . +# Maximal two translatable macro keywords, marked by the prefix '!_', +# can be given. The first points to the string that replaces the +# "Full aut&hor list" checkbox label in the Citation dialog, the +# second one an optional tooltip for this checkbox. Note that these +# two macros have to be defined in the CiteFormat section, dropping +# the '!' from the prefix (see below), e.g.: +# _stardesc Starred command label +# _stardesctooltip Tooltip for the starred command checkbox. + +# +# CITE COMMAND DEFINITIONS for either engine type +# +CiteEngine authoryear + Cite|citealt,citealp[][] + Citet[][]=textcite + Citep[][]=parencite + Citeauthor*[][] + citeyearpar[][]=parencite* + citeyear[][]=cite* + citebyear[][]=citeyear + Footcite[][]=smartcite + Autocite[][] + citetitle*[][] + fullcite[][] + footfullcite[][] + nocite +End + +CiteEngine numerical + cite|parencite,citep,citealt,citealp[][] + Citet[][]=textcite + supercite + Footcite[][]=smartcite + Autocite[][] + Citeauthor*[][] + citeyear|parencite*,citebyear[][]=citeyear* + citetitle*[][] + fullcite[][] + footfullcite[][] + nocite +End + + +# +# CITE FORMAT +# + +# The following defines how the commands are represented in the GUI +# (inset button and citation dialog) as well as in XHTML, docbook and +# plain text output. +# +# There are common definitions (default) and specific definitions for +# either cite engine type (which overwrite existing defaults. +# +CiteFormat default + # + # MACROS + # + # 1. Translatable bits (need to be marked by _ prefix) + # Note that preceding and trailing spaces matter. + # + _notcited not cited + _addtobib Add to bibliography only. + _footnote Footnote + _foot Foot + _fullcite bibliography entry + _bibentry Full bibliography entry. + _autocite Autocite + _auto Auto + # GUI strings for the starred commands + _citeauthorstar S&horten author list[[Possible substitute to All aut&hors]] + _citeauthorstartooltip Force a short author list (using et al.) + _citetitlestar F&orce full title[[Possible substitute to All aut&hors]] + _citetitlestartooltip Use full title even if shorttitle exists + # The following are handled by BiblioInfo + _etal et al. + _namesep , [[separate author names in citation, except for last name]] + _lastnamesep , and [[separate name of last author in citation]] + _pairnamesep and [[separate two authors in citation]] + + # + # 2. Macros re-used in the style definitions + # + # A link that lets us jump to the bibliography entry in LyXHTML + # %clean:key% will be substituted by the cite key to give a unique id + !startlink {!!} + !endlink {!!} + + # Add " , and " before the last item (but " and " if there are only two), else ", " + !smartsep {%second%[[{%next%[[%_namesep%]][[%_pairnamesep%]]}]][[{%next%[[%_namesep%]][[%_lastnamesep%]]}]]} + + # A dummy year modifier. This just indicates that a modifier might be output, + # to differentiate \cite* and \citeyear + !dummymod [a] + + # "...; Nextauthor ..." + !nextauthor {%next%[[%!sep% %!startlink%%!abbrvauthor%%!endlink%%!nextauthor%]]} + # Handle starred command: abbr. or full author list + !makenextauthor {%next%[[%!sep% %!startlink%%!makeauthor%%!endlink%%!makenextauthor%]]} + # "...; [NextID] ..." + !nextkey {%next%[[%!sep% %key%%!nextkey%]]} + # "...; Nextyear ..." (including extra label, as in 2017a) + !nextyear {%next%[[%!sep% %!startlink%%!year%%!endlink%%!nextyear%]]} + # "...; Nextyear ..." (including emulated extra label, as in 2017[a]) + !nextmyear {%next%[[%!sep% %!startlink%%!myear%%!endlink%%!nextmyear%]]} + # "...; Nextyear ..." (without any extra label) + !nextbyear {%next%[[%!sep% %!startlink%%!byear%%!endlink%%!nextbyear%]]} + # "...; Nexttitle ..." + !makenexttitle {%next%[[%!sep% %!startlink%%!maketitle%%!endlink%%!makenexttitle%]]} + # "...; NextKey..." + !nextfullcite {%next%[[%!sep% %bibentry%%!nextfullcite%]]} + + # "Author et al." (if > 3 authors) or "??" + !abbrvauthor {%abbrvauthor%[[%abbrvauthor%]][[??]]} + # "Author et al." (always) or "??" + !forceabbrvauthor {%forceabbrvauthor%[[%forceabbrvauthor%]][[??]]} + # Handle starred command: force of abbr. author list, independent of maxcitenames + !makeauthor {%ifstar%[[%!forceabbrvauthor%]][[%!abbrvauthor%]]} + # "prenote " + !textbefore {%textbefore%[[%textbefore% ]]} + # ", postnote" + !textafter {%textafter%[[, %textafter%]]} + # Add a year if it exists (else "??") and possibly a modifier (as in 2017a) + !year {%year%[[%year%]][[??]]}{%modifier%[[%modifier%]]} + # Add a year if it exists (else "??") and indicate a possible modifier (as in 2017[a]) + !myear {%year%[[%year%]][[??]]}{%modifier%[[%modifier%]][[{%export%[[]][[%!dummymod%]]}]]} + # Add a year if it exists (else "??") without any modifier at all + !byear {%year%[[%year%]][[??]]} + # Add a shorttitle or title if it exists (else "??") + !makeshorttitle {%shorttitle%[[%shorttitle%]][[{%title%[[%title%]][[??]]}]]} + # Add a title (or "??") + !maketitle {%ifstar%[[{%title%[[%title%]][[??]]}]][[%!makeshorttitle%]]} + # "cf. Key..." + !fullcite %!startlink%%bibentry%%!endlink%%!nextfullcite% + + # + # ACTUAL STYLE DEFINITIONS + # + # (identical in authoryear and numerical) + # + + # "cf. Author; Nextautor, p. xx" + citeauthor %!textbefore%%!startlink%%!makeauthor%%!endlink%%!makenextauthor%%!textafter% + # "cf. Year; Nextyear, p. xx" (including extra label, as in 2017a) + citeyear %!textbefore%%!startlink%%!myear%%!endlink%%!nextyear%%!textafter% + # "cf. Year; Nextyear, p. xx" (without any extra label) + citebyear %!textbefore%%!startlink%%!byear%%!endlink%%!nextbyear%%!textafter% + # "cf. Year; Nextyear, p. xx" (without any extra label) + citetitle %!textbefore%%!startlink%%!maketitle%%!endlink%%!makenexttitle%%!textafter% + # "Bibliography entry." (dialog) / "cf. Key; NextKey..., p. xx (bibliography entry)" (button) + fullcite {%dialog%[[%_bibentry%]][[%!textbefore%{%label%[[%!fullcite%]][[%key%%!nextkey% (%_fullcite%)]]}%!textafter%}]]} + # "Footnote: Full bibliography entry." (dialog) / "Foot: Key (bibliography entry)" + footfullcite {%dialog%[[%_footnote%]][[%_foot%]]}: {%dialog%[[%_bibentry%]][[{%label%[[%!fullcite%]][[%key%%!nextkey% (%_fullcite%)]]}]]} + # "Add to bibliography only." (dialog) / "[ID] (not cited)" (button) + nocite {%dialog%[[%_addtobib%]][[%key%%!nextkey% (%_notcited%)]]} +End + +CiteFormat authoryear + # + # MACROS + # + !open ( + !sep ; + !close ) + + # "cf. Author et. al Year..." + !makecite %!startlink%%!abbrvauthor% %!year%%!endlink%%!nextcite% + # Author et al. (cf. Year... + !maketextcite %!startlink%%!abbrvauthor%%!endlink% %!open%%!textbefore%%!year%%!nexttextcite% + + # "...; Nextauthor Year..." + !nextcite {%next%[[%!sep% %!makecite%]]} + # "...); Nextauthor (Year..." + !nexttextcite {%next%[[%!close%%!smartsep%%!startlink%%!abbrvauthor%%!endlink% %!open%%!year%%!nexttextcite%]]} + + # Add a year if it exists (else title, else "??") and possibly a modifier (as in 2017a) + !yeartitle {%year%[[%year%{%modifier%[[%modifier%]][[{%export%[[]][[%!dummymod%]]}]]}]][[{%title%[[%title%]][[??]]}]]} + # "...; Nextyear ..." (including extra label, as in 2017a) + !nextyeartitle {%next%[[%!sep% %!startlink%%!yeartitle%%!endlink%%!nextyeartitle%]]} + + # + # ACTUAL STYLE DEFINITIONS + # + # (additions and modifications to default) + # + + # "cf. Author A Year; Author B Year, p. xx" + cite %!textbefore%%!makecite%%!textafter% + # "cf. Author A (Year),[ and] Author B (Year), p. xx" + citet %!maketextcite%%!close%%!textafter% + # "(cf. Author A Year; Author B Year, p. xx)" + citep %!open%%!textbefore%%!makecite%%!textafter%%!close% + # This prints year or title, if year is missing + citeyear %!textbefore%%!startlink%%!yeartitle%%!endlink%%!nextyeartitle%%!textafter% + # "(cf. Year; Nextyear, p. xx)" + citeyearpar %!open%%!textbefore%%!startlink%%!myear%%!endlink%%!nextmyear%%!textafter%%!close% + # "Footnote: cf. Author A Year; Author B Year, p. xx." + footcite {%dialog%[[%_footnote%]][[%_foot%]]}: %!textbefore%%!makecite%%!textafter%. + # "Auto: (cf. Author A Year; Author B Year, p. xx)" + autocite {%dialog%[[%_autocite%]][[%_auto%]]}: %!open%%!textbefore%%!makecite%%!textafter%%!close% +End + +CiteFormat numerical + # + # MACROS + # + # 1. Translatable bits (need to be marked by _ prefix) + # + _super Super + _superscript Superscript + + # + # 2. Macros re-used in the style definitions + # + !open [ + !sep , + !close ] + + # "Author [cf. ID..." + !maketextcite %!abbrvauthor% %!open%%!textbefore%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nexttextcite% + # "ID" + !makekey {%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%%!nextkey%]]} + + # "...); Nextauthor [ID..." + !nexttextcite {%next%[[%!close%%!smartsep%%!abbrvauthor% %!open%{%dialog%[[#ID]][[%!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%]]}%!nexttextcite%]]} + # "..., NextID..." + !nextkey {%next%[[%!sep% %!startlink%{%numericallabel%[[%numericallabel%]][[#%key%]]}%!endlink%%!nextkey%]]} + + # + # ACTUAL STYLE DEFINITIONS + # + # (additions and modifications to default) + # + + # "[cf. ID, NextID, p. xx]" + cite %!open%%!textbefore%%!makekey%%!textafter%%!close% + # "Author [cf. ID],[ and] Nextauthor [NextID, p. xx]" + citet %!maketextcite%%!textafter%%!close% + # "Footnote: cf. ID, NextID, p. xx." + footcite {%dialog%[[%_footnote%]][[%_foot%]]}: %!textbefore%%!makekey%%!textafter%. + # "Auto: (cf. Author A Year; Author B Year, p. xx)" + autocite {%dialog%[[%_autocite%]][[%_auto%]]}: %!open%%!textbefore%%!makekey%%!textafter%%!close% + # "Superscript: ID" (dialog) / "Super: ID" (button) + supercite {%dialog%[[%_superscript%]][[%_super%]]}: %!makekey% +End diff --git a/lib/citeengines/jurabib.citeengine b/lib/citeengines/jurabib.citeengine index f092fa06e2..2d6cb0d232 100644 --- a/lib/citeengines/jurabib.citeengine +++ b/lib/citeengines/jurabib.citeengine @@ -4,7 +4,7 @@ # and the Humanities. It includes localizations for English, German, French, Dutch, # Spanish and Italian. # DescriptionEnd -# Excludes: basic | natbib | biblatex +# Excludes: basic | natbib | biblatex | biblatex-natbib # Author: Julien Rioux diff --git a/lib/citeengines/natbib.citeengine b/lib/citeengines/natbib.citeengine index f3a0385094..6a263022a5 100644 --- a/lib/citeengines/natbib.citeengine +++ b/lib/citeengines/natbib.citeengine @@ -5,7 +5,7 @@ # numerical citations, annotations, capitalization of the `van' part of # author names, shortened and full author lists, and more. # DescriptionEnd -# Excludes: basic | jurabib | biblatex +# Excludes: basic | jurabib | biblatex | biblatex-natbib # Author: Julien Rioux diff --git a/lib/lyx2lyx/lyx_2_3.py b/lib/lyx2lyx/lyx_2_3.py index 8d8e1c8c4e..114bfa6ce1 100644 --- a/lib/lyx2lyx/lyx_2_3.py +++ b/lib/lyx2lyx/lyx_2_3.py @@ -1172,6 +1172,203 @@ def revert_noprefix(document): i += 1 +def revert_biblatex(document): + " Revert biblatex support " + + # + # Header + # + + # 1. Get cite engine + engine = "basic" + i = find_token(document.header, "\\cite_engine", 0) + if i == -1: + document.warning("Malformed document! Missing \\cite_engine") + else: + engine = get_value(document.header, "\\cite_engine", i) + + # 2. Store biblatex state and revert to natbib + biblatex = False + if engine in ["biblatex", "biblatex-natbib"]: + biblatex = True + document.header[i] = "\cite_engine natbib" + + # 3. Store and remove new document headers + bibstyle = "" + i = find_token(document.header, "\\biblatex_bibstyle", 0) + if i != -1: + bibstyle = get_value(document.header, "\\biblatex_bibstyle", i) + del document.header[i] + + citestyle = "" + i = find_token(document.header, "\\biblatex_citestyle", 0) + if i != -1: + citestyle = get_value(document.header, "\\biblatex_citestyle", i) + del document.header[i] + + biblio_options = "" + i = find_token(document.header, "\\biblio_options", 0) + if i != -1: + biblio_options = get_value(document.header, "\\biblio_options", i) + del document.header[i] + + if biblatex: + bbxopts = "[natbib=true" + if bibstyle != "": + bbxopts += ",bibstyle=" + bibstyle + if citestyle != "": + bbxopts += ",citestyle=" + citestyle + if biblio_options != "": + bbxopts += "," + biblio_options + bbxopts += "]" + add_to_preamble(document, "\\usepackage" + bbxopts + "{biblatex}") + + # + # Body + # + + # 1. Bibtex insets + i = 0 + bibresources = [] + while (True): + i = find_token(document.body, "\\begin_inset CommandInset bibtex", i) + if i == -1: + break + j = find_end_of_inset(document.body, i) + if j == -1: + document.warning("Can't find end of bibtex inset at line %d!!" %(i)) + i += 1 + continue + bibs = get_quoted_value(document.body, "bibfiles", i, j) + opts = get_quoted_value(document.body, "biblatexopts", i, j) + # store resources + if bibs: + bibresources += bibs.split(",") + else: + document.warning("Can't find bibfiles for bibtex inset at line %d!" %(i)) + # remove biblatexopts line + k = find_token(document.body, "biblatexopts", i, j) + if k != -1: + del document.body[k] + # Re-find inset end line + j = find_end_of_inset(document.body, i) + # Insert ERT \\printbibliography and wrap bibtex inset to a Note + if biblatex: + pcmd = "printbibliography" + if opts: + pcmd += "[" + opts + "]" + repl = ["\\begin_inset ERT", "status open", "", "\\begin_layout Plain Layout",\ + "", "", "\\backslash", pcmd, "\\end_layout", "", "\\end_inset", "", "",\ + "\\end_layout", "", "\\begin_layout Standard", "\\begin_inset Note Note",\ + "status open", "", "\\begin_layout Plain Layout" ] + repl += document.body[i:j+1] + repl += ["", "\\end_layout", "", "\\end_inset", "", ""] + document.body[i:j+1] = repl + j += 27 + + i = j + 1 + + if biblatex: + for b in bibresources: + add_to_preamble(document, "\\addbibresource{" + b + ".bib}") + + # 2. Citation insets + + # Specific citation insets used in biblatex that need to be reverted to ERT + new_citations = { + "Cite" : "Cite", + "citebyear" : "citeyear", + "citeyear" : "cite*", + "Footcite" : "Smartcite", + "footcite" : "smartcite", + "Autocite" : "Autocite", + "autocite" : "autocite", + "citetitle" : "citetitle", + "citetitle*" : "citetitle*", + "fullcite" : "fullcite", + "footfullcite" : "footfullcite", + "supercite" : "supercite", + "citeauthor" : "citeauthor", + "citeauthor*" : "citeauthor*", + "Citeauthor" : "Citeauthor", + "Citeauthor*" : "Citeauthor*" + } + + # All commands accepted by LyX < 2.3. Everything else throws an error. + old_citations = [ "cite", "nocite", "citet", "citep", "citealt", "citealp",\ + "citeauthor", "citeyear", "citeyearpar", "citet*", "citep*",\ + "citealt*", "citealp*", "citeauthor*", "Citet", "Citep",\ + "Citealt", "Citealp", "Citeauthor", "Citet*", "Citep*",\ + "Citealt*", "Citealp*", "Citeauthor*", "fullcite", "footcite",\ + "footcitet", "footcitep", "footcitealt", "footcitealp",\ + "footciteauthor", "footciteyear", "footciteyearpar",\ + "citefield", "citetitle", "cite*" ] + + i = 0 + while (True): + i = find_token(document.body, "\\begin_inset CommandInset citation", i) + if i == -1: + break + j = find_end_of_inset(document.body, i) + if j == -1: + document.warning("Can't find end of citation inset at line %d!!" %(i)) + i += 1 + continue + k = find_token(document.body, "LatexCommand", i, j) + if k == -1: + document.warning("Can't find LatexCommand for citation inset at line %d!" %(i)) + i = j + 1 + continue + cmd = get_value(document.body, "LatexCommand", k) + if biblatex and cmd in list(new_citations.keys()): + pre = get_quoted_value(document.body, "before", i, j) + post = get_quoted_value(document.body, "after", i, j) + key = get_quoted_value(document.body, "key", i, j) + if not key: + document.warning("Citation inset at line %d does not have a key!" %(i)) + key = "???" + # Replace known new commands with ERT + res = "\\" + new_citations[cmd] + if pre: + res += "[" + pre + "]" + elif post: + res += "[]" + if post: + res += "[" + post + "]" + res += "{" + key + "}" + document.body[i:j+1] = put_cmd_in_ert([res]) + elif cmd not in old_citations: + # Reset unknown commands to cite. This is what LyX does as well + # (but LyX 2.2 would break on unknown commands) + document.body[k] = "LatexCommand cite" + document.warning("Reset unknown cite command '%s' with cite" % cmd) + i = j + 1 + + # Emulate the old biblatex-workaround (pretend natbib in order to use the styles) + if biblatex: + i = find_token(document.header, "\\begin_local_layout", 0) + if i == -1: + k = find_token(document.header, "\\language", 0) + if k == -1: + # this should not happen + document.warning("Malformed LyX document! No \\language header found!") + return + document.header[k-1 : k-1] = ["\\begin_local_layout", "\\end_local_layout"] + i = k-1 + + j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout") + if j == -1: + # this should not happen + document.warning("Malformed LyX document! Can't find end of local layout!") + return + + document.header[i+1 : i+1] = [ + "### Inserted by lyx2lyx (biblatex emulation) ###", + "Provides natbib 1", + "### End of insertion by lyx2lyx (biblatex emulation) ###" + ] + + ## # Conversion hub # @@ -1196,10 +1393,12 @@ convert = [ [524, []], [525, []], [526, []], - [527, []] + [527, []], + [528, []] ] revert = [ + [527, [revert_biblatex]], [526, [revert_noprefix]], [525, [revert_plural_refs]], [524, [revert_labelonly]], diff --git a/src/Buffer.cpp b/src/Buffer.cpp index d8d93b0afd..0d773918da 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -1875,7 +1875,15 @@ void Buffer::writeLaTeXSource(otexstream & os, // Write the preamble runparams.use_babel = params().writeLaTeX(os, features, d->filename.onlyPath()); - + + // Biblatex bibliographies are loaded here + if (params().useBiblatex()) { + vector const bibfiles = + prepareBibFilePaths(runparams, getBibfilesCache(), true); + for (docstring const & file: bibfiles) + os << "\\addbibresource{" << file << "}\n"; + } + if (!runparams.dryrun && features.hasPolyglossiaExclusiveLanguages() && !features.hasOnlyPolyglossiaLanguages()) { docstring blangs; @@ -3104,6 +3112,114 @@ DocFileName Buffer::getReferencedFileName(string const & fn) const } +string const Buffer::prepareFileNameForLaTeX(string const & name, + string const & ext, bool nice) const +{ + string const fname = makeAbsPath(name, filePath()).absFileName(); + if (FileName::isAbsolute(name) || !FileName(fname + ext).isReadableFile()) + return name; + if (!nice) + return fname; + + // FIXME UNICODE + return to_utf8(makeRelPath(from_utf8(fname), + from_utf8(masterBuffer()->filePath()))); +} + + +vector const Buffer::prepareBibFilePaths(OutputParams const & runparams, + FileNamePairList const bibfilelist, + bool const add_extension) const +{ + // If we are processing the LaTeX file in a temp directory then + // copy the .bib databases to this temp directory, mangling their + // names in the process. Store this mangled name in the list of + // all databases. + // (We need to do all this because BibTeX *really*, *really* + // can't handle "files with spaces" and Windows users tend to + // use such filenames.) + // Otherwise, store the (maybe absolute) path to the original, + // unmangled database name. + + vector res; + + // determine the export format + string const tex_format = flavor2format(runparams.flavor); + + // check for spaces in paths + bool found_space = false; + + FileNamePairList::const_iterator it = bibfilelist.begin(); + FileNamePairList::const_iterator en = bibfilelist.end(); + for (; it != en; ++it) { + string utf8input = to_utf8(it->first); + string database = + prepareFileNameForLaTeX(utf8input, ".bib", runparams.nice); + FileName const try_in_file = + makeAbsPath(database + ".bib", filePath()); + bool const not_from_texmf = try_in_file.isReadableFile(); + + if (!runparams.inComment && !runparams.dryrun && !runparams.nice && + not_from_texmf) { + // mangledFileName() needs the extension + DocFileName const in_file = DocFileName(try_in_file); + database = removeExtension(in_file.mangledFileName()); + FileName const out_file = makeAbsPath(database + ".bib", + masterBuffer()->temppath()); + bool const success = in_file.copyTo(out_file); + if (!success) { + LYXERR0("Failed to copy '" << in_file + << "' to '" << out_file << "'"); + } + } else if (!runparams.inComment && runparams.nice && not_from_texmf) { + runparams.exportdata->addExternalFile(tex_format, try_in_file, database + ".bib"); + if (!isValidLaTeXFileName(database)) { + frontend::Alert::warning(_("Invalid filename"), + _("The following filename will cause troubles " + "when running the exported file through LaTeX: ") + + from_utf8(database)); + } + if (!isValidDVIFileName(database)) { + frontend::Alert::warning(_("Problematic filename for DVI"), + _("The following filename can cause troubles " + "when running the exported file through LaTeX " + "and opening the resulting DVI: ") + + from_utf8(database), true); + } + } + + if (add_extension) + database += ".bib"; + + // FIXME UNICODE + docstring const path = from_utf8(latex_path(database)); + + if (contains(path, ' ')) + found_space = true; + + if (find(res.begin(), res.end(), path) == res.end()) + res.push_back(path); + } + + // Check if there are spaces in the path and warn BibTeX users, if so. + // (biber can cope with such paths) + if (!prefixIs(runparams.bibtex_command, "biber")) { + // Post this warning only once. + static bool warned_about_spaces = false; + if (!warned_about_spaces && + runparams.nice && found_space) { + warned_about_spaces = true; + Alert::warning(_("Export Warning!"), + _("There are spaces in the paths to your BibTeX databases.\n" + "BibTeX will be unable to find them.")); + } + } + + return res; +} + + + string Buffer::layoutPos() const { return d->layout_position; diff --git a/src/Buffer.h b/src/Buffer.h index 999b7cbf73..04539647c9 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -417,6 +417,18 @@ public: */ support::DocFileName getReferencedFileName(std::string const & fn) const; + /// Format a file name for LaTeX output (absolute or relative or filename only, + /// depending on file and context) + std::string const prepareFileNameForLaTeX(std::string const &, + std::string const &, bool nice) const; + + /** Returns a vector of bibliography (*.bib) file paths suitable for the + * output in the respective BibTeX/Biblatex macro + */ + std::vector const prepareBibFilePaths(OutputParams const &, + support::FileNamePairList const bibfilelist, + bool const extension = true) const; + /** Returns the path where a local layout file lives. * An empty string is returned for standard system and user layouts. * If possible, it is always relative to the buffer path. diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index e96067a985..f6e7f50fd0 100644 --- a/src/BufferParams.cpp +++ b/src/BufferParams.cpp @@ -847,6 +847,15 @@ string BufferParams::readToken(Lexer & lex, string const & token, } else if (token == "\\biblio_style") { lex.eatLine(); biblio_style = lex.getString(); + } else if (token == "\\biblio_options") { + lex.eatLine(); + biblio_opts = lex.getString(); + } else if (token == "\\biblatex_bibstyle") { + lex.eatLine(); + biblatex_bibstyle = lex.getString(); + } else if (token == "\\biblatex_citestyle") { + lex.eatLine(); + biblatex_citestyle = lex.getString(); } else if (token == "\\use_bibtopic") { lex >> use_bibtopic; } else if (token == "\\use_indices") { @@ -1214,9 +1223,18 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const os << "basic"; } - os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_) - << "\n\\biblio_style " << biblio_style - << "\n\\use_bibtopic " << convert(use_bibtopic) + os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_); + + if (!biblio_style.empty()) + os << "\n\\biblio_style " << biblio_style; + if (!biblio_opts.empty()) + os << "\n\\biblio_options " << biblio_opts; + if (!biblatex_bibstyle.empty()) + os << "\n\\biblatex_bibstyle " << biblatex_bibstyle; + if (!biblatex_citestyle.empty()) + os << "\n\\biblatex_citestyle " << biblatex_citestyle; + + os << "\n\\use_bibtopic " << convert(use_bibtopic) << "\n\\use_indices " << convert(use_indices) << "\n\\paperorientation " << string_orientation[orientation] << "\n\\suppress_date " << convert(suppress_date) @@ -2165,7 +2183,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, && useNonTeXFonts) os << "\\usepackage{xunicode}\n"; - // Polyglossia must be loaded last + // Polyglossia must be loaded last ... if (use_polyglossia) { // call the package os << "\\usepackage{polyglossia}\n"; @@ -2189,6 +2207,42 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, } } + // ... but before biblatex (see #7065) + if (features.mustProvide("biblatex")) { + string delim = ""; + string opts; + os << "\\usepackage"; + if (!biblatex_bibstyle.empty() + && (biblatex_bibstyle == biblatex_citestyle)) { + opts = "style=" + biblatex_bibstyle; + delim = ","; + } else { + if (!biblatex_bibstyle.empty()) { + opts = "bibstyle=" + biblatex_bibstyle; + delim = ","; + } + if (!biblatex_citestyle.empty()) { + opts += delim + "citestyle=" + biblatex_citestyle; + delim = ","; + } + } + if (bibtexCommand() == "bibtex8" + || prefixIs(bibtexCommand(), "bibtex8 ")) { + opts += delim + "backend=bibtex8"; + delim = ","; + } else if (bibtexCommand() == "bibtex" + || prefixIs(bibtexCommand(), "bibtex ")) { + opts += delim + "backend=bibtex"; + delim = ","; + } + if (!biblio_opts.empty()) + opts += delim + biblio_opts; + if (!opts.empty()) + os << "[" << opts << "]"; + os << "{biblatex}\n"; + } + + // Load custom language package here if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) { if (lang_package == "default") @@ -3312,6 +3366,13 @@ string const & BufferParams::bibtexCommand() const } +bool BufferParams::useBiblatex() const +{ + return theCiteEnginesList[citeEngine().list().front()] + ->getCiteFramework() == "biblatex"; +} + + void BufferParams::invalidateConverterCache() const { pimpl_->isExportCacheValid = false; diff --git a/src/BufferParams.h b/src/BufferParams.h index 30b65e0619..1c64f3a341 100644 --- a/src/BufferParams.h +++ b/src/BufferParams.h @@ -465,6 +465,9 @@ public: /// Return the actual bibtex command (lyxrc or buffer param) std::string const & bibtexCommand() const; + /// Are we using biblatex? + bool useBiblatex() const; + /// Set the default BibTeX style file for the document void setDefaultBiblioStyle(std::string const & s){ biblio_style = s; } /// Get the default BibTeX style file from the TextClass @@ -474,6 +477,13 @@ public: /// Check if a citation style is an alias to another style std::string getCiteAlias(std::string const & s) const; + /// Options of the bibiography package + std::string biblio_opts; + /// The biblatex bibliography style + std::string biblatex_bibstyle; + /// The biblatex citation style + std::string biblatex_citestyle; + /// options for pdf output PDFOptions & pdfoptions(); PDFOptions const & pdfoptions() const; diff --git a/src/frontends/qt4/GuiBibtex.cpp b/src/frontends/qt4/GuiBibtex.cpp index 8c35ced050..1be20bc4b1 100644 --- a/src/frontends/qt4/GuiBibtex.cpp +++ b/src/frontends/qt4/GuiBibtex.cpp @@ -17,6 +17,7 @@ #include "Buffer.h" #include "BufferParams.h" +#include "CiteEnginesList.h" #include "FuncRequest.h" #include "LyXRC.h" #include "qt_helpers.h" @@ -81,6 +82,8 @@ GuiBibtex::GuiBibtex(GuiView & lv) this, SLOT(addPressed())); connect(rescanPB, SIGNAL(clicked()), this, SLOT(rescanClicked())); + connect(biblatexOptsLE, SIGNAL(textChanged(QString)), + this, SLOT(change_adaptor())); add_ = new GuiBibtexAddDialog(this); add_bc_.setPolicy(ButtonPolicy::OkCancelPolicy); @@ -295,6 +298,7 @@ void GuiBibtex::availableChanged() void GuiBibtex::updateContents() { bool bibtopic = usingBibtopic(); + bool biblatex = usingBiblatex(); databaseLW->clear(); @@ -337,27 +341,40 @@ void GuiBibtex::updateContents() btPrintCO->setCurrentIndex(btp); - styleCB->clear(); + // Only useful for biblatex + biblatexOptsLA->setVisible(biblatex); + biblatexOptsLE->setVisible(biblatex); - int item_nr = -1; + // only useful for BibTeX + styleCB->setVisible(!biblatex); + styleLA->setVisible(!biblatex); + stylePB->setVisible(!biblatex); - QStringList const str = bibStyles(); - for (int i = 0; i != str.count(); ++i) { - QString item = changeExtension(str[i], ""); - if (item == bibstyle) - item_nr = i; - styleCB->addItem(item); - } + if (!biblatex) { + styleCB->clear(); - if (item_nr == -1 && !bibstyle.isEmpty()) { - styleCB->addItem(bibstyle); - item_nr = styleCB->count() - 1; - } + int item_nr = -1; - if (item_nr != -1) - styleCB->setCurrentIndex(item_nr); - else - styleCB->clearEditText(); + QStringList const str = bibStyles(); + for (int i = 0; i != str.count(); ++i) { + QString item = changeExtension(str[i], ""); + if (item == bibstyle) + item_nr = i; + styleCB->addItem(item); + } + + if (item_nr == -1 && !bibstyle.isEmpty()) { + styleCB->addItem(bibstyle); + item_nr = styleCB->count() - 1; + } + + + if (item_nr != -1) + styleCB->setCurrentIndex(item_nr); + else + styleCB->clearEditText(); + } else + biblatexOptsLE->setText(toqstr(params_["biblatexopts"])); } @@ -392,6 +409,8 @@ void GuiBibtex::applyView() params_["options"] = bibstyle; } + params_["biblatexopts"] = qstring_to_ucs4(biblatexOptsLE->text()); + int btp = btPrintCO->currentIndex(); if (usingBibtopic()) { @@ -484,7 +503,10 @@ QStringList GuiBibtex::bibFiles() const void GuiBibtex::rescanBibStyles() const { - rescanTexStyles("bst bib"); + if (usingBiblatex()) + rescanTexStyles("bib"); + else + rescanTexStyles("bst bib"); } @@ -500,6 +522,12 @@ bool GuiBibtex::bibtotoc() const } +bool GuiBibtex::usingBiblatex() const +{ + return buffer().params().useBiblatex(); +} + + QString GuiBibtex::styleFile() const { // the different bibtex packages have (and need) their diff --git a/src/frontends/qt4/GuiBibtex.h b/src/frontends/qt4/GuiBibtex.h index 3ce3ada32d..2ffdbe6705 100644 --- a/src/frontends/qt4/GuiBibtex.h +++ b/src/frontends/qt4/GuiBibtex.h @@ -79,6 +79,8 @@ private: bool usingBibtopic() const; /// should we put the bibliography to the TOC? bool bibtotoc() const; + /// do we use biblatex? + bool usingBiblatex() const; /// which stylefile do we use? QString styleFile() const; diff --git a/src/frontends/qt4/GuiDocument.cpp b/src/frontends/qt4/GuiDocument.cpp index c532a32b69..f7f00795ab 100644 --- a/src/frontends/qt4/GuiDocument.cpp +++ b/src/frontends/qt4/GuiDocument.cpp @@ -1130,16 +1130,32 @@ GuiDocument::GuiDocument(GuiView & lv) this, SLOT(bibtexChanged(int))); connect(biblioModule->bibtexOptionsLE, SIGNAL(textChanged(QString)), this, SLOT(biblioChanged())); + connect(biblioModule->citePackageOptionsLE, SIGNAL(textChanged(QString)), + this, SLOT(biblioChanged())); connect(biblioModule->defaultBiblioCO, SIGNAL(activated(int)), this, SLOT(biblioChanged())); connect(biblioModule->defaultBiblioCO, SIGNAL(editTextChanged(QString)), this, SLOT(biblioChanged())); connect(biblioModule->defaultBiblioCO, SIGNAL(editTextChanged(QString)), this, SLOT(updateResetDefaultBiblio())); + connect(biblioModule->biblatexBbxCO, SIGNAL(activated(int)), + this, SLOT(biblioChanged())); + connect(biblioModule->biblatexBbxCO, SIGNAL(editTextChanged(QString)), + this, SLOT(updateResetDefaultBiblio())); + connect(biblioModule->biblatexCbxCO, SIGNAL(activated(int)), + this, SLOT(biblioChanged())); + connect(biblioModule->biblatexCbxCO, SIGNAL(editTextChanged(QString)), + this, SLOT(updateResetDefaultBiblio())); connect(biblioModule->rescanBibliosPB, SIGNAL(clicked()), this, SLOT(rescanBibFiles())); connect(biblioModule->resetDefaultBiblioPB, SIGNAL(clicked()), this, SLOT(resetDefaultBibfile())); + connect(biblioModule->resetCbxPB, SIGNAL(clicked()), + this, SLOT(resetDefaultCbxBibfile())); + connect(biblioModule->resetBbxPB, SIGNAL(clicked()), + this, SLOT(resetDefaultBbxBibfile())); + connect(biblioModule->matchBbxPB, SIGNAL(clicked()), + this, SLOT(matchBiblatexStyles())); biblioModule->citeEngineCO->clear(); for (LyXCiteEngine const & cet : theCiteEnginesList) { @@ -2303,11 +2319,14 @@ void GuiDocument::biblioChanged() void GuiDocument::rescanBibFiles() { - rescanTexStyles("bst"); + if (isBiblatex()) + rescanTexStyles("bbx cbx"); + else + rescanTexStyles("bst"); } -void GuiDocument::resetDefaultBibfile() +void GuiDocument::resetDefaultBibfile(string const & which) { QString const engine = biblioModule->citeEngineCO->itemData( @@ -2317,7 +2336,19 @@ void GuiDocument::resetDefaultBibfile() CiteEngineType(biblioModule->citeStyleCO->itemData( biblioModule->citeStyleCO->currentIndex()).toInt()); - updateDefaultBiblio(theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet)); + updateDefaultBiblio(theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet), which); +} + + +void GuiDocument::resetDefaultBbxBibfile() +{ + resetDefaultBibfile("bbx"); +} + + +void GuiDocument::resetDefaultCbxBibfile() +{ + resetDefaultBibfile("cbx"); } @@ -2330,19 +2361,44 @@ void GuiDocument::citeEngineChanged(int n) theCiteEnginesList[fromqstr(engine)]->getEngineType(); updateCiteStyles(engs); + updateEngineDependends(); resetDefaultBibfile(); - biblioChanged(); } +void GuiDocument::updateEngineDependends() +{ + bool const biblatex = isBiblatex(); + + // These are only useful with BibTeX + biblioModule->defaultBiblioCO->setEnabled(!biblatex); + biblioModule->bibtexStyleLA->setEnabled(!biblatex); + biblioModule->resetDefaultBiblioPB->setEnabled(!biblatex); + biblioModule->bibtopicCB->setEnabled(!biblatex); + + // These are only useful with Biblatex + biblioModule->citePackageOptionsLE->setEnabled(biblatex); + biblioModule->citePackageOptionsL->setEnabled(biblatex); + biblioModule->biblatexBbxCO->setEnabled(biblatex); + biblioModule->biblatexBbxLA->setEnabled(biblatex); + biblioModule->biblatexCbxCO->setEnabled(biblatex); + biblioModule->biblatexCbxLA->setEnabled(biblatex); + biblioModule->resetBbxPB->setEnabled(biblatex); + biblioModule->resetCbxPB->setEnabled(biblatex); + biblioModule->matchBbxPB->setEnabled(biblatex); +} + + void GuiDocument::citeStyleChanged() { QString const engine = biblioModule->citeEngineCO->itemData( biblioModule->citeEngineCO->currentIndex()).toString(); - if (theCiteEnginesList[fromqstr(engine)]->isDefaultBiblio( - fromqstr(biblioModule->defaultBiblioCO->currentText()))) + QString const currentDef = isBiblatex() ? + biblioModule->biblatexBbxCO->currentText() + : biblioModule->defaultBiblioCO->currentText(); + if (theCiteEnginesList[fromqstr(engine)]->isDefaultBiblio(fromqstr(currentDef))) resetDefaultBibfile(); biblioChanged(); @@ -2666,6 +2722,10 @@ void GuiDocument::applyView() bp_.setDefaultBiblioStyle(fromqstr(biblioModule->defaultBiblioCO->currentText())); + bp_.biblatex_bibstyle = fromqstr(biblioModule->biblatexBbxCO->currentText()); + bp_.biblatex_citestyle = fromqstr(biblioModule->biblatexCbxCO->currentText()); + bp_.biblio_opts = fromqstr(biblioModule->citePackageOptionsLE->text()); + string const bibtex_command = fromqstr(biblioModule->bibtexCO->itemData( biblioModule->bibtexCO->currentIndex()).toString()); @@ -3087,7 +3147,15 @@ void GuiDocument::paramsToDialog() biblioModule->bibtopicCB->setChecked( bp_.use_bibtopic); - updateDefaultBiblio(bp_.defaultBiblioStyle()); + updateEngineDependends(); + + if (isBiblatex()) { + updateDefaultBiblio(bp_.biblatex_bibstyle, "bbx"); + updateDefaultBiblio(bp_.biblatex_citestyle, "cbx"); + } else + updateDefaultBiblio(bp_.defaultBiblioStyle()); + + biblioModule->citePackageOptionsLE->setText(toqstr(bp_.biblio_opts)); string command; string options = @@ -3675,40 +3743,117 @@ void GuiDocument::updateIncludeonlys() } -void GuiDocument::updateDefaultBiblio(string const & style) +bool GuiDocument::isBiblatex() const +{ + QString const engine = + biblioModule->citeEngineCO->itemData( + biblioModule->citeEngineCO->currentIndex()).toString(); + + return theCiteEnginesList[fromqstr(engine)]->getCiteFramework() == "biblatex"; +} + + +void GuiDocument::updateDefaultBiblio(string const & style, + string const & which) { QString const bibstyle = toqstr(style); biblioModule->defaultBiblioCO->clear(); + biblioModule->biblatexBbxCO->clear(); + biblioModule->biblatexCbxCO->clear(); int item_nr = -1; - QStringList str = texFileList("bstFiles.lst"); - // test whether we have a valid list, otherwise run rescan - if (str.isEmpty()) { - rescanTexStyles("bst"); - str = texFileList("bstFiles.lst"); - } - for (int i = 0; i != str.size(); ++i) - str[i] = onlyFileName(str[i]); - // sort on filename only (no path) - str.sort(); - - for (int i = 0; i != str.count(); ++i) { - QString item = changeExtension(str[i], ""); - if (item == bibstyle) - item_nr = i; - biblioModule->defaultBiblioCO->addItem(item); - } + if (isBiblatex()) { + if (which != "cbx") { + // First the bbx styles + QStringList str = texFileList("bbxFiles.lst"); + // test whether we have a valid list, otherwise run rescan + if (str.isEmpty()) { + rescanTexStyles("bbx"); + str = texFileList("bbxFiles.lst"); + } + for (int i = 0; i != str.size(); ++i) + str[i] = onlyFileName(str[i]); + // sort on filename only (no path) + str.sort(); + + for (int i = 0; i != str.count(); ++i) { + QString item = changeExtension(str[i], ""); + if (item == bibstyle) + item_nr = i; + biblioModule->biblatexBbxCO->addItem(item); + } - if (item_nr == -1 && !bibstyle.isEmpty()) { - biblioModule->defaultBiblioCO->addItem(bibstyle); - item_nr = biblioModule->defaultBiblioCO->count() - 1; - } + if (item_nr == -1 && !bibstyle.isEmpty()) { + biblioModule->biblatexBbxCO->addItem(bibstyle); + item_nr = biblioModule->biblatexBbxCO->count() - 1; + } - if (item_nr != -1) - biblioModule->defaultBiblioCO->setCurrentIndex(item_nr); - else - biblioModule->defaultBiblioCO->clearEditText(); + if (item_nr != -1) + biblioModule->biblatexBbxCO->setCurrentIndex(item_nr); + else + biblioModule->biblatexBbxCO->clearEditText(); + } + + if (which != "bbx") { + // now the cbx styles + QStringList str = texFileList("cbxFiles.lst"); + // test whether we have a valid list, otherwise run rescan + if (str.isEmpty()) { + rescanTexStyles("cbx"); + str = texFileList("cbxFiles.lst"); + } + for (int i = 0; i != str.size(); ++i) + str[i] = onlyFileName(str[i]); + // sort on filename only (no path) + str.sort(); + + for (int i = 0; i != str.count(); ++i) { + QString item = changeExtension(str[i], ""); + if (item == bibstyle) + item_nr = i; + biblioModule->biblatexCbxCO->addItem(item); + } + + if (item_nr == -1 && !bibstyle.isEmpty()) { + biblioModule->biblatexCbxCO->addItem(bibstyle); + item_nr = biblioModule->biblatexCbxCO->count() - 1; + } + + if (item_nr != -1) + biblioModule->biblatexCbxCO->setCurrentIndex(item_nr); + else + biblioModule->biblatexCbxCO->clearEditText(); + } + } else {// BibTeX + QStringList str = texFileList("bstFiles.lst"); + // test whether we have a valid list, otherwise run rescan + if (str.isEmpty()) { + rescanTexStyles("bst"); + str = texFileList("bstFiles.lst"); + } + for (int i = 0; i != str.size(); ++i) + str[i] = onlyFileName(str[i]); + // sort on filename only (no path) + str.sort(); + + for (int i = 0; i != str.count(); ++i) { + QString item = changeExtension(str[i], ""); + if (item == bibstyle) + item_nr = i; + biblioModule->defaultBiblioCO->addItem(item); + } + + if (item_nr == -1 && !bibstyle.isEmpty()) { + biblioModule->defaultBiblioCO->addItem(bibstyle); + item_nr = biblioModule->defaultBiblioCO->count() - 1; + } + + if (item_nr != -1) + biblioModule->defaultBiblioCO->setCurrentIndex(item_nr); + else + biblioModule->defaultBiblioCO->clearEditText(); + } updateResetDefaultBiblio(); } @@ -3722,9 +3867,25 @@ void GuiDocument::updateResetDefaultBiblio() CiteEngineType const cet = CiteEngineType(biblioModule->citeStyleCO->itemData( biblioModule->citeStyleCO->currentIndex()).toInt()); - biblioModule->resetDefaultBiblioPB->setEnabled( - theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet) - != fromqstr(biblioModule->defaultBiblioCO->currentText())); + + string const defbib = theCiteEnginesList[fromqstr(engine)]->getDefaultBiblio(cet); + if (isBiblatex()) { + QString const bbx = biblioModule->biblatexBbxCO->currentText(); + QString const cbx = biblioModule->biblatexCbxCO->currentText(); + biblioModule->resetCbxPB->setEnabled(defbib != fromqstr(cbx)); + biblioModule->resetBbxPB->setEnabled(defbib != fromqstr(bbx)); + biblioModule->matchBbxPB->setEnabled(bbx != cbx && !cbx.isEmpty() + && biblioModule->biblatexBbxCO->findText(cbx) != -1); + } else + biblioModule->resetDefaultBiblioPB->setEnabled( + defbib != fromqstr(biblioModule->defaultBiblioCO->currentText())); +} + + +void GuiDocument::matchBiblatexStyles() +{ + updateDefaultBiblio(fromqstr(biblioModule->biblatexCbxCO->currentText()), "bbx"); + biblioChanged(); } diff --git a/src/frontends/qt4/GuiDocument.h b/src/frontends/qt4/GuiDocument.h index 32ebb57d5e..593a67a3d7 100644 --- a/src/frontends/qt4/GuiDocument.h +++ b/src/frontends/qt4/GuiDocument.h @@ -116,11 +116,15 @@ private Q_SLOTS: void languagePackageChanged(int); void biblioChanged(); void rescanBibFiles(); - void resetDefaultBibfile(); + void resetDefaultBibfile(std::string const & which = std::string()); + void resetDefaultBbxBibfile(); + void resetDefaultCbxBibfile(); void citeEngineChanged(int); void citeStyleChanged(); void bibtexChanged(int); void updateResetDefaultBiblio(); + void matchBiblatexStyles(); + void updateEngineDependends(); void updateModuleInfo(); void modulesChanged(); void changeBackgroundColor(); @@ -184,7 +188,8 @@ private: /// void updateIncludeonlys(); /// - void updateDefaultBiblio(std::string const & style); + void updateDefaultBiblio(std::string const & style, + std::string const & which = std::string()); /// save as default template void saveDocDefault(); /// reset to default params @@ -281,6 +286,8 @@ private: /// void allPackages(int); /// + bool isBiblatex() const; + /// BufferParams bp_; /// List of names of available modules std::list moduleNames_; diff --git a/src/frontends/qt4/ui/BiblioUi.ui b/src/frontends/qt4/ui/BiblioUi.ui index b6ce417432..78f50b1aa7 100644 --- a/src/frontends/qt4/ui/BiblioUi.ui +++ b/src/frontends/qt4/ui/BiblioUi.ui @@ -6,16 +6,22 @@ 0 0 - 475 - 394 + 534 + 481 - + + + + 0 + 0 + + Citation Style @@ -104,30 +110,155 @@ + + + + + + Opt&ions: + + + citePackageOptionsLE + + + + + + + + 0 + 0 + + + + Here you can enter further options of the biblatex package + + + + + + + + + + + + 0 + 0 + + + + + + + &Biblatex citation style: + + + biblatexCbxCO + + + + + + + The style that determines the layout of the citations + + + true + + + + + + + + 0 + 0 + + + + Reset to the preset default + + + Rese&t + + + + + + + + 0 + 0 + + Bibliography Style true - - - - - Select this if you want to split your bibliography into sections - - - S&ectioned bibliography - - - + - + + + + + + + + Biblate&x bibliography style: + + + biblatexBbxCO + + + + + + + + 0 + 0 + + + + The style that determines the layout of the biblatex-generated bibliography + + + true + + + + + + + Reset to the preset default + + + R&eset + + + + + + + Match biblatex bibliography with citation style + + + &Match + + + + + + + @@ -140,6 +271,12 @@ + + + 0 + 0 + + Here, you can define a BibTeX style that is suggested in the BibTeX dialog by default @@ -149,45 +286,65 @@ - + - Rescan style files + Reset to the preset default - Re&scan + &Reset + + + + - + - Reset to the preset default + Select this if you want to split your bibliography into sections - &Reset + Secti&oned bibliography + + + + + + + Qt::Horizontal + + + + 189 + 20 + + + + + + + + Rescan style files + + + Re&scan - - - - Qt::Horizontal - - - - 40 - 20 - - - - + + + 0 + 0 + + Here you can define an alternative program to or specific options of BibTeX. @@ -219,7 +376,7 @@ - + Qt::Horizontal @@ -232,7 +389,7 @@ - + @@ -246,6 +403,12 @@ + + + 0 + 0 + + Define options such as --min-crossrefs (see the documentation of BibTeX) diff --git a/src/frontends/qt4/ui/BibtexUi.ui b/src/frontends/qt4/ui/BibtexUi.ui index b99ddacf37..f72ba6ce29 100644 --- a/src/frontends/qt4/ui/BibtexUi.ui +++ b/src/frontends/qt4/ui/BibtexUi.ui @@ -1,65 +1,96 @@ - + + BibtexUi - - + + 0 0 - 352 - 334 + 361 + 397 - + - + true - - - 9 - - - 6 - - - - - Qt::Vertical + + + + + + 0 + 0 + - - QSizePolicy::Expanding + + BibTeX database to use - - - 20 - 20 - + + Da&tabases - + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + databaseLW + + - - + + - - - - Scan for new databases and styles + + + + Add a BibTeX database file - - &Rescan + + &Add... - + + + + Remove the selected database + + + &Delete + + + + + + + Move the selected database upwards in the list + + + &Up + + + + + + + Move the selected database downwards in the list + + + Do&wn + + + + - + Qt::Vertical - + QSizePolicy::Expanding - + 77 16 @@ -67,126 +98,178 @@ - - - - - 1 - 0 + + + + Scan for new databases and styles + + + &Rescan + + + + + + + 0 0 - + The BibTeX style - + St&yle - + styleCB - - - + + + Choose a style file - - &Browse... + + true + + + true - + false - - - + + + Choose a style file - - true - - - true + + &Browse... - + false - - - - - 1 - 0 + + + + 0 0 - + This bibliography section contains... - + &Content: - + btPrintCO - - - + + + This bibliography section contains... - + all cited references - + all uncited references - + all references - - - + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + Add bibliography to the table of contents - + Add bibliography to &TOC - - - + + + + + + O&ptions: + + + biblatexOptsLE + + + + + + + Options to the biblatex bibliography command. See the biblatex manual for details. + + + + + + + + + 6 + + 0 - - 6 + + 0 + + + 0 + + + 0 - + Qt::Horizontal - + QSizePolicy::Expanding - + 20 20 @@ -195,94 +278,30 @@ - - + + &OK - + false - + true - - + + Cancel - + false - - - - Move the selected database downwards in the list - - - Do&wn - - - - - - - Move the selected database upwards in the list - - - &Up - - - - - - - - 1 - 0 - 0 - 0 - - - - BibTeX database to use - - - Databa&ses - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - databaseLW - - - - - - - Add a BibTeX database file - - - &Add... - - - - - - - Remove the selected database - - - &Delete - - - @@ -296,7 +315,7 @@ closePB - qt_i18n.h + qt_i18n.h diff --git a/src/insets/InsetBibtex.cpp b/src/insets/InsetBibtex.cpp index 1965a3ec9d..4ead866349 100644 --- a/src/insets/InsetBibtex.cpp +++ b/src/insets/InsetBibtex.cpp @@ -5,6 +5,7 @@ * * \author Alejandro Aguilar Sierra * \author Richard Heck (BibTeX parser improvements) + * \author Jürgen Spitzmüller * * Full author contact details are available in file CREDITS. */ @@ -16,6 +17,7 @@ #include "BiblioInfo.h" #include "Buffer.h" #include "BufferParams.h" +#include "CiteEnginesList.h" #include "Cursor.h" #include "DispatchResult.h" #include "Encoding.h" @@ -79,6 +81,7 @@ ParamInfo const & InsetBibtex::findInfo(string const & /* cmdName */) param_info_.add("btprint", ParamInfo::LATEX_OPTIONAL); param_info_.add("bibfiles", ParamInfo::LATEX_REQUIRED); param_info_.add("options", ParamInfo::LYX_INTERNAL); + param_info_.add("biblatexopts", ParamInfo::LATEX_OPTIONAL); } return param_info_; } @@ -146,9 +149,10 @@ void InsetBibtex::editDatabases() const int nr_databases = bibfilelist.size(); if (nr_databases > 1) { - docstring message = bformat(_("The BibTeX inset includes %1$s databases.\n" + docstring const engine = usingBiblatex() ? _("Biblatex") : _("BibTex"); + docstring message = bformat(_("The %1$s[[BibTeX/Biblatex]] inset includes %2$s databases.\n" "If you proceed, all of them will be opened."), - convert(nr_databases)); + engine, convert(nr_databases)); int const ret = Alert::prompt(_("Open Databases?"), message, 0, 1, _("&Cancel"), _("&Proceed")); @@ -166,9 +170,16 @@ void InsetBibtex::editDatabases() const } +bool InsetBibtex::usingBiblatex() const +{ + return buffer().params().useBiblatex(); +} + + docstring InsetBibtex::screenLabel() const { - return _("BibTeX Generated Bibliography"); + return usingBiblatex() ? _("Biblatex Generated Bibliography") + : _("BibTeX Generated Bibliography"); } @@ -195,130 +206,51 @@ docstring InsetBibtex::toolTip(BufferView const & /*bv*/, int /*x*/, int /*y*/) style = split(style, bibtotoc, char_type(',')); } - tip += _("Style File:"); - tip += "
  • " + (style.empty() ? _("none") : style) + "
"; + if (!usingBiblatex()) { + tip += _("Style File:"); + tip += "
  • " + (style.empty() ? _("none") : style) + "
"; - tip += _("Lists:") + " "; - docstring btprint = getParam("btprint"); + tip += _("Lists:") + " "; + docstring btprint = getParam("btprint"); if (btprint == "btPrintAll") tip += _("all references"); else if (btprint == "btPrintNotCited") tip += _("all uncited references"); else tip += _("all cited references"); - - if (toc) { - tip += ", "; - tip += _("included in TOC"); + if (toc) { + tip += ", "; + tip += _("included in TOC"); + } + } else { + if (toc) + tip += _("Included in TOC"); + if (!getParam("biblatexopts").empty()) { + if (toc) + tip += "
"; + tip += _("Options: ") + getParam("biblatexopts"); + } } return tip; } -static string normalizeName(Buffer const & buffer, - OutputParams const & runparams, string const & name, string const & ext) -{ - string const fname = makeAbsPath(name, buffer.filePath()).absFileName(); - if (FileName::isAbsolute(name) || !FileName(fname + ext).isReadableFile()) - return name; - if (!runparams.nice) - return fname; - - // FIXME UNICODE - return to_utf8(makeRelPath(from_utf8(fname), - from_utf8(buffer.masterBuffer()->filePath()))); -} - - void InsetBibtex::latex(otexstream & os, OutputParams const & runparams) const { - // the sequence of the commands: + // The sequence of the commands: + // With normal BibTeX: // 1. \bibliographystyle{style} // 2. \addcontentsline{...} - if option bibtotoc set // 3. \bibliography{database} - // and with bibtopic: + // With bibtopic: // 1. \bibliographystyle{style} // 2. \begin{btSect}{database} // 3. \btPrint{Cited|NotCited|All} // 4. \end{btSect} + // With Biblatex: + // \printbibliography[biblatexopts] - // Database(s) - // If we are processing the LaTeX file in a temp directory then - // copy the .bib databases to this temp directory, mangling their - // names in the process. Store this mangled name in the list of - // all databases. - // (We need to do all this because BibTeX *really*, *really* - // can't handle "files with spaces" and Windows users tend to - // use such filenames.) - // Otherwise, store the (maybe absolute) path to the original, - // unmangled database name. - vector bibfilelist = getVectorFromString(getParam("bibfiles")); - vector::const_iterator it = bibfilelist.begin(); - vector::const_iterator en = bibfilelist.end(); - odocstringstream dbs; - bool didone = false; - - // determine the export format - string const tex_format = flavor2format(runparams.flavor); - - for (; it != en; ++it) { - string utf8input = to_utf8(*it); - string database = - normalizeName(buffer(), runparams, utf8input, ".bib"); - FileName const try_in_file = - makeAbsPath(database + ".bib", buffer().filePath()); - bool const not_from_texmf = try_in_file.isReadableFile(); - - if (!runparams.inComment && !runparams.dryrun && !runparams.nice && - not_from_texmf) { - // mangledFileName() needs the extension - DocFileName const in_file = DocFileName(try_in_file); - database = removeExtension(in_file.mangledFileName()); - FileName const out_file = makeAbsPath(database + ".bib", - buffer().masterBuffer()->temppath()); - bool const success = in_file.copyTo(out_file); - if (!success) { - lyxerr << "Failed to copy '" << in_file - << "' to '" << out_file << "'" - << endl; - } - } else if (!runparams.inComment && runparams.nice && not_from_texmf) { - runparams.exportdata->addExternalFile(tex_format, try_in_file, database + ".bib"); - if (!isValidLaTeXFileName(database)) { - frontend::Alert::warning(_("Invalid filename"), - _("The following filename will cause troubles " - "when running the exported file through LaTeX: ") + - from_utf8(database)); - } - if (!isValidDVIFileName(database)) { - frontend::Alert::warning(_("Problematic filename for DVI"), - _("The following filename can cause troubles " - "when running the exported file through LaTeX " - "and opening the resulting DVI: ") + - from_utf8(database), true); - } - } - - if (didone) - dbs << ','; - else - didone = true; - // FIXME UNICODE - dbs << from_utf8(latex_path(database)); - } - docstring const db_out = dbs.str(); - - // Post this warning only once. - static bool warned_about_spaces = false; - if (!warned_about_spaces && - runparams.nice && db_out.find(' ') != docstring::npos) { - warned_about_spaces = true; - Alert::warning(_("Export Warning!"), - _("There are spaces in the paths to your BibTeX databases.\n" - "BibTeX will be unable to find them.")); - } - // Style-Options string style = to_utf8(getParam("options")); // maybe empty! and with bibtotoc string bibtotoc; if (prefixIs(style, "bibtotoc")) { @@ -327,77 +259,93 @@ void InsetBibtex::latex(otexstream & os, OutputParams const & runparams) const style = split(style, bibtotoc, ','); } - if (style == "default") - style = buffer().params().defaultBiblioStyle(); - - if (!style.empty() && !buffer().params().use_bibtopic) { - string base = normalizeName(buffer(), runparams, style, ".bst"); - FileName const try_in_file = - makeAbsPath(base + ".bst", buffer().filePath()); - bool const not_from_texmf = try_in_file.isReadableFile(); - // If this style does not come from texmf and we are not - // exporting to .tex copy it to the tmp directory. - // This prevents problems with spaces and 8bit charcaters - // in the file name. - if (!runparams.inComment && !runparams.dryrun && !runparams.nice && - not_from_texmf) { - // use new style name - DocFileName const in_file = DocFileName(try_in_file); - base = removeExtension(in_file.mangledFileName()); - FileName const out_file = makeAbsPath(base + ".bst", - buffer().masterBuffer()->temppath()); - bool const success = in_file.copyTo(out_file); - if (!success) { - lyxerr << "Failed to copy '" << in_file - << "' to '" << out_file << "'" - << endl; - } - } - // FIXME UNICODE - os << "\\bibliographystyle{" - << from_utf8(latex_path(normalizeName(buffer(), runparams, base, ".bst"))) - << "}\n"; - } - - // Post this warning only once. - static bool warned_about_bst_spaces = false; - if (!warned_about_bst_spaces && runparams.nice && contains(style, ' ')) { - warned_about_bst_spaces = true; - Alert::warning(_("Export Warning!"), - _("There are spaces in the path to your BibTeX style file.\n" - "BibTeX will be unable to find it.")); - } - - if (!db_out.empty() && buffer().params().use_bibtopic) { - os << "\\begin{btSect}"; - if (!style.empty()) - os << "[" << style << "]"; - os << "{" << db_out << "}\n"; + if (usingBiblatex()) { + // Options + string opts = to_utf8(getParam("biblatexopts")); + // bibtotoc-Option + if (!bibtotoc.empty()) + opts = opts.empty() ? "heading=bibintoc" : "heading=bibintoc," + opts; + // The bibliography command docstring btprint = getParam("btprint"); - if (btprint.empty()) - // default - btprint = from_ascii("btPrintCited"); - os << "\\" << btprint << "\n" - << "\\end{btSect}\n"; - } - - // bibtotoc-Option - if (!bibtotoc.empty() && !buffer().params().use_bibtopic) { - // set label for hyperref, see http://www.lyx.org/trac/ticket/6470 - if (buffer().params().pdfoptions().use_hyperref) - os << "\\phantomsection"; - if (buffer().params().documentClass().hasLaTeXLayout("chapter")) - os << "\\addcontentsline{toc}{chapter}{\\bibname}"; - else if (buffer().params().documentClass().hasLaTeXLayout("section")) - os << "\\addcontentsline{toc}{section}{\\refname}"; - } - - if (!db_out.empty() && !buffer().params().use_bibtopic) { - docstring btprint = getParam("btprint"); - if (btprint == "btPrintAll") { + if (btprint == "btPrintAll") os << "\\nocite{*}\n"; + os << "\\printbibliography"; + if (!opts.empty()) + os << "[" << opts << "]"; + os << "\n"; + } else {// using BibTeX + // Database(s) + vector const db_out = + buffer().prepareBibFilePaths(runparams, getBibFiles(), false); + // Style options + if (style == "default") + style = buffer().params().defaultBiblioStyle(); + if (!style.empty() && !buffer().params().use_bibtopic) { + string base = buffer().prepareFileNameForLaTeX(style, ".bst", runparams.nice); + FileName const try_in_file = + makeAbsPath(base + ".bst", buffer().filePath()); + bool const not_from_texmf = try_in_file.isReadableFile(); + // If this style does not come from texmf and we are not + // exporting to .tex copy it to the tmp directory. + // This prevents problems with spaces and 8bit characters + // in the file name. + if (!runparams.inComment && !runparams.dryrun && !runparams.nice && + not_from_texmf) { + // use new style name + DocFileName const in_file = DocFileName(try_in_file); + base = removeExtension(in_file.mangledFileName()); + FileName const out_file = makeAbsPath(base + ".bst", + buffer().masterBuffer()->temppath()); + bool const success = in_file.copyTo(out_file); + if (!success) { + LYXERR0("Failed to copy '" << in_file + << "' to '" << out_file << "'"); + } + } + // FIXME UNICODE + os << "\\bibliographystyle{" + << from_utf8(latex_path(buffer().prepareFileNameForLaTeX(base, ".bst", runparams.nice))) + << "}\n"; + } + // Warn about spaces in bst path. Warn only once. + static bool warned_about_bst_spaces = false; + if (!warned_about_bst_spaces && runparams.nice && contains(style, ' ')) { + warned_about_bst_spaces = true; + Alert::warning(_("Export Warning!"), + _("There are spaces in the path to your BibTeX style file.\n" + "BibTeX will be unable to find it.")); + } + // Handle the bibtopic case + if (!db_out.empty() && buffer().params().use_bibtopic) { + os << "\\begin{btSect}"; + if (!style.empty()) + os << "[" << style << "]"; + os << "{" << getStringFromVector(db_out) << "}\n"; + docstring btprint = getParam("btprint"); + if (btprint.empty()) + // default + btprint = from_ascii("btPrintCited"); + os << "\\" << btprint << "\n" + << "\\end{btSect}\n"; + } + // bibtotoc option + if (!bibtotoc.empty() && !buffer().params().use_bibtopic) { + // set label for hyperref, see http://www.lyx.org/trac/ticket/6470 + if (buffer().params().pdfoptions().use_hyperref) + os << "\\phantomsection"; + if (buffer().params().documentClass().hasLaTeXLayout("chapter")) + os << "\\addcontentsline{toc}{chapter}{\\bibname}"; + else if (buffer().params().documentClass().hasLaTeXLayout("section")) + os << "\\addcontentsline{toc}{section}{\\refname}"; + } + // The bibliography command + if (!db_out.empty() && !buffer().params().use_bibtopic) { + docstring btprint = getParam("btprint"); + if (btprint == "btPrintAll") { + os << "\\nocite{*}\n"; + } + os << "\\bibliography{" << getStringFromVector(db_out) << "}\n"; } - os << "\\bibliography{" << db_out << "}\n"; } } diff --git a/src/insets/InsetBibtex.h b/src/insets/InsetBibtex.h index 1e42ca4152..038065ffc0 100644 --- a/src/insets/InsetBibtex.h +++ b/src/insets/InsetBibtex.h @@ -85,6 +85,8 @@ private: void editDatabases() const; /// void parseBibTeXFiles() const; + /// + bool usingBiblatex() const; /// \name Private functions inherited from Inset class //@{ diff --git a/src/tex2lyx/TODO.txt b/src/tex2lyx/TODO.txt index 23c7ff4672..c6866ed92a 100644 --- a/src/tex2lyx/TODO.txt +++ b/src/tex2lyx/TODO.txt @@ -107,6 +107,34 @@ Format LaTeX feature LyX feature \usepackage[cochineal]{newtxmath} \font_math "cochineal-ntxm" "" 526 Plural and capitalized refstyles InsetRef +528 Biblatex + \usepackage{biblatex} \cite_engine biblatex + ...[...natbib=true...]... \cite_engine biblatex-natbib + ...[...style=...]... \biblatex_bibstyle + \biblatex_citestyle + ...[...bibstyle=...]... \biblatex_bibstyle + ...[...citestyle=...]... \biblatex_citestyle + ...[......]... \biblio_options + \printbibliography[] \begin_inset CommandInset bibtex + biblatexopts "" + \addbibresource{file.bib} \begin_inset CommandInset bibtex + [multiple possible!] bibfiles "...,file,..." [NB: strip ext!] + \bibliography{file1,file2,...} \begin_inset CommandInset bibtex + bibfiles "...,file1,file2,..." + \begin_inset CommandInset citation + \Cite LatexCmd Cite + \cite* LatexCmd citeyear + \citeyear LatexCmd citebyear + \{T,t}extcite LatexCmd {C,c}itet + \{P,p}arencite LatexCmd {C,c}itep + \parencite* LatexCmd citeyearpar + \{S,s}martcite LatexCmd {F,f}ootcite + \{F,f}ootcite LatexCmd {F,f}ootcite + \{A,a}utocite LatexCmd {A,a}utocite + \citecite[*] LatexCmd citecite[*] + \fullcite LatexCmd fullcite + \footfullcite LatexCmd footfullcite + \supercite LatexCmd supercite General diff --git a/src/version.h b/src/version.h index 9ff5b6b5b1..1c9922ffb1 100644 --- a/src/version.h +++ b/src/version.h @@ -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 527 // rgh: labelonly for references -#define LYX_FORMAT_TEX2LYX 527 +#define LYX_FORMAT_LYX 528 // spitz: biblatex +#define LYX_FORMAT_TEX2LYX 528 #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX #ifndef _MSC_VER -- 2.39.5