> Another solution (but only if we managed to have exception handling)
> would be to provide the default textclass.lst (the one when using
> --without-latex-config) in case of problem.
This is what I am doing:
1. chkconfig.ltx generates textclass.lst.tmp, package.lst.tmp first.
Index: lib/chkconfig.ltx
===================================================================
--- lib/chkconfig.ltx (revision 20491)
+++ lib/chkconfig.ltx (working copy)
@@ -129,10 +129,10 @@
% Initializes the files
\typeout{\prefix Inspecting your LaTeX configuration.}
-\newwrite{\layouts} \immediate\openout \layouts = textclass.lst
+\newwrite{\layouts} \immediate\openout \layouts = textclass.lst.tmp
\newwrite{\sed} \immediate\openout \sed = chkconfig.sed
\newwrite{\vars} \immediate\openout \vars = chkconfig.vars
-\newwrite{\packages} \immediate\openout \packages = packages.lst
+\newwrite{\packages} \immediate\openout \packages = packages.lst.tmp
2. generate a default textclass.lst regardless of --without-latex-config
- if not check_config:
- print ' default values'
+ # Then, generate a default textclass.lst. In case configure.py
+ # fails, we still have something to start lyx.
+ print ' default values'
3. If not in --without-latex-config mode, try to produce
textclass.lst.tmp and packages.lst.tmp
- else:
+ if check_config:
print '\tauto'
4. replace textclass.lst with textclass.lst.tmp and replace
packages.lst with packages.lst.tmp if configure succeed.
+ # if configure successed, move textclass.lst.tmp to textclass.lst
+ # and packages.lst.tmp to packages.lst
+ if os.path.isfile('textclass.lst.tmp') and
len(open('textclass.lst.tmp').read()) > 0 \
+ and os.path.isfile('packages.lst.tmp') and
len(open('packages.lst.tmp').read()) > 0:
+ shutil.move('textclass.lst.tmp', 'textclass.lst')
+ shutil.move('packages.lst.tmp', 'packages.lst')
+
5. The rest of the patch (to lyx itself) is arguably unnecessary.
However, it makes sure that lyx will always start in case of invalid
list files, and I suggest that we put it in (after testing).
Cheers,
Bo
Index: src/LyX.cpp
===================================================================
--- src/LyX.cpp (revision 20474)
+++ src/LyX.cpp (working copy)
@@ -611,6 +611,13 @@
// aknowledged.
restoreGuiSession();
+ // if reconfiguration is needed.
+ if (textclasslist.empty()) {
+ Alert::error(_("No textclass is found"),
+ _("Click OK to reconfigure lyx."));
+ pimpl_->lyxfunc_.dispatch(FuncRequest(LFUN_RECONFIGURE));
+ }
+
// Execute batch commands if available
if (batch_command.empty())
return;
@@ -626,6 +633,10 @@
{
LyXView * view = newLyXView();
+ // if there is no valid class list, do not load any file.
+ if (textclasslist.empty())
+ return;
+
// if some files were specified at command-line we assume that the
// user wants to edit *these* files and not to restore the session.
if (!pimpl_->files_to_load_.empty()) {
Index: src/TextClassList.cpp
===================================================================
--- src/TextClassList.cpp (revision 20474)
+++ src/TextClassList.cpp (working copy)
@@ -164,13 +164,15 @@
}
LYXERR(Debug::TCLASS) << "End of parsing of textclass.lst" << endl;
- if (classlist_.empty()) {
+ // lyx will start with an empty classlist_, but only reconfigure is allowed
+ // in this case. This gives users a second chance to configure lyx if
+ // initial configuration fails. (c.f. bug 2829)
+ if (classlist_.empty())
lyxerr << "TextClassList::Read: no textclasses found!"
<< endl;
- return false;
- }
- // Ok everything loaded ok, now sort the list.
- sort(classlist_.begin(), classlist_.end(), less_textclass_avail_desc());
+ else
+ // Ok everything loaded ok, now sort the list.
+ sort(classlist_.begin(), classlist_.end(), less_textclass_avail_desc());
return true;
}
Index: src/TextClassList.h
===================================================================
--- src/TextClassList.h (revision 20474)
+++ src/TextClassList.h (working copy)
@@ -40,6 +40,8 @@
const_iterator begin() const { return classlist_.begin(); }
///
const_iterator end() const { return classlist_.end(); }
+ ///
+ bool empty() const { return classlist_.empty(); }
/// Gets textclass number from name, -1 if textclass name does not exist
std::pair<bool, textclass_type> const
Index: src/LyXFunc.cpp
===================================================================
--- src/LyXFunc.cpp (revision 20474)
+++ src/LyXFunc.cpp (working copy)
@@ -390,6 +390,16 @@
//lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl;
FuncStatus flag;
+ // if textclasslist is empty, the only allowed operation is reconfigure (c.f. bug 2829)
+ // FIXME: this can be removed after lyx can restart itself automatically
+ // after reconfiguration. Note that reconfiguration is triggered at
+ // LyX::execBatchCommands() in LyX.cpp.
+ if (textclasslist.empty() && cmd.action != LFUN_RECONFIGURE
+ && cmd.action != LFUN_LYX_QUIT) {
+ flag.enabled(false);
+ return flag;
+ }
+
Cursor & cur = view()->cursor();
/* In LyX/Mac, when a dialog is open, the menus of the
Index: lib/chkconfig.ltx
===================================================================
--- lib/chkconfig.ltx (revision 20491)
+++ lib/chkconfig.ltx (working copy)
@@ -129,10 +129,10 @@
% Initializes the files
\typeout{\prefix Inspecting your LaTeX configuration.}
-\newwrite{\layouts} \immediate\openout \layouts = textclass.lst
+\newwrite{\layouts} \immediate\openout \layouts = textclass.lst.tmp
\newwrite{\sed} \immediate\openout \sed = chkconfig.sed
\newwrite{\vars} \immediate\openout \vars = chkconfig.vars
-\newwrite{\packages} \immediate\openout \packages = packages.lst
+\newwrite{\packages} \immediate\openout \packages = packages.lst.tmp
\immediate\write\layouts{%
# This file declares layouts and their associated definition files.^^J%
Index: lib/configure.py
===================================================================
--- lib/configure.py (revision 20491)
+++ lib/configure.py (working copy)
@@ -594,37 +594,39 @@
# First, remove the files that we want to re-create
removeFiles(['textclass.lst', 'packages.lst', 'chkconfig.sed'])
#
- if not check_config:
- print ' default values'
- print '+checking list of textclasses... '
- tx = open('textclass.lst', 'w')
- tx.write('''
+ # Then, generate a default textclass.lst. In case configure.py
+ # fails, we still have something to start lyx.
+ print ' default values'
+ print '+checking list of textclasses... '
+ tx = open('textclass.lst', 'w')
+ tx.write('''
# This file declares layouts and their associated definition files
# (include dir. relative to the place where this file is).
# It contains only default values, since chkconfig.ltx could not be run
# for some reason. Run ./configure.py if you need to update it after a
# configuration change.
''')
- # build the list of available layout files and convert it to commands
- # for chkconfig.ltx
- foundClasses = []
- for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
- glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
- # valid file?
- if not os.path.isfile(file):
- continue
- # get stuff between /xxxx.layout .
- classname = file.split(os.sep)[-1].split('.')[0]
- # tr ' -' '__'`
- cleanclass = classname.replace(' ', '_')
- cleanclass = cleanclass.replace('-', '_')
- # make sure the same class is not considered twice
- if foundClasses.count(cleanclass) == 0: # not found before
- foundClasses.append(cleanclass)
- tx.write(processLayoutFile(file, bool_docbook, bool_linuxdoc))
- tx.close()
- print '\tdone'
- else:
+ # build the list of available layout files and convert it to commands
+ # for chkconfig.ltx
+ foundClasses = []
+ for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
+ glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
+ # valid file?
+ if not os.path.isfile(file):
+ continue
+ # get stuff between /xxxx.layout .
+ classname = file.split(os.sep)[-1].split('.')[0]
+ # tr ' -' '__'`
+ cleanclass = classname.replace(' ', '_')
+ cleanclass = cleanclass.replace('-', '_')
+ # make sure the same class is not considered twice
+ if foundClasses.count(cleanclass) == 0: # not found before
+ foundClasses.append(cleanclass)
+ tx.write(processLayoutFile(file, bool_docbook, bool_linuxdoc))
+ tx.close()
+ print '\tdone'
+ # the following will generate textclass.lst.tmp, and packages.lst.tmp
+ if check_config:
print '\tauto'
removeFiles(['wrap_chkconfig.ltx', 'chkconfig.vars', \
'chkconfig.classes', 'chklayouts.tex'])
@@ -682,6 +684,13 @@
pass
if rmcopy: # remove the copied file
removeFiles( [ 'chkconfig.ltx' ] )
+ # if configure successed, move textclass.lst.tmp to textclass.lst
+ # and packages.lst.tmp to packages.lst
+ if os.path.isfile('textclass.lst.tmp') and len(open('textclass.lst.tmp').read()) > 0 \
+ and os.path.isfile('packages.lst.tmp') and len(open('packages.lst.tmp').read()) > 0:
+ shutil.move('textclass.lst.tmp', 'textclass.lst')
+ shutil.move('packages.lst.tmp', 'packages.lst')
+
def createLaTeXConfig():