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