Globbing.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8300 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Angus Leeming 2004-01-05 16:49:38 +00:00
parent 36fda753fc
commit 9387970e7d
10 changed files with 199 additions and 45 deletions

View File

@ -1,3 +1,10 @@
2004-01-05 Angus Leeming <leeming@lyx.org>
* external_templates: use the valid csh-style glob
"*.{gif,png,jpg,bmp,pbm,ppm,tga,tif,xpm,xbm}" to define the
RasterImage file filter, rather than the current psuedo-glob,
psuedo-regex .
2003-12-22 Michael Schmitt <michael.schmitt@teststep.org>
* layouts/g-brief2.layout: more spelling fixes

View File

@ -38,18 +38,10 @@ Template RasterImage
GuiName "Bitmap: $$Basename"
HelpText
A bitmap file.
In the parameters box, you can provide optional
parameters for the ImageMagick convert program.
E.g., use `-border 10x10 -bordercolor black'
to surround the picture with a black border
when you export to LaTeX.
When you export to Ascii, you can provide a
number describing how many columns the picture
should expand to.
This template uses Gimp for editing.
HelpTextEnd
InputFormat "*"
FileFilter "*.(gif|png|jpg|bmp|pbm|ppm|tga|tif|xpm|xbm)"
FileFilter "*.{gif,png,jpg,bmp,pbm,ppm,tga,tif,xpm,xbm}"
EditCommand "gimp $$FName"
AutomaticProduction true
Transform Rotate
@ -188,7 +180,7 @@ TemplateEnd
Template Date
GuiName "Date"
HelpText
Todays date.
Today's date.
Read 'info date' for more information.
HelpTextEnd
InputFormat date

View File

@ -1,3 +1,9 @@
2004-01-05 Angus Leeming <leeming@lyx.org>
* FileDialog_private.C (c-tor): invoke convert_brace_glob to convert
a csh-style glob like "*.{abc,def}" to something that
Qt can understand.
2003-12-30 Juergen Spitzmueller <j.spitzmueller@gmx.de>
* ui/QGraphicsDialogBase.ui: add missing signal/slot (bug 1469).

View File

@ -14,11 +14,13 @@
#include "FileDialog_private.h"
#include "qt_helpers.h"
#include "support/globbing.h"
#include "support/lstrings.h"
#include <qapplication.h>
#include <qtoolbutton.h>
using lyx::support::convert_brace_glob;
using lyx::support::split;
using std::string;
@ -45,7 +47,7 @@ string const getLabel(string const & str) {
LyXFileDialog::LyXFileDialog(string const & p, string const & m,
string const & t,
FileDialog::Button const & b1, FileDialog::Button const & b2)
: QFileDialog(toqstr(p), toqstr(m),
: QFileDialog(toqstr(p), toqstr(convert_brace_glob(m)),
qApp->focusWidget() ? qApp->focusWidget() : qApp->mainWidget(), toqstr(t), true),
b1_(0), b2_(0)
{

View File

@ -1,3 +1,8 @@
2004-01-05 Angus Leeming <leeming@lyx.org>
* FormFiledialog.C (glob2regex, globMatch): removed.
(Reread): use lyx::support::expand_globs instead.
2004-01-02 Angus Leeming <leeming@lyx.org>
* forms/fdfix.sh: no need to assume that the fdfix files are in

View File

@ -20,10 +20,11 @@
#include "frontends/Dialogs.h"
#include "support/FileInfo.h"
#include "support/lyxlib.h"
#include "support/lstrings.h"
#include "support/tostr.h"
#include "support/filetools.h"
#include "support/globbing.h"
#include "support/lstrings.h"
#include "support/lyxlib.h"
#include "support/tostr.h"
#include "lyx_forms.h"
@ -72,6 +73,7 @@ using std::max;
using std::sort;
using std::string;
using std::map;
using std::vector;
namespace {
@ -198,32 +200,6 @@ int FileDialog::Private::minw_ = 0;
int FileDialog::Private::minh_ = 0;
namespace {
boost::regex glob2regex(string const & pat)
{
// We massage the pattern a bit so that the usual
// shell pattern we all are used to will work.
// One nice thing about using a real regex is that
// things like "*.*[^~]" will work also.
// build the regex string.
string pattern = subst(pat, ".", "\\.");
pattern = subst(pattern, "*", ".*");
boost::regex reg(pattern);
return reg;
}
bool globMatch(string const & a, boost::regex const & reg)
{
// If the glob is invalid then match everything.
return reg.empty() ? true : boost::regex_match(a, reg);
}
} // namespace anon
// Reread: updates dialog list to match class directory
void FileDialog::Private::Reread()
{
@ -263,9 +239,9 @@ void FileDialog::Private::Reread()
++depth_;
}
// Parses all entries of the given subdirectory
boost::regex const mask_regex = glob2regex(mask_);
vector<string> const glob_matches =
lyx::support::expand_globs(mask_, directory_);
time_t curTime = time(0);
rewinddir(dir);
while (dirent * entry = readdir(dir)) {
@ -331,7 +307,7 @@ void FileDialog::Private::Reread()
buffer += Link;
// This gives the FileType of the file that
// is really pointed too after resolving all
// is really pointed to after resolving all
// symlinks. This is not necessarily the same
// as the type of Link (which could again be a
// link). Is that intended?
@ -349,7 +325,10 @@ void FileDialog::Private::Reread()
|| fileInfo.isChar()
|| fileInfo.isBlock()
|| fileInfo.isFifo()) {
if (!globMatch(fname, mask_regex))
typedef vector<string>::const_iterator viterator;
viterator gbegin = glob_matches.begin();
viterator const gend = glob_matches.end();
if (std::find(gbegin, gend, fname) == gend)
continue;
} else if (!(isDir = fileInfo.isDir()))
continue;

View File

@ -1,3 +1,7 @@
2004-01-05 Angus Leeming <leeming@lyx.org>
* globbing.[Ch]: new files containing some globbing utilities.
2003-11-05 João Luis M. Assirati <assirati@fma.if.usp.br>
* putenv.C: allocate the string before putting it into the

View File

@ -39,6 +39,8 @@ libsupport_la_SOURCES = \
forkedcontr.C \
forkedcontr.h \
getcwd.C \
globbing.C \
globbing.h \
$(COMPRESSION) kill.C \
limited_stack.h \
lstrings.C \

105
src/support/globbing.C Normal file
View File

@ -0,0 +1,105 @@
/**
* \file globbing.C
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Angus Leeming
*
* Full author contact details are available in file CREDITS.
*/
#include "globbing.h"
#include "path.h"
#include <boost/regex.hpp>
#include <boost/tokenizer.hpp>
#include "glob.h"
using std::string;
using std::vector;
namespace lyx {
namespace support {
string const convert_brace_glob(string const & glob)
{
// Matches " *.{abc,def,ghi}", storing "*." as group 1 and
// "abc,def,ghi" as group 2.
static boost::regex const glob_re(" *([^ {]*)\\{([^ }]+)\\}");
// Matches "abc" and "abc,", storing "abc" as group 1.
static boost::regex const block_re("([^,}]+),?");
string pattern;
string::const_iterator it = glob.begin();
string::const_iterator const end = glob.end();
while (true) {
boost::match_results<string::const_iterator> what;
if (!boost::regex_search(it, end, what, glob_re)) {
// Ensure that no information is lost.
pattern += string(it, end);
break;
}
// Everything from the start of the input to
// the start of the match.
pattern += string(what[-1].first, what[-1].second);
// Given " *.{abc,def}", head == "*." and tail == "abc,def".
string const head = string(what[1].first, what[1].second);
string const tail = string(what[2].first, what[2].second);
// Split the ','-separated chunks of tail so that
// $head{$chunk1,$chunk2} becomes "$head$chunk1 $head$chunk2".
string const fmt = " " + head + "$1";
pattern += boost::regex_merge(tail, block_re, fmt);
// Increment the iterator to the end of the match.
it += std::distance(it, what[0].second);
}
return pattern;
}
vector<string> const glob(string const & pattern, int flags)
{
glob_t glob_buffer = {0, 0, 0, 0, 0, 0, 0, 0, 0};
glob(pattern.c_str(), flags, 0, &glob_buffer);
vector<string> const matches(glob_buffer.gl_pathv,
glob_buffer.gl_pathv +
glob_buffer.gl_pathc);
globfree(&glob_buffer);
return matches;
}
vector<string> const expand_globs(string const & mask,
std::string const & directory)
{
typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
boost::char_separator<char> const separator(" ");
// Given "<glob> <glob> ... *.{abc,def} <glob>", expand to
// "<glob> <glob> ... *.abc *.def <glob>"
string const expanded_glob = convert_brace_glob(mask);
Path p(directory);
// Split into individual globs and then call 'glob' on each one.
vector<string> matches;
Tokenizer const tokens(expanded_glob, separator);
Tokenizer::const_iterator it = tokens.begin();
Tokenizer::const_iterator const end = tokens.end();
for (; it != end; ++it) {
vector<string> const tmp = glob(*it);
matches.insert(matches.end(), tmp.begin(), tmp.end());
}
return matches;
}
} // namespace support
} // namespace lyx

52
src/support/globbing.h Normal file
View File

@ -0,0 +1,52 @@
// -*- C++ -*-
/**
* \file globbing.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Angus Leeming
*
* Full author contact details are available in file CREDITS.
*/
#ifndef GLOBBING_H
#define GLOBBING_H
#include <string>
#include <vector>
namespace lyx {
namespace support {
/** Given a string such as
* "<glob> <glob> ... *.{abc,def} <glob>",
* convert the csh-style brace expresions:
* "<glob> <glob> ... *.abc *.def <glob>".
* Requires no system support, so should work equally on Unix, Mac, Win32.
*/
std::string const convert_brace_glob(std::string const & glob);
/** A wrapper for the Posix function 'glob'.
* \param pattern the glob to be expanded. Eg "*.[Ch]".
* \param flags flags to be passed to the system function. See 'man glob'.
* \returns a vector of the files found to match \c pattern.
*/
std::vector<std::string> const glob(std::string const & pattern, int flags = 0);
/** Given a string "<glob> <glob> <glob>", expand each glob in turn.
* Any glob that cannot be expanded is ignored silently.
* Invokes \c expand_brace_glob and \c glob internally, so use only
* on systems supporting the Posix function 'glob'.
* \param mask the string "<glob> <glob> <glob>".
* \param directory (if not empty) the current working directory from
* which \c glob is invoked.
* \returns a vector of all matching file names.
*/
std::vector<std::string> const
expand_globs(std::string const & mask,
std::string const & directory = std::string());
} // namespace support
} // namespace lyx
#endif // NOT GLOBBING_H