Introduce textclass categories

The categories are ascribed by \DeclareCategory{<category>} in the layout file header.
UI follows.
This commit is contained in:
Juergen Spitzmueller 2012-10-09 07:17:36 +02:00
parent 2b0a7a5e01
commit f18af303fe
6 changed files with 109 additions and 39 deletions

View File

@ -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

View File

@ -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():

View File

@ -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

View File

@ -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.

View File

@ -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_;
} }

View File

@ -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