Skip to content

Commit 235da96

Browse files
committed
Flexibility of \cite command
Adding some options to the `\cite` command to make it more flexible so that not only a reference number can be show.
1 parent b4437b3 commit 235da96

17 files changed

+352
-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: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@ struct CiteInfo
2929

3030
virtual QCString label() const = 0;
3131
virtual QCString text() const = 0;
32+
virtual QCString shortAuthor() const = 0;
33+
virtual QCString year() const = 0;
34+
35+
enum CiteOptionType {
36+
UNKNOWN = 0x00,
37+
NUMBER = 0x01,
38+
SHORTAUTHOR = 0x02,
39+
YEAR = 0x04,
40+
41+
NOPAR_BIT = 0x001000, //< Don't use square brackets
42+
NOCITE_BIT = 0x100000, //< Don't create a link
43+
};
3244
};
3345

3446
/**

src/commentscan.l

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

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

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)
@@ -601,9 +602,23 @@ void DocbookDocVisitor::operator()(const DocCite &cite)
601602
{
602603
DB_VIS_C
603604
if (m_hide) return;
604-
if (!cite.file().isEmpty()) startLink(cite.file(),filterId(cite.anchor()));
605-
filter(cite.text());
606-
if (!cite.file().isEmpty()) endLink();
605+
int opt = cite.option();
606+
if (!cite.file().isEmpty())
607+
{
608+
if (!(opt & CiteInfo::NOCITE_BIT)) startLink(cite.file(),filterId(cite.anchor()));
609+
610+
filter(cite.getText());
611+
612+
if (!(opt & CiteInfo::NOCITE_BIT)) endLink();
613+
}
614+
else
615+
{
616+
if (!(opt & CiteInfo::NOPAR_BIT)) filter("[");
617+
filter(cite.target());
618+
if (!(opt & CiteInfo::NOPAR_BIT)) filter("]");
619+
620+
}
621+
607622
}
608623

609624
//--------------------------------------

src/docnode.cpp

Lines changed: 101 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,7 @@ void DocRef::parse()
891891

892892
//---------------------------------------------------------------------------
893893

894-
DocCite::DocCite(DocParser *parser,DocNodeVariant *parent,const QCString &target,const QCString &) : DocNode(parser,parent)
894+
DocCite::DocCite(DocParser *parser,DocNodeVariant *parent,const QCString &target,const QCString &,int opt) : DocNode(parser,parent)
895895
{
896896
size_t numBibFiles = Config_getList(CITE_BIB_FILES).size();
897897
//printf("DocCite::DocCite(target=%s)\n",qPrint(target));
@@ -900,17 +900,17 @@ DocCite::DocCite(DocParser *parser,DocNodeVariant *parent,const QCString &target
900900
const CitationManager &ct = CitationManager::instance();
901901
const CiteInfo *cite = ct.find(target);
902902
//printf("cite=%p text='%s' numBibFiles=%d\n",cite,cite?qPrint(cite->text):"<null>",numBibFiles);
903+
m_option = opt;
904+
m_target = target;
903905
if (numBibFiles>0 && cite && !cite->text().isEmpty()) // ref to citation
904906
{
905-
m_text = cite->text();
906907
m_ref = "";
907908
m_anchor = ct.anchorPrefix()+cite->label();
908909
m_file = convertNameToFile(ct.fileName(),FALSE,TRUE);
909910
//printf("CITE ==> m_text=%s,m_ref=%s,m_file=%s,m_anchor=%s\n",
910911
// qPrint(m_text),qPrint(m_ref),qPrint(m_file),qPrint(m_anchor));
911912
return;
912913
}
913-
m_text = target;
914914
if (numBibFiles==0)
915915
{
916916
warn_doc_error(parser->context.fileName,parser->tokenizer.getLineNr(),"\\cite command found but no bib files specified via CITE_BIB_FILES!");
@@ -927,6 +927,27 @@ DocCite::DocCite(DocParser *parser,DocNodeVariant *parent,const QCString &target
927927
}
928928
}
929929

930+
QCString DocCite::getText() const
931+
{
932+
QCString txt;
933+
int opt = m_option;
934+
const CitationManager &ct = CitationManager::instance();
935+
const CiteInfo *citeInfo = ct.find(m_target);
936+
937+
if (!(opt & CiteInfo::NOPAR_BIT)) txt += "[";
938+
939+
if (citeInfo)
940+
{
941+
if (opt & CiteInfo::NUMBER) txt += citeInfo->text();
942+
else if (opt & CiteInfo::SHORTAUTHOR) txt += citeInfo->shortAuthor();
943+
else if (opt & CiteInfo::YEAR) txt += citeInfo->year();
944+
}
945+
946+
if (!(opt & CiteInfo::NOPAR_BIT)) txt += "]";
947+
return txt;
948+
}
949+
950+
930951
//---------------------------------------------------------------------------
931952

932953
DocLink::DocLink(DocParser *parser,DocNodeVariant *parent,const QCString &target) : DocCompoundNode(parser,parent)
@@ -3295,31 +3316,102 @@ Token DocPara::handleParamSection(const QCString &cmdName,
32953316
void DocPara::handleCite(char cmdChar,const QCString &cmdName)
32963317
{
32973318
AUTO_TRACE();
3319+
QCString saveCmdName = cmdName;
32983320
// get the argument of the cite command.
32993321
Token tok=parser()->tokenizer.lex();
3300-
if (!tok.is(TokenRetval::TK_WHITESPACE))
3322+
3323+
int option = CiteInfo::UNKNOWN;
3324+
bool nopar_bit = false;
3325+
bool nocite_bit = false;
3326+
if (tok.is(TokenRetval::TK_WORD) && parser()->context.token->name=="{")
3327+
{
3328+
parser()->tokenizer.setStateOptions();
3329+
parser()->tokenizer.lex();
3330+
StringVector optList=split(parser()->context.token->name.str(),",");
3331+
for (auto const &opt : optList)
3332+
{
3333+
if (opt == "number")
3334+
{
3335+
if (option != CiteInfo::UNKNOWN)
3336+
{
3337+
warn(parser()->context.fileName,parser()->tokenizer.getLineNr(),"Multiple options specified with \\{}, discarding '{}'", saveCmdName, opt);
3338+
}
3339+
else
3340+
{
3341+
option = CiteInfo::NUMBER;
3342+
}
3343+
}
3344+
else if (opt == "year")
3345+
{
3346+
if (option != CiteInfo::UNKNOWN)
3347+
{
3348+
warn(parser()->context.fileName,parser()->tokenizer.getLineNr(),"Multiple options specified with \\{}, discarding '{}'", saveCmdName, opt);
3349+
}
3350+
else
3351+
{
3352+
option = CiteInfo::YEAR;
3353+
}
3354+
}
3355+
else if (opt == "shortauthor")
3356+
{
3357+
if (option != CiteInfo::UNKNOWN)
3358+
{
3359+
warn(parser()->context.fileName,parser()->tokenizer.getLineNr(),"Multiple options specified with \\{}, discarding '{}'", saveCmdName, opt);
3360+
}
3361+
else
3362+
{
3363+
option = CiteInfo::SHORTAUTHOR;
3364+
}
3365+
}
3366+
else if (opt == "nopar") nopar_bit = true;
3367+
else if (opt == "nocite") nocite_bit = true;
3368+
else
3369+
{
3370+
warn(parser()->context.fileName,parser()->tokenizer.getLineNr(),"Unkown option specified with \\{}, discarding '{}'", saveCmdName, opt);
3371+
}
3372+
}
3373+
3374+
if (option == CiteInfo::UNKNOWN) option = CiteInfo::NUMBER;
3375+
if (nopar_bit) option |= CiteInfo::NOPAR_BIT;
3376+
if (nocite_bit) option |= CiteInfo::NOCITE_BIT;
3377+
3378+
parser()->tokenizer.setStatePara();
3379+
tok=parser()->tokenizer.lex();
3380+
if (!tok.is(TokenRetval::TK_WHITESPACE))
3381+
{
3382+
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"expected whitespace after \\{} command",
3383+
saveCmdName);
3384+
return;
3385+
}
3386+
}
3387+
else if (!tok.is(TokenRetval::TK_WHITESPACE))
33013388
{
33023389
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"expected whitespace after '{:c}{}' command",
3303-
cmdChar,cmdName);
3390+
cmdChar,saveCmdName);
33043391
return;
33053392
}
3393+
else
3394+
{
3395+
option = CiteInfo::NUMBER;
3396+
}
3397+
33063398
parser()->tokenizer.setStateCite();
33073399
tok=parser()->tokenizer.lex();
33083400
if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
33093401
{
3310-
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
3311-
"argument of command '{:c}{}'",cmdChar,cmdName);
3402+
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"THE ONE unexpected end of comment block while parsing the "
3403+
"argument of command '{:c}{}'",cmdChar,saveCmdName);
33123404
return;
33133405
}
33143406
else if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
33153407
{
33163408
warn_doc_error(parser()->context.fileName,parser()->tokenizer.getLineNr(),"unexpected token {} as the argument of '{:c}{}'",
3317-
tok.to_string(),cmdChar,cmdName);
3409+
tok.to_string(),cmdChar,saveCmdName);
33183410
return;
33193411
}
33203412
parser()->context.token->sectionId = parser()->context.token->name;
33213413
children().append<DocCite>(
3322-
parser(),thisVariant(),parser()->context.token->name,parser()->context.context);
3414+
parser(),thisVariant(),parser()->context.token->name,parser()->context.context,option);
33233415

33243416
parser()->tokenizer.setStatePara();
33253417
}

src/docnode.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,19 +243,22 @@ class DocAnchor : public DocNode
243243
class DocCite : public DocNode
244244
{
245245
public:
246-
DocCite(DocParser *parser,DocNodeVariant *parent,const QCString &target,const QCString &context);
246+
DocCite(DocParser *parser,DocNodeVariant *parent,const QCString &target,const QCString &context, int opt);
247247
QCString file() const { return m_file; }
248248
QCString relPath() const { return m_relPath; }
249249
QCString ref() const { return m_ref; }
250250
QCString anchor() const { return m_anchor; }
251-
QCString text() const { return m_text; }
251+
QCString target() const { return m_target; }
252+
int option() const { return m_option; }
253+
QCString getText() const;
252254

253255
private:
254256
QCString m_file;
255257
QCString m_relPath;
256258
QCString m_ref;
257259
QCString m_anchor;
258-
QCString m_text;
260+
QCString m_target;
261+
int m_option;
259262
};
260263

261264

0 commit comments

Comments
 (0)