aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/glob.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/glob.cpp')
-rw-r--r--src/glob.cpp152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/glob.cpp b/src/glob.cpp
new file mode 100644
index 0000000..71100b7
--- /dev/null
+++ b/src/glob.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2012-2014 Robin Haberkorn
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+
+#include "sciteco.h"
+#include "interface.h"
+#include "parser.h"
+#include "ring.h"
+#include "glob.h"
+
+namespace SciTECO {
+
+namespace States {
+ StateGlob glob;
+}
+
+Globber::Globber(const gchar *_pattern)
+{
+ gchar *basename;
+
+ dirname = g_path_get_dirname(_pattern);
+ dir = g_dir_open(dirname, 0, NULL);
+
+ basename = g_path_get_basename(_pattern);
+ pattern = g_pattern_spec_new(basename);
+ g_free(basename);
+}
+
+gchar *
+Globber::next(void)
+{
+ const gchar *basename;
+
+ while ((basename = g_dir_read_name(dir)))
+ if (g_pattern_match_string(pattern, basename))
+ return g_build_filename(dirname, basename, NIL);
+
+ return NULL;
+}
+
+Globber::~Globber()
+{
+ if (pattern)
+ g_pattern_spec_free(pattern);
+ if (dir)
+ g_dir_close(dir);
+ g_free(dirname);
+}
+
+/*
+ * Command States
+ */
+
+/*$
+ * EN[pattern]$ -- Get list of files matching a glob pattern
+ *
+ * The EN command expands a glob \fIpattern\fP to a list of
+ * matching file names. This is similar to globbing
+ * on UNIX but not as powerful.
+ * A \fIpattern\fP is a file name with \(lq*\(rq and
+ * \(lq?\(rq wildcards:
+ * \(lq*\(rq matches an arbitrary, possibly empty, string.
+ * \(lq?\(rq matches an arbitrary character.
+ *
+ * EN will currently only match files in the file name component
+ * of \fIpattern\fP, not on each component of the path name
+ * separately.
+ * In other words, EN only looks through the directory
+ * of \fIpattern\fP \(em you cannot effectively match
+ * multiple directories.
+ *
+ * The result of the globbing is inserted into the current
+ * document, at the current position.
+ * A linefeed is inserted after every file name, i.e.
+ * every matching file will be on its own line.
+ *
+ * String-building characters are enabled for EN.
+ */
+/*
+ * NOTE: This does not work like classic TECO's
+ * EN command (iterative globbing), since the
+ * position in the directory cannot be reasonably
+ * reset on rubout with glib's API.
+ * If we have to perform all the globbing on initialization
+ * we can just as well return all the results at once.
+ * And we can add them to the current document since
+ * when they should be in a register, the user will
+ * have to edit that register anyway.
+ */
+State *
+StateGlob::done(const gchar *str)
+{
+ BEGIN_EXEC(&States::start);
+
+ Globber globber(str);
+
+ gchar *filename;
+ bool text_added = false;
+
+ interface.ssm(SCI_BEGINUNDOACTION);
+
+ while ((filename = globber.next())) {
+ size_t len = strlen(filename);
+ /* overwrite trailing null */
+ filename[len] = '\n';
+
+ /*
+ * FIXME: Once we're 8-bit clean, we should
+ * add the filenames null-terminated
+ * (there may be linebreaks in filename).
+ */
+ interface.ssm(SCI_ADDTEXT, len+1,
+ (sptr_t)filename);
+
+ g_free(filename);
+ text_added = true;
+ }
+
+ interface.ssm(SCI_SCROLLCARET);
+ interface.ssm(SCI_ENDUNDOACTION);
+
+ if (text_added) {
+ ring.dirtify();
+ if (current_doc_must_undo())
+ interface.undo_ssm(SCI_UNDO);
+ }
+
+ return &States::start;
+}
+
+} /* namespace SciTECO */