diff options
| author | Mitja Felicijan <mitja.felicijan@gmail.com> | 2023-11-09 23:19:53 +0100 |
|---|---|---|
| committer | Mitja Felicijan <mitja.felicijan@gmail.com> | 2023-11-09 23:19:53 +0100 |
| commit | 1566b6faa8534118c3566188181367cd0868468f (patch) | |
| tree | 1de8d4b369efb5e592685a31088f798a6b63ffa1 /examples/dte/file-option.c | |
| parent | 349991bf6efe473ab9a5cbdae0a8114d72b997e3 (diff) | |
| download | crep-1566b6faa8534118c3566188181367cd0868468f.tar.gz | |
Added partial matching and introduced threads
Diffstat (limited to 'examples/dte/file-option.c')
| -rw-r--r-- | examples/dte/file-option.c | 193 |
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)); +} |
