summaryrefslogtreecommitdiff
path: root/examples/dte/file-option.c
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2023-11-09 23:19:53 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2023-11-09 23:19:53 +0100
commit1566b6faa8534118c3566188181367cd0868468f (patch)
tree1de8d4b369efb5e592685a31088f798a6b63ffa1 /examples/dte/file-option.c
parent349991bf6efe473ab9a5cbdae0a8114d72b997e3 (diff)
downloadcrep-1566b6faa8534118c3566188181367cd0868468f.tar.gz
Added partial matching and introduced threads
Diffstat (limited to 'examples/dte/file-option.c')
-rw-r--r--examples/dte/file-option.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/examples/dte/file-option.c b/examples/dte/file-option.c
new file mode 100644
index 0000000..df6af3d
--- /dev/null
+++ b/examples/dte/file-option.c
@@ -0,0 +1,193 @@
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "file-option.h"
+#include "command/serialize.h"
+#include "editor.h"
+#include "editorconfig/editorconfig.h"
+#include "error.h"
+#include "options.h"
+#include "regexp.h"
+#include "util/debug.h"
+#include "util/str-util.h"
+#include "util/xmalloc.h"
+
+typedef struct {
+ FileOptionType type;
+ char **strs;
+ union {
+ char *filetype;
+ CachedRegexp *filename;
+ } u;
+} FileOption;
+
+static void set_options(EditorState *e, char **args)
+{
+ for (size_t i = 0; args[i]; i += 2) {
+ set_option(e, args[i], args[i + 1], true, false);
+ }
+}
+
+void set_editorconfig_options(Buffer *buffer)
+{
+ LocalOptions *options = &buffer->options;
+ if (!options->editorconfig) {
+ return;
+ }
+
+ const char *path = buffer->abs_filename;
+ char cwd[8192];
+ if (!path) {
+ // For buffers with no associated filename, use a dummy path of
+ // "$PWD/__", to obtain generic settings for the working directory
+ // or the user's default settings
+ static const char suffix[] = "/__";
+ if (unlikely(!getcwd(cwd, sizeof(cwd) - sizeof(suffix)))) {
+ return;
+ }
+ memcpy(cwd + strlen(cwd), suffix, sizeof(suffix));
+ path = cwd;
+ }
+
+ EditorConfigOptions opts;
+ if (get_editorconfig_options(path, &opts) != 0) {
+ return;
+ }
+
+ switch (opts.indent_style) {
+ case INDENT_STYLE_SPACE:
+ options->expand_tab = true;
+ options->emulate_tab = true;
+ options->detect_indent = 0;
+ break;
+ case INDENT_STYLE_TAB:
+ options->expand_tab = false;
+ options->emulate_tab = false;
+ options->detect_indent = 0;
+ break;
+ case INDENT_STYLE_UNSPECIFIED:
+ break;
+ }
+
+ const unsigned int indent_size = opts.indent_size;
+ if (indent_size > 0 && indent_size <= INDENT_WIDTH_MAX) {
+ options->indent_width = indent_size;
+ options->detect_indent = 0;
+ }
+
+ const unsigned int tab_width = opts.tab_width;
+ if (tab_width > 0 && tab_width <= TAB_WIDTH_MAX) {
+ options->tab_width = tab_width;
+ }
+
+ const unsigned int max_line_length = opts.max_line_length;
+ if (max_line_length > 0 && max_line_length <= TEXT_WIDTH_MAX) {
+ options->text_width = max_line_length;
+ }
+}
+
+void set_file_options(EditorState *e, Buffer *buffer)
+{
+ for (size_t i = 0, n = e->file_options.count; i < n; i++) {
+ const FileOption *opt = e->file_options.ptrs[i];
+ if (opt->type == FOPTS_FILETYPE) {
+ if (streq(opt->u.filetype, buffer->options.filetype)) {
+ set_options(e, opt->strs);
+ }
+ continue;
+ }
+
+ BUG_ON(opt->type != FOPTS_FILENAME);
+ const char *filename = buffer->abs_filename;
+ if (!filename) {
+ continue;
+ }
+
+ const regex_t *re = &opt->u.filename->re;
+ regmatch_t m;
+ if (regexp_exec(re, filename, strlen(filename), 0, &m, 0)) {
+ set_options(e, opt->strs);
+ }
+ }
+}
+
+bool add_file_options(PointerArray *file_options, FileOptionType type, StringView str, char **strs, size_t nstrs)
+{
+ size_t len = str.length;
+ if (unlikely(len == 0)) {
+ const char *desc = (type == FOPTS_FILETYPE) ? "filetype" : "pattern";
+ return error_msg("can't add option with empty %s", desc);
+ }
+
+ FileOption *opt = xnew(FileOption, 1);
+ if (type == FOPTS_FILETYPE) {
+ opt->u.filetype = xstrcut(str.data, len);
+ goto append;
+ }
+
+ BUG_ON(type != FOPTS_FILENAME);
+ CachedRegexp *r = xmalloc(sizeof(*r) + len + 1);
+ memcpy(r->str, str.data, len);
+ r->str[len] = '\0';
+ opt->u.filename = r;
+
+ int err = regcomp(&r->re, r->str, DEFAULT_REGEX_FLAGS | REG_NEWLINE | REG_NOSUB);
+ if (unlikely(err)) {
+ regexp_error_msg(&r->re, r->str, err);
+ free(r);
+ free(opt);
+ return false;
+ }
+
+append:
+ opt->type = type;
+ opt->strs = copy_string_array(strs, nstrs);
+ ptr_array_append(file_options, opt);
+ return true;
+}
+
+void dump_file_options(const PointerArray *file_options, String *buf)
+{
+ for (size_t i = 0, n = file_options->count; i < n; i++) {
+ const FileOption *opt = file_options->ptrs[i];
+ const char *tp;
+ if (opt->type == FOPTS_FILENAME) {
+ tp = opt->u.filename->str;
+ } else {
+ tp = opt->u.filetype;
+ }
+ char **strs = opt->strs;
+ string_append_literal(buf, "option ");
+ if (opt->type == FOPTS_FILENAME) {
+ string_append_literal(buf, "-r ");
+ }
+ if (str_has_prefix(tp, "-") || string_array_contains_prefix(strs, "-")) {
+ string_append_literal(buf, "-- ");
+ }
+ string_append_escaped_arg(buf, tp, true);
+ for (size_t j = 0; strs[j]; j += 2) {
+ string_append_byte(buf, ' ');
+ string_append_cstring(buf, strs[j]);
+ string_append_byte(buf, ' ');
+ string_append_escaped_arg(buf, strs[j + 1], true);
+ }
+ string_append_byte(buf, '\n');
+ }
+}
+
+static void free_file_option(FileOption *opt)
+{
+ if (opt->type == FOPTS_FILENAME) {
+ free_cached_regexp(opt->u.filename);
+ } else {
+ BUG_ON(opt->type != FOPTS_FILETYPE);
+ free(opt->u.filetype);
+ }
+ free_string_array(opt->strs);
+ free(opt);
+}
+
+void free_file_options(PointerArray *file_options)
+{
+ ptr_array_free_cb(file_options, FREE_FUNC(free_file_option));
+}