mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 10:00:33 +00:00
Introduce textclass categories
The categories are ascribed by \DeclareCategory{<category>} in the layout file header. UI follows.
This commit is contained in:
parent
2b0a7a5e01
commit
f18af303fe
@ -64,7 +64,13 @@
|
|||||||
|
|
||||||
\newcommand{\AddLayout}[5][\default]{
|
\newcommand{\AddLayout}[5][\default]{
|
||||||
\def\default{#2}
|
\def\default{#2}
|
||||||
\immediate\write\layouts{"#2" "#1" "#3" "#4" "#5"}}
|
\@ifundefined{category@#2}{%
|
||||||
|
\immediate\write\layouts{"#2" "#1" "#3" "#4" "#5" ""}%
|
||||||
|
}{%
|
||||||
|
\immediate\write\layouts{"#2" "#1" "#3" "#4" "#5" "\@nameuse{category@#2}"}%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
\newcommand{\AddVariable}[2]{
|
\newcommand{\AddVariable}[2]{
|
||||||
\immediate\write\vars{chk_#1='#2'}}
|
\immediate\write\vars{chk_#1='#2'}}
|
||||||
@ -148,6 +154,12 @@
|
|||||||
{\AddLayout[\firstelement]{\layoutname}{#2}{false}{\missingelements}}
|
{\AddLayout[\firstelement]{\layoutname}{#2}{false}{\missingelements}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
\newcommand{\DeclareCategory}[2]{
|
||||||
|
\@ifundefined{category@#1}
|
||||||
|
{\global\@namedef{category@#1}{#2}}%
|
||||||
|
{}% we have already defined this one.
|
||||||
|
}
|
||||||
|
|
||||||
% Only for compatibility. Will be removed later.
|
% Only for compatibility. Will be removed later.
|
||||||
\let\DeclareSGMLClass=\DeclareDocBookClass
|
\let\DeclareSGMLClass=\DeclareDocBookClass
|
||||||
|
|
||||||
|
@ -1006,17 +1006,29 @@ def checkOtherEntries():
|
|||||||
def processLayoutFile(file, bool_docbook):
|
def processLayoutFile(file, bool_docbook):
|
||||||
''' process layout file and get a line of result
|
''' process layout file and get a line of result
|
||||||
|
|
||||||
Declare lines look like this: (article.layout, scrbook.layout, svjog.layout)
|
Declare lines look like this:
|
||||||
|
|
||||||
|
\DeclareLaTeXClass[<requirements>]{<description>}
|
||||||
|
|
||||||
|
Optionally, a \DeclareCategory line follows:
|
||||||
|
|
||||||
|
\DeclareCategory{<category>}
|
||||||
|
|
||||||
|
So for example (article.layout, scrbook.layout, svjog.layout)
|
||||||
|
|
||||||
\DeclareLaTeXClass{article}
|
\DeclareLaTeXClass{article}
|
||||||
|
\DeclareCategory{Articles}
|
||||||
|
|
||||||
\DeclareLaTeXClass[scrbook]{book (koma-script)}
|
\DeclareLaTeXClass[scrbook]{book (koma-script)}
|
||||||
|
\DeclareCategory{Books}
|
||||||
|
|
||||||
\DeclareLaTeXClass[svjour,svjog.clo]{article (Springer - svjour/jog)}
|
\DeclareLaTeXClass[svjour,svjog.clo]{article (Springer - svjour/jog)}
|
||||||
|
|
||||||
we expect output:
|
we'd expect this output:
|
||||||
|
|
||||||
"article" "article" "article" "false" "article.cls"
|
"article" "article" "article" "false" "article.cls" "Articles"
|
||||||
"scrbook" "scrbook" "book (koma-script)" "false" "scrbook.cls"
|
"scrbook" "scrbook" "book (koma-script)" "false" "scrbook.cls" "Books"
|
||||||
"svjog" "svjour" "article (Springer - svjour/jog)" "false" "svjour.cls,svjog.clo"
|
"svjog" "svjour" "article (Springer - svjour/jog)" "false" "svjour.cls,svjog.clo" ""
|
||||||
'''
|
'''
|
||||||
def checkForClassExtension(x):
|
def checkForClassExtension(x):
|
||||||
'''if the extension for a latex class is not
|
'''if the extension for a latex class is not
|
||||||
@ -1028,8 +1040,12 @@ def processLayoutFile(file, bool_docbook):
|
|||||||
classname = file.split(os.sep)[-1].split('.')[0]
|
classname = file.split(os.sep)[-1].split('.')[0]
|
||||||
# return ('LaTeX', '[a,b]', 'a', ',b,c', 'article') for \DeclareLaTeXClass[a,b,c]{article}
|
# return ('LaTeX', '[a,b]', 'a', ',b,c', 'article') for \DeclareLaTeXClass[a,b,c]{article}
|
||||||
p = re.compile(r'\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
|
p = re.compile(r'\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
|
||||||
|
q = re.compile(r'\DeclareCategory{(.*)}')
|
||||||
|
classdeclaration = ""
|
||||||
|
categorydeclaration = '""'
|
||||||
for line in open(file).readlines():
|
for line in open(file).readlines():
|
||||||
res = p.search(line)
|
res = p.search(line)
|
||||||
|
qres = q.search(line)
|
||||||
if res != None:
|
if res != None:
|
||||||
(classtype, optAll, opt, opt1, desc) = res.groups()
|
(classtype, optAll, opt, opt1, desc) = res.groups()
|
||||||
avai = {'LaTeX':'false', 'DocBook':bool_docbook}[classtype]
|
avai = {'LaTeX':'false', 'DocBook':bool_docbook}[classtype]
|
||||||
@ -1042,7 +1058,15 @@ def processLayoutFile(file, bool_docbook):
|
|||||||
prereq_latex = ','.join(prereq_list)
|
prereq_latex = ','.join(prereq_list)
|
||||||
prereq_docbook = {'true':'', 'false':'docbook'}[bool_docbook]
|
prereq_docbook = {'true':'', 'false':'docbook'}[bool_docbook]
|
||||||
prereq = {'LaTeX':prereq_latex, 'DocBook':prereq_docbook}[classtype]
|
prereq = {'LaTeX':prereq_latex, 'DocBook':prereq_docbook}[classtype]
|
||||||
return '"%s" "%s" "%s" "%s" "%s"\n' % (classname, opt, desc, avai, prereq)
|
classdeclaration = '"%s" "%s" "%s" "%s" "%s"' % (classname, opt, desc, avai, prereq)
|
||||||
|
if categorydeclaration != "":
|
||||||
|
return classdeclaration + " " + categorydeclaration
|
||||||
|
if qres != None:
|
||||||
|
categorydeclaration = '"%s"' % (qres.groups()[0])
|
||||||
|
if classdeclaration != "":
|
||||||
|
return classdeclaration + " " + categorydeclaration
|
||||||
|
if classdeclaration != "":
|
||||||
|
return classdeclaration + " " + categorydeclaration
|
||||||
logger.warning("Layout file " + file + " has no \DeclareXXClass line. ")
|
logger.warning("Layout file " + file + " has no \DeclareXXClass line. ")
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@ -1112,6 +1136,7 @@ def checkLatexConfig(check_config, bool_docbook):
|
|||||||
# build the list of available layout files and convert it to commands
|
# build the list of available layout files and convert it to commands
|
||||||
# for chkconfig.ltx
|
# for chkconfig.ltx
|
||||||
declare = re.compile(r'\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
|
declare = re.compile(r'\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
|
||||||
|
category = re.compile(r'\DeclareCategory{(.*)}')
|
||||||
empty = re.compile(r'^\s*$')
|
empty = re.compile(r'^\s*$')
|
||||||
testclasses = list()
|
testclasses = list()
|
||||||
for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
|
for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
|
||||||
@ -1120,14 +1145,23 @@ def checkLatexConfig(check_config, bool_docbook):
|
|||||||
if not os.path.isfile(file):
|
if not os.path.isfile(file):
|
||||||
continue
|
continue
|
||||||
classname = file.split(os.sep)[-1].split('.')[0]
|
classname = file.split(os.sep)[-1].split('.')[0]
|
||||||
|
decline = ""
|
||||||
|
catline = ""
|
||||||
for line in open(file).readlines():
|
for line in open(file).readlines():
|
||||||
if not empty.match(line) and line[0] != '#':
|
if not empty.match(line) and line[0] != '#':
|
||||||
logger.warning("Failed to find valid \Declare line for layout file `" + file + "'.\n\t=> Skipping this file!")
|
if decline == "":
|
||||||
nodeclaration = True
|
logger.warning("Failed to find valid \Declare line for layout file `" + file + "'.\n\t=> Skipping this file!")
|
||||||
|
nodeclaration = True
|
||||||
|
# A class, but no category declaration. Just break.
|
||||||
break
|
break
|
||||||
if declare.search(line) == None:
|
if declare.search(line) != None:
|
||||||
|
decline = "\\TestDocClass{%s}{%s}" % (classname, line[1:].strip())
|
||||||
|
testclasses.append(decline)
|
||||||
|
elif category.search(line) != None:
|
||||||
|
catline = "\\DeclareCategory{%s}{%s}" % (classname, category.search(line).groups()[0])
|
||||||
|
testclasses.append(catline)
|
||||||
|
if catline == "" or decline == "":
|
||||||
continue
|
continue
|
||||||
testclasses.append("\\TestDocClass{%s}{%s}" % (classname, line[1:].strip()))
|
|
||||||
break
|
break
|
||||||
if nodeclaration:
|
if nodeclaration:
|
||||||
continue
|
continue
|
||||||
@ -1151,7 +1185,7 @@ def checkLatexConfig(check_config, bool_docbook):
|
|||||||
if rmcopy:
|
if rmcopy:
|
||||||
removeFiles( [ 'chkconfig.ltx' ] )
|
removeFiles( [ 'chkconfig.ltx' ] )
|
||||||
#
|
#
|
||||||
# currently, values in chhkconfig are only used to set
|
# currently, values in chkconfig are only used to set
|
||||||
# \font_encoding
|
# \font_encoding
|
||||||
values = {}
|
values = {}
|
||||||
for line in open('chkconfig.vars').readlines():
|
for line in open('chkconfig.vars').readlines():
|
||||||
|
@ -40,13 +40,14 @@ namespace lyx {
|
|||||||
|
|
||||||
|
|
||||||
LayoutFile::LayoutFile(string const & fn, string const & cln,
|
LayoutFile::LayoutFile(string const & fn, string const & cln,
|
||||||
string const & desc, string const & prereq,
|
string const & desc, string const & prereq,
|
||||||
bool texclassavail)
|
string const & category, bool texclassavail)
|
||||||
{
|
{
|
||||||
name_ = fn;
|
name_ = fn;
|
||||||
latexname_ = cln;
|
latexname_ = cln;
|
||||||
description_ = desc;
|
description_ = desc;
|
||||||
prerequisites_ = prereq;
|
prerequisites_ = prereq;
|
||||||
|
category_ = category;
|
||||||
tex_class_avail_ = texclassavail;
|
tex_class_avail_ = texclassavail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,9 +142,13 @@ bool LayoutFileList::read()
|
|||||||
break;
|
break;
|
||||||
string const prereq = lex.getString();
|
string const prereq = lex.getString();
|
||||||
LYXERR(Debug::TCLASS, "Prereq: " << prereq);
|
LYXERR(Debug::TCLASS, "Prereq: " << prereq);
|
||||||
|
if (!lex.next())
|
||||||
|
break;
|
||||||
|
string const category = lex.getString();
|
||||||
|
LYXERR(Debug::TCLASS, "Category: " << category);
|
||||||
// This code is run when we have
|
// This code is run when we have
|
||||||
// fname, clname, desc, prereq, and avail
|
// fname, clname, desc, prereq, and avail
|
||||||
LayoutFile * tmpl = new LayoutFile(fname, clname, desc, prereq, avail);
|
LayoutFile * tmpl = new LayoutFile(fname, clname, desc, prereq, category, avail);
|
||||||
if (lyxerr.debugging(Debug::TCLASS)) {
|
if (lyxerr.debugging(Debug::TCLASS)) {
|
||||||
// only system layout files are loaded here so no
|
// only system layout files are loaded here so no
|
||||||
// buffer path is needed.
|
// buffer path is needed.
|
||||||
@ -182,7 +187,8 @@ void LayoutFileList::reset(LayoutFileIndex const & classname) {
|
|||||||
LayoutFile * tc = classmap_[classname];
|
LayoutFile * tc = classmap_[classname];
|
||||||
LayoutFile * tmpl =
|
LayoutFile * tmpl =
|
||||||
new LayoutFile(tc->name(), tc->latexname(), tc->description(),
|
new LayoutFile(tc->name(), tc->latexname(), tc->description(),
|
||||||
tc->prerequisites(), tc->isTeXClassAvailable());
|
tc->prerequisites(), tc->category(),
|
||||||
|
tc->isTeXClassAvailable());
|
||||||
classmap_[classname] = tmpl;
|
classmap_[classname] = tmpl;
|
||||||
delete tc;
|
delete tc;
|
||||||
}
|
}
|
||||||
@ -227,7 +233,7 @@ LayoutFileIndex LayoutFileList::addEmptyClass(string const & textclass)
|
|||||||
// the last parameter to true will suppress a warning message about missing
|
// the last parameter to true will suppress a warning message about missing
|
||||||
// tex class.
|
// tex class.
|
||||||
LayoutFile * tc = new LayoutFile(textclass, textclass,
|
LayoutFile * tc = new LayoutFile(textclass, textclass,
|
||||||
"Unknown text class " + textclass, textclass + ".cls", true);
|
"Unknown text class " + textclass, textclass + ".cls", "", true);
|
||||||
|
|
||||||
if (!tc->load(tempLayout.absFileName())) {
|
if (!tc->load(tempLayout.absFileName())) {
|
||||||
// The only way this happens is because the hardcoded layout file
|
// The only way this happens is because the hardcoded layout file
|
||||||
@ -272,7 +278,12 @@ LayoutFileIndex
|
|||||||
ifstream ifs(layout_file.toFilesystemEncoding().c_str());
|
ifstream ifs(layout_file.toFilesystemEncoding().c_str());
|
||||||
static regex const reg("^#\\s*\\\\Declare(LaTeX|DocBook)Class\\s*"
|
static regex const reg("^#\\s*\\\\Declare(LaTeX|DocBook)Class\\s*"
|
||||||
"(?:\\[([^,]*)(?:,.*)*\\])*\\s*\\{(.*)\\}\\s*");
|
"(?:\\[([^,]*)(?:,.*)*\\])*\\s*\\{(.*)\\}\\s*");
|
||||||
|
static regex const catreg("^#\\s*\\\\DeclareCategory\\{(.*)\\}");
|
||||||
string line;
|
string line;
|
||||||
|
string class_name;
|
||||||
|
string class_prereq;
|
||||||
|
string category;
|
||||||
|
bool have_declaration = false;
|
||||||
while (getline(ifs, line)) {
|
while (getline(ifs, line)) {
|
||||||
// look for the \DeclareXXXClass line
|
// look for the \DeclareXXXClass line
|
||||||
smatch sub;
|
smatch sub;
|
||||||
@ -280,26 +291,34 @@ LayoutFileIndex
|
|||||||
// returns: whole string, classtype (not used here), class name, description
|
// returns: whole string, classtype (not used here), class name, description
|
||||||
LASSERT(sub.size() == 4, /**/);
|
LASSERT(sub.size() == 4, /**/);
|
||||||
// now, create a TextClass with description containing path information
|
// now, create a TextClass with description containing path information
|
||||||
string class_name(sub.str(2) == "" ? textclass : sub.str(2));
|
class_name = (sub.str(2) == "" ? textclass : sub.str(2));
|
||||||
string class_prereq(class_name + ".cls");
|
class_prereq = class_name + ".cls";
|
||||||
LayoutFile * tmpl =
|
have_declaration = true;
|
||||||
new LayoutFile(textclass, class_name, textclass, class_prereq, true);
|
|
||||||
//FIXME: The prerequisites are available from the layout file and
|
|
||||||
// can be extracted from the above regex, but for now this
|
|
||||||
// field is simply set to class_name + ".cls"
|
|
||||||
// This textclass is added on request so it will definitely be
|
|
||||||
// used. Load it now because other load() calls may fail if they
|
|
||||||
// are called in a context without buffer path information.
|
|
||||||
tmpl->load(path);
|
|
||||||
// There will be only one textclass with this name, even if different
|
|
||||||
// layout files are loaded from different directories.
|
|
||||||
if (haveClass(textclass)) {
|
|
||||||
LYXERR0("Existing textclass " << textclass << " is redefined by " << fullName);
|
|
||||||
delete classmap_[textclass];
|
|
||||||
}
|
|
||||||
classmap_[textclass] = tmpl;
|
|
||||||
return textclass;
|
|
||||||
}
|
}
|
||||||
|
else if (regex_match(line, sub, catreg)) {
|
||||||
|
category = sub.str(1);
|
||||||
|
}
|
||||||
|
if (have_declaration && !category.empty())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (have_declaration) {
|
||||||
|
LayoutFile * tmpl =
|
||||||
|
new LayoutFile(textclass, class_name, textclass, class_prereq, category, true);
|
||||||
|
//FIXME: The prerequisites are available from the layout file and
|
||||||
|
// can be extracted from the above regex, but for now this
|
||||||
|
// field is simply set to class_name + ".cls"
|
||||||
|
// This textclass is added on request so it will definitely be
|
||||||
|
// used. Load it now because other load() calls may fail if they
|
||||||
|
// are called in a context without buffer path information.
|
||||||
|
tmpl->load(path);
|
||||||
|
// There will be only one textclass with this name, even if different
|
||||||
|
// layout files are loaded from different directories.
|
||||||
|
if (haveClass(textclass)) {
|
||||||
|
LYXERR0("Existing textclass " << textclass << " is redefined by " << fullName);
|
||||||
|
delete classmap_[textclass];
|
||||||
|
}
|
||||||
|
classmap_[textclass] = tmpl;
|
||||||
|
return textclass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If .layout is not in local directory, or an invalid layout is found, return null
|
// If .layout is not in local directory, or an invalid layout is found, return null
|
||||||
|
@ -76,6 +76,7 @@ private:
|
|||||||
std::string const & className = std::string(),
|
std::string const & className = std::string(),
|
||||||
std::string const & description = std::string(),
|
std::string const & description = std::string(),
|
||||||
std::string const & prerequisites = std::string(),
|
std::string const & prerequisites = std::string(),
|
||||||
|
std::string const & category = std::string(),
|
||||||
bool texclassavail = false);
|
bool texclassavail = false);
|
||||||
/// The only class that should create a LayoutFile is
|
/// The only class that should create a LayoutFile is
|
||||||
/// LayoutFileList, which calls the private constructor.
|
/// LayoutFileList, which calls the private constructor.
|
||||||
|
@ -1228,11 +1228,11 @@ bool TextClass::readFloat(Lexer & lexrc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string const & TextClass::prerequisites() const
|
string const & TextClass::prerequisites(string const & sep) const
|
||||||
{
|
{
|
||||||
if (contains(prerequisites_, ',')) {
|
if (contains(prerequisites_, ',')) {
|
||||||
vector<string> const pres = getVectorFromString(prerequisites_);
|
vector<string> const pres = getVectorFromString(prerequisites_);
|
||||||
prerequisites_ = getStringFromVector(pres, "\n\t");
|
prerequisites_ = getStringFromVector(pres, sep);
|
||||||
}
|
}
|
||||||
return prerequisites_;
|
return prerequisites_;
|
||||||
}
|
}
|
||||||
|
@ -189,11 +189,13 @@ public:
|
|||||||
///
|
///
|
||||||
std::string const & name() const { return name_; }
|
std::string const & name() const { return name_; }
|
||||||
///
|
///
|
||||||
|
std::string const & category() const { return category_; }
|
||||||
|
///
|
||||||
std::string const & description() const { return description_; }
|
std::string const & description() const { return description_; }
|
||||||
///
|
///
|
||||||
std::string const & latexname() const { return latexname_; }
|
std::string const & latexname() const { return latexname_; }
|
||||||
///
|
///
|
||||||
std::string const & prerequisites() const;
|
std::string const & prerequisites(std::string const & sep = "\n\t") const;
|
||||||
/// Can be LaTeX, DocBook, etc.
|
/// Can be LaTeX, DocBook, etc.
|
||||||
OutputType outputType() const { return outputType_; }
|
OutputType outputType() const { return outputType_; }
|
||||||
/// Can be latex, docbook ... (the name of a format)
|
/// Can be latex, docbook ... (the name of a format)
|
||||||
@ -231,6 +233,8 @@ protected:
|
|||||||
mutable LayoutList layoutlist_;
|
mutable LayoutList layoutlist_;
|
||||||
/// Layout file name
|
/// Layout file name
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
/// Class category
|
||||||
|
std::string category_;
|
||||||
/// document class name
|
/// document class name
|
||||||
std::string latexname_;
|
std::string latexname_;
|
||||||
/// document class description
|
/// document class description
|
||||||
|
Loading…
Reference in New Issue
Block a user