Skip to content

Commit 0462d3a

Browse files
committed
Merge branch 'albert-github-feature/bug_cite_option'
2 parents e65c8b6 + 6de4422 commit 0462d3a

17 files changed

+386
-67
lines changed

doc/commands.dox

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2477,7 +2477,7 @@ Commands to create links
24772477
\sa section \ref cmdref "\\ref".
24782478

24792479
<hr>
2480-
\section cmdcite \\cite \<label\>
2480+
\section cmdcite \\cite['{'[option]'}'] \<label\>
24812481

24822482
\addindex \\cite
24832483
Adds a bibliographic reference in the text and in the list of bibliographic
@@ -2488,6 +2488,18 @@ Commands to create links
24882488
output formats a fixed representation is used. Note that using this
24892489
command requires the \c bibtex tool to be present in the search path.
24902490

2491+
There are a number of options possible:
2492+
- `number`, `shortauthor`, `year`, these options are mutually exclusive,
2493+
in case none of these is specified `number` is assumed.
2494+
- `number` create a numerical reference
2495+
- `shortauthor` just the surname of the first author is given, and in case
2496+
multiple authors are present the text "et al." is added
2497+
- `year`, the year of publication is mentioned (when specified in the bibtex
2498+
file.
2499+
- `nopar`, no (square) brackets are added
2500+
- `nocite`, no link to a citation in the bibliography is made (and the
2501+
reference is not added to the bibliography based on this item)
2502+
24912503
<hr>
24922504
\section cmdendlink \\endlink
24932505

src/cite.cpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,22 @@ class CiteInfoImpl : public CiteInfo
5858
{
5959
public:
6060
CiteInfoImpl(const QCString &label, const QCString &text=QCString())
61-
: m_label(label), m_text(text) { }
61+
: m_label(label), m_text(text), m_shortAuthor(QCString()), m_year(QCString()) { }
6262

6363
QCString label() const override { return m_label; }
6464
QCString text() const override { return m_text; }
65+
QCString shortAuthor() const override { return m_shortAuthor; }
66+
QCString year() const override { return m_year; }
6567

6668
void setText(const QCString &s) { m_text = s; }
69+
void setShortAuthor(const QCString &s) { m_shortAuthor = s; }
70+
void setYear(const QCString &s) { m_year = s; }
6771

6872
private:
6973
QCString m_label;
7074
QCString m_text;
75+
QCString m_shortAuthor;
76+
QCString m_year;
7177
};
7278

7379
struct CitationManager::Private
@@ -457,20 +463,32 @@ void CitationManager::generatePage()
457463
if (insideBib && ((i=line.find("name=\"CITEREF_"))!=-1 || (i=line.find("name=\"#CITEREF_"))!=-1))
458464
{
459465
int j=line.find("\">[");
460-
int k=line.find("]</a>");
466+
int j1=line.find("<!--[");
467+
int k=line.find("]<!--");
468+
int k1=line.find("]-->");
461469
if (j!=-1 && k!=-1)
462470
{
463471
size_t ui=static_cast<size_t>(i);
464-
size_t uj=static_cast<size_t>(j);
465-
size_t uk=static_cast<size_t>(k);
466-
QCString label = line.mid(ui+14,uj-ui-14);
467-
QCString number = line.mid(uj+2,uk-uj-1);
468-
line = line.left(ui+14) + label + line.right(line.length()-uj);
472+
size_t uj0=static_cast<size_t>(j);
473+
size_t uj=static_cast<size_t>(j1);
474+
size_t uk=static_cast<size_t>(k1);
475+
QCString label = line.mid(ui+14,uj0-ui-14);
476+
StringVector optList = split(line.mid(uj+5,uk-uj-5).str(),",");
477+
QCString number = optList[0].c_str();
478+
QCString shortAuthor = optList[1].c_str();
479+
QCString year;
480+
if (optList.size() == 3)
481+
{
482+
year = optList[2].c_str();
483+
}
484+
line = line.left(ui+14) + label + line.right(line.length()-uj0);
469485
auto it = p->entries.find(label.lower().str());
470486
//printf("label='%s' number='%s' => %p\n",qPrint(label),qPrint(number),it->second.get());
471487
if (it!=p->entries.end())
472488
{
473489
it->second->setText(number);
490+
it->second->setShortAuthor(shortAuthor);
491+
it->second->setYear(year.stripWhiteSpace());
474492
}
475493
}
476494
}

src/cite.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,56 @@
2222
#include "qcstring.h"
2323
#include "construct.h"
2424

25+
class CiteInfoOption
26+
{
27+
public:
28+
CiteInfoOption() {}
29+
static CiteInfoOption makeNumber() { return CiteInfoOption(NUMBER); }
30+
static CiteInfoOption makeShortAuthor() { return CiteInfoOption(SHORTAUTHOR); }
31+
static CiteInfoOption makeYear() { return CiteInfoOption(YEAR); }
32+
void setNoPar() { m_bits |= NOPAR_BIT; }
33+
void setNoCite() { m_bits |= NOCITE_BIT; }
34+
35+
bool isUnknown() const { return (m_bits & TypeMask)==0; }
36+
bool isNumber() const { return (m_bits & NUMBER)!=0; }
37+
bool isShortAuthor() const { return (m_bits & SHORTAUTHOR)!=0; }
38+
bool isYear() const { return (m_bits & YEAR)!=0; }
39+
40+
bool noPar() const { return (m_bits & NOPAR_BIT)!=0; }
41+
bool noCite() const { return (m_bits & NOCITE_BIT)!=0; }
42+
43+
friend inline bool operator==(const CiteInfoOption &t1,const CiteInfoOption &t2) { return t1.m_bits==t2.m_bits; }
44+
friend inline bool operator!=(const CiteInfoOption &t1,const CiteInfoOption &t2) { return !(operator==(t1,t2)); }
45+
46+
private:
47+
CiteInfoOption(int bits) : m_bits(bits) {}
48+
49+
enum Bits
50+
{
51+
UNKNOWN = 0,
52+
NUMBER = (1<<0),
53+
SHORTAUTHOR = (1<<1),
54+
YEAR = (1<<2),
55+
56+
TypeMask = 0x0000FFFF,
57+
OptionMask = 0xFFFF0000,
58+
59+
NOPAR_BIT = (1<<16), //< Don't use square brackets
60+
NOCITE_BIT = (1<<17) //< Don't create a link
61+
};
62+
unsigned int m_bits = UNKNOWN;
63+
};
64+
65+
2566
/// Citation-related data.
2667
struct CiteInfo
2768
{
2869
ABSTRACT_BASE_CLASS(CiteInfo)
2970

3071
virtual QCString label() const = 0;
3172
virtual QCString text() const = 0;
73+
virtual QCString shortAuthor() const = 0;
74+
virtual QCString year() const = 0;
3275
};
3376

3477
/**

src/commentscan.l

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3367,15 +3367,22 @@ static bool handleImage(yyscan_t yyscanner,const QCString &s, const StringVector
33673367
return FALSE;
33683368
}
33693369

3370-
static bool handleCite(yyscan_t yyscanner,const QCString &s, const StringVector &)
3370+
static bool handleCite(yyscan_t yyscanner,const QCString &s, const StringVector &optList)
33713371
{
33723372
struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
33733373
if (!yyextra->spaceBeforeCmd.isEmpty())
33743374
{
33753375
addOutput(yyscanner,yyextra->spaceBeforeCmd);
33763376
yyextra->spaceBeforeCmd.clear();
33773377
}
3378-
addOutput(yyscanner,"@"+s+" ");
3378+
if (optList.empty())
3379+
{
3380+
addOutput(yyscanner,"@"+s+" ");
3381+
}
3382+
else
3383+
{
3384+
addOutput(yyscanner,"@"+s+"{"+QCString(join(optList,","))+"} ");
3385+
}
33793386
BEGIN(CiteLabel);
33803387
return FALSE;
33813388
}

src/docbookvisitor.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "fileinfo.h"
3636
#include "portable.h"
3737
#include "codefragment.h"
38+
#include "cite.h"
3839

3940
#if 0
4041
#define DB_VIS_C DB_VIS_C1(m_t)
@@ -602,9 +603,23 @@ void DocbookDocVisitor::operator()(const DocCite &cite)
602603
{
603604
DB_VIS_C
604605
if (m_hide) return;
605-
if (!cite.file().isEmpty()) startLink(cite.file(),filterId(cite.anchor()));
606-
filter(cite.text());
607-
if (!cite.file().isEmpty()) endLink();
606+
auto opt = cite.option();
607+
if (!cite.file().isEmpty())
608+
{
609+
if (!opt.noCite()) startLink(cite.file(),filterId(cite.anchor()));
610+
611+
filter(cite.getText());
612+
613+
if (!opt.noCite()) endLink();
614+
}
615+
else
616+
{
617+
if (!opt.noPar()) filter("[");
618+
filter(cite.target());
619+
if (!opt.noPar()) filter("]");
620+
621+
}
622+
608623
}
609624

610625
//--------------------------------------

src/docnode.cpp

Lines changed: 103 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ void DocRef::parse()
900900

901901
//---------------------------------------------------------------------------
902902

903-
DocCite::DocCite(DocParser *parser,DocNodeVariant *parent,const QCString &target,const QCString &) : DocNode(parser,parent)
903+
DocCite::DocCite(DocParser *parser,DocNodeVariant *parent,const QCString &target,const QCString &,CiteInfoOption opt) : DocNode(parser,parent)
904904
{
905905
size_t numBibFiles = Config_getList(CITE_BIB_FILES).size();
906906
//printf("DocCite::DocCite(target=%s)\n",qPrint(target));
@@ -909,17 +909,17 @@ DocCite::DocCite(DocParser *parser,DocNodeVariant *parent,const QCString &target
909909
const CitationManager &ct = CitationManager::instance();
910910
const CiteInfo *cite = ct.find(target);
911911
//printf("cite=%p text='%s' numBibFiles=%d\n",cite,cite?qPrint(cite->text):"<null>",numBibFiles);
912+
m_option = opt;
913+
m_target = target;
912914
if (numBibFiles>0 && cite && !cite->text().isEmpty()) // ref to citation
913915
{
914-
m_text = cite->text();
915916
m_ref = "";
916917
m_anchor = ct.anchorPrefix()+cite->label();
917918
m_file = convertNameToFile(ct.fileName(),FALSE,TRUE);
918919
//printf("CITE ==> m_text=%s,m_ref=%s,m_file=%s,m_anchor=%s\n",
919920
// qPrint(m_text),qPrint(m_ref),qPrint(m_file),qPrint(m_anchor));
920921
return;
921922
}
922-
m_text = target;
923923
if (numBibFiles==0)
924924
{
925925
warn_doc_error(parser->context.fileName,parser->tokenizer.getLineNr(),"\\cite command found but no bib files specified via CITE_BIB_FILES!");
@@ -936,6 +936,27 @@ DocCite::DocCite(DocParser *parser,DocNodeVariant *parent,const QCString &target
936936
}
937937
}
938938

939+
QCString DocCite::getText() const
940+
{
941+
QCString txt;
942+
auto opt = m_option;
943+
const CitationManager &ct = CitationManager::instance();
944+
const CiteInfo *citeInfo = ct.find(m_target);
945+
946+
if (!opt.noPar()) txt += "[";
947+
948+
if (citeInfo)
949+
{
950+
if (opt.isNumber()) txt += citeInfo->text();
951+
else if (opt.isShortAuthor()) txt += citeInfo->shortAuthor();
952+
else if (opt.isYear()) txt += citeInfo->year();
953+
}
954+
955+
if (!opt.noPar()) txt += "]";
956+
return txt;
957+
}
958+
959+
939960
//---------------------------------------------------------------------------
940961

941962
DocLink::DocLink(DocParser *parser,DocNodeVariant *parent,const QCString &target) : DocCompoundNode(parser,parent)
@@ -3304,31 +3325,104 @@ Token DocPara::handleParamSection(const QCString &cmdName,
33043325
void DocPara::handleCite(char cmdChar,const QCString &cmdName)
33053326
{
33063327
AUTO_TRACE();
3328+
QCString saveCmdName = cmdName;
33073329
// get the argument of the cite command.
33083330
Token tok=parser()->tokenizer.lex();
3309-
if (!tok.is(TokenRetval::TK_WHITESPACE))
3331+
3332+
CiteInfoOption option;
3333+
if (tok.is(TokenRetval::TK_WORD) && parser()->context.token->name=="{")
3334+
{
3335+
parser()->tokenizer.setStateOptions();
3336+
parser()->tokenizer.lex();
3337+
StringVector optList=split(parser()->context.token->name.str(),",");
3338+
for (auto const &opt : optList)
3339+
{
3340+
if (opt == "number")
3341+
{
3342+
if (!option.isUnknown())
3343+
{
3344+
warn(parser()->context.fileName,parser()->tokenizer.getLineNr(),"Multiple options specified with \\{}, discarding '{}'", saveCmdName, opt);
3345+
}
3346+
else
3347+
{
3348+
option = CiteInfoOption::makeNumber();
3349+
}
3350+
}
3351+
else if (opt == "year")
3352+
{
3353+
if (!option.isUnknown())
3354+
{
3355+
warn(parser()->context.fileName,parser()->tokenizer.getLineNr(),"Multiple options specified with \\{}, discarding '{}'", saveCmdName, opt);
3356+
}
3357+
else
3358+
{
3359+
option = CiteInfoOption::makeYear();
3360+
}
3361+
}
3362+
else if (opt == "shortauthor")
3363+
{
3364+
if (!option.isUnknown())
3365+
{
3366+
warn(parser()->context.fileName,parser()->tokenizer.getLineNr(),"Multiple options specified with \\{}, discarding '{}'", saveCmdName, opt);
3367+
}
3368+
else
3369+
{
3370+
option = CiteInfoOption::makeShortAuthor();
3371+
}
3372+
}
3373+
else if (opt == "nopar")
3374+
{
3375+
option.setNoPar();
3376+
}
3377+
else if (opt == "nocite")
3378+
{
3379+
option.setNoCite();
3380+
}
3381+
else
3382+
{
3383+
warn(parser()->context.fileName,parser()->tokenizer.getLineNr(),"Unkown option specified with \\{}, discarding '{}'", saveCmdName, opt);
3384+
}
3385+
}
3386+
3387+
if (option.isUnknown()) option = CiteInfoOption::makeNumber();
3388+
3389+
parser()->tokenizer.setStatePara();
3390+
tok=parser()->tokenizer.lex();
3391+
if (!tok.is(TokenRetval::TK_WHITESPACE))
3392+
{
3393+
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"expected whitespace after \\{} command",
3394+
saveCmdName);
3395+
return;
3396+
}
3397+
}
3398+
else if (!tok.is(TokenRetval::TK_WHITESPACE))
33103399
{
33113400
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"expected whitespace after '{:c}{}' command",
3312-
cmdChar,cmdName);
3401+
cmdChar,saveCmdName);
33133402
return;
33143403
}
3404+
else
3405+
{
3406+
option = CiteInfoOption::makeNumber();
3407+
}
3408+
33153409
parser()->tokenizer.setStateCite();
33163410
tok=parser()->tokenizer.lex();
33173411
if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
33183412
{
3319-
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
3320-
"argument of command '{:c}{}'",cmdChar,cmdName);
3413+
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"THE ONE unexpected end of comment block while parsing the "
3414+
"argument of command '{:c}{}'",cmdChar,saveCmdName);
33213415
return;
33223416
}
33233417
else if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
33243418
{
33253419
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"unexpected token {} as the argument of '{:c}{}'",
3326-
tok.to_string(),cmdChar,cmdName);
3420+
tok.to_string(),cmdChar,saveCmdName);
33273421
return;
33283422
}
33293423
parser()->context.token->sectionId = parser()->context.token->name;
33303424
children().append<DocCite>(
3331-
parser(),thisVariant(),parser()->context.token->name,parser()->context.context);
3425+
parser(),thisVariant(),parser()->context.token->name,parser()->context.context,option);
33323426

33333427
parser()->tokenizer.setStatePara();
33343428
}

0 commit comments

Comments
 (0)