]> git.lyx.org Git - features.git/commitdiff
First patch for auto-cls-layout feature, from Bo Peng (ben.bob@gmail.com)
authorBo Peng <bpeng@lyx.org>
Sun, 9 Apr 2006 04:35:24 +0000 (04:35 +0000)
committerBo Peng <bpeng@lyx.org>
Sun, 9 Apr 2006 04:35:24 +0000 (04:35 +0000)
layout file in the same directory as .lyx file will be used. .cls can also
be in this directory.
* src/buffer.C, bufferparams.C: move filepath to bufferparams so this
info will be available in getToken()
* src/lyxtextclasslist.h, .C: add addTextClass() that read a .layout file
from filepath.
* src/lyxtextclass.h, .C: pass filepath to LyXTextClass::load(). .layout
file in filepath will be loaded before system ones.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@13611 a592a061-630c-0410-9148-cb99ea01b6c8

src/buffer.C
src/bufferparams.C
src/bufferparams.h
src/lyxtextclass.C
src/lyxtextclass.h
src/lyxtextclasslist.C
src/lyxtextclasslist.h

index a4d257ee9f39d5a26e88ab994264cd09449c00f4..2375a9b11de1eacce0fc854d1662a4ce261099b4 100644 (file)
@@ -182,9 +182,6 @@ public:
        /// name of the file the buffer is associated with.
        string filename;
 
-       /// The path to the document file.
-       string filepath;
-
        boost::scoped_ptr<Messages> messages;
 
        /** Set to true only when the file is fully loaded.
@@ -203,12 +200,13 @@ public:
 
 Buffer::Impl::Impl(Buffer & parent, string const & file, bool readonly_)
        : lyx_clean(true), bak_clean(true), unnamed(false), read_only(readonly_),
-         filename(file), filepath(onlyPath(file)), file_fully_loaded(false),
+         filename(file), file_fully_loaded(false),
                inset(params)
 {
        inset.setAutoBreakRows(true);
        lyxvc.buffer(&parent);
        temppath = createBufferTmpDir();
+       params.filepath = onlyPath(file);
        // FIXME: And now do something if temppath == string(), because we
        // assume from now on that temppath points to a valid temp dir.
        // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg67406.html
@@ -378,7 +376,7 @@ void Buffer::setReadonly(bool const flag)
 void Buffer::setFileName(string const & newfile)
 {
        pimpl_->filename = makeAbsPath(newfile);
-       pimpl_->filepath = onlyPath(pimpl_->filename);
+       params().filepath = onlyPath(pimpl_->filename);
        setReadonly(fs::is_readonly(pimpl_->filename));
        updateTitles();
 }
@@ -476,7 +474,7 @@ bool Buffer::readDocument(LyXLex & lex)
        BOOST_ASSERT(paragraphs().empty());
 
        readHeader(lex);
-       if (!params().getLyXTextClass().load()) {
+       if (!params().getLyXTextClass().load(filePath())) {
                string theclass = params().getLyXTextClass().name();
                Alert::error(_("Can't load document class"), bformat(
                                     "Using the default document class, because the "
@@ -1468,7 +1466,7 @@ string const & Buffer::fileName() const
 
 string const & Buffer::filePath() const
 {
-       return pimpl_->filepath;
+       return params().filepath;
 }
 
 
index 8c48aaf9f85953645380e6097f85433df89e0c5e..924b7e2698aed4cf8774ea87d7c411873df6cc30 100644 (file)
@@ -406,9 +406,18 @@ string const BufferParams::readToken(LyXLex & lex, string const & token)
                if (pp.first) {
                        textclass = pp.second;
                } else {
-                       textclass = 0;
-                       return classname;
+                       // if text class does not exist, try to load it from filepath
+                       pp = textclasslist.addTextClass(classname, filepath);
+                       if (pp.first) {
+                               textclass = pp.second;
+                       } else {        
+                               textclass = 0;
+                               return classname;
+                       }       
                }
+               // FIXME: isTeXClassAvailable will try to load the layout file, but will
+               // fail because of the lack of path info. Warnings will be given although
+               // the layout file will be correctly loaded later.
                if (!getLyXTextClass().isTeXClassAvailable()) {
                        string const msg =
                                bformat(_("The document uses a missing "
index 5951f830114577da9f71f54bc626453634044ba7..bfbaf7c936d45aac2ec900fe4c8505c986502f5a 100644 (file)
@@ -230,6 +230,8 @@ public:
        std::string const paperSizeName() const;
        ///
        std::string const babelCall(std::string const & lang_opts) const;
+       /// path of the current buffer
+       std::string filepath;
 
 private:
        /** Use the Pimpl idiom to hide those member variables that would otherwise
index 0e2e964501edd1f4bf6ae3b97c0f46f2ddce535f..1790d979b6e2cd4a8b7999f9be39ea323206420d 100644 (file)
@@ -24,6 +24,8 @@
 #include "support/lstrings.h"
 #include "support/lyxlib.h"
 #include "support/filetools.h"
+#include <boost/filesystem/operations.hpp>
+namespace fs = boost::filesystem;
 
 #include <sstream>
 
@@ -910,13 +912,15 @@ bool LyXTextClass::delete_layout(string const & name)
 
 
 // Load textclass info if not loaded yet
-bool LyXTextClass::load() const
+bool LyXTextClass::load(string const & path) const
 {
        if (loaded_)
                return true;
 
-       // Read style-file
-       string const real_file = libFileSearch("layouts", name_, "layout");
+       // Read style-file, current directory is searched before system ones
+       string real_file = path + "/" + name_ + ".layout";
+       if (!fs::exists(real_file))
+               real_file = libFileSearch("layouts", name_, "layout");
        loaded_ = const_cast<LyXTextClass*>(this)->read(real_file) == 0;
 
        if (!loaded_) {
index a878b25eff69bffa734e32a52d6a87009ff69aaf..7d34e5032cfce66fb3220799193d9975597e933e 100644 (file)
@@ -84,7 +84,7 @@ public:
        LyXLayout_ptr const & operator[](std::string const & vname) const;
 
        /// Sees to that the textclass structure has been loaded
-       bool load() const;
+       bool load(std::string const & path=".") const;
        /// Has this layout file been loaded yet?
        bool loaded() const { return loaded_; }
 
index 5887c72aee05bfd36ff3c71d48aa1381fd2d2a5c..d0be70ff77546d8ab12b068dd67189481526bfa3 100644 (file)
 #include "support/filetools.h"
 
 #include <boost/bind.hpp>
+#include <boost/regex.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <fstream>
+namespace fs = boost::filesystem;
 
 using lyx::textclass_type;
 
@@ -26,6 +30,8 @@ using lyx::support::libFileSearch;
 using lyx::support::makeDisplayPath;
 
 using boost::bind;
+using boost::regex;
+using boost::smatch;
 
 #ifndef CXX_GLOBAL_CSTD
 using std::exit;
@@ -38,6 +44,7 @@ using std::make_pair;
 using std::sort;
 using std::string;
 using std::pair;
+using std::ifstream;
 
 
 // Gets textclass number from name
@@ -167,6 +174,44 @@ bool LyXTextClassList::read()
 }
 
 
+std::pair<bool, lyx::textclass_type> const
+LyXTextClassList::addTextClass(std::string const & textclass, std::string const & path)
+{
+       // only check for textclass.layout file, .cls can be anywhere in $TEXINPUTS
+       // NOTE: latex class name is defined in textclass.layout, which can be different from textclass
+       string layout_file = path + "/" + textclass + ".layout";
+       if (fs::exists(layout_file)) {
+               lyxerr[Debug::TCLASS] << "Adding class " << textclass << " from directory " << path << endl;
+               // Read .layout file and get description, real latex classname etc
+               //
+               // This is a C++ version of function processLayoutFile in configure.py,
+               // which uses the following regex
+               //     \Declare(LaTeX|DocBook|LinuxDoc)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}
+               ifstream ifs(layout_file.c_str());
+               static regex const reg("^#\\s*\\\\Declare(LaTeX|DocBook|LinuxDoc)Class\\s*"
+                       "(?:\\[([^,]*)(?:,.*)*\\])*\\s*\\{(.*)\\}\\s*");
+               string line;
+               while (getline(ifs, line)) {
+                       // look for the \DeclareXXXClass line
+                       smatch sub;
+                       if (regex_match(line, sub, reg)) {
+                               // returns: whole string, classtype (not used here), first option, description
+                               BOOST_ASSERT(sub.size()==4);
+                               // now, add the layout to textclass.
+                               LyXTextClass tmpl(textclass, sub.str(2)==""?textclass:sub.str(2), 
+                                       sub.str(3) + " <" + path + ">", true);
+                               if (lyxerr.debugging(Debug::TCLASS))
+                                       tmpl.load(path);
+                               classlist_.push_back(tmpl);
+                               return make_pair(true, classlist_.size() - 1);
+                       }
+               }
+       }
+       // If .layout is not in local directory, or an invalid layout is found, return false
+       return make_pair(false, textclass_type(0));
+}
+       
+
 // Global variable: textclass table.
 LyXTextClassList textclasslist;
 
index 80ac1de17b00371a037a039d0cf65abdd8d0437c..9bea70bde5b8e12760fc7ec5cef6bd4f7700a35a 100644 (file)
@@ -47,6 +47,12 @@ public:
 
        /// Read textclass list.  Returns false if this fails.
        bool read();
+       
+       /// add a textclass from user local directory. 
+       /// Return ture/false, and textclass number
+       std::pair<bool, lyx::textclass_type> const
+       addTextClass(std::string const & textclass, std::string const & path);
+
 private:
        ///
        mutable ClassList classlist_;