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

Reply via email to