3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
8 * Full author contact details are available in file CREDITS.
15 #include <boost/regex.hpp>
16 #include <boost/tokenizer.hpp>
27 string const convert_brace_glob(string const & glob)
29 // Matches " *.{abc,def,ghi}", storing "*." as group 1 and
30 // "abc,def,ghi" as group 2.
31 static boost::regex const glob_re(" *([^ {]*)\\{([^ }]+)\\}");
32 // Matches "abc" and "abc,", storing "abc" as group 1.
33 static boost::regex const block_re("([^,}]+),?");
37 string::const_iterator it = glob.begin();
38 string::const_iterator const end = glob.end();
40 boost::match_results<string::const_iterator> what;
41 if (!boost::regex_search(it, end, what, glob_re)) {
42 // Ensure that no information is lost.
43 pattern += string(it, end);
47 // Everything from the start of the input to
48 // the start of the match.
49 pattern += string(what[-1].first, what[-1].second);
51 // Given " *.{abc,def}", head == "*." and tail == "abc,def".
52 string const head = string(what[1].first, what[1].second);
53 string const tail = string(what[2].first, what[2].second);
55 // Split the ','-separated chunks of tail so that
56 // $head{$chunk1,$chunk2} becomes "$head$chunk1 $head$chunk2".
57 string const fmt = " " + head + "$1";
58 pattern += boost::regex_merge(tail, block_re, fmt);
60 // Increment the iterator to the end of the match.
61 it += std::distance(it, what[0].second);
68 vector<string> const glob(string const & pattern, int flags)
71 glob_buffer.gl_offs = 0;
72 glob(pattern.c_str(), flags, 0, &glob_buffer);
73 vector<string> const matches(glob_buffer.gl_pathv,
74 glob_buffer.gl_pathv +
75 glob_buffer.gl_pathc);
76 globfree(&glob_buffer);
81 vector<string> const expand_globs(string const & mask,
82 std::string const & directory)
84 typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
85 boost::char_separator<char> const separator(" ");
87 // Given "<glob> <glob> ... *.{abc,def} <glob>", expand to
88 // "<glob> <glob> ... *.abc *.def <glob>"
89 string const expanded_glob = convert_brace_glob(mask);
93 // Split into individual globs and then call 'glob' on each one.
94 vector<string> matches;
95 Tokenizer const tokens(expanded_glob, separator);
96 Tokenizer::const_iterator it = tokens.begin();
97 Tokenizer::const_iterator const end = tokens.end();
98 for (; it != end; ++it) {
99 vector<string> const tmp = glob(*it);
100 matches.insert(matches.end(), tmp.begin(), tmp.end());
105 } // namespace support