summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-04-20 14:51:50 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2021-04-20 14:51:50 -0400
commita57a9682e74ff3609acb2ca6697fc6fa94c23fb6 (patch)
treebbe848dd7e5c7ae259fbcfdf3253240bc564c8d8
parentf90d98c3c451aa5be2979ff05863b5aa8bee9336 (diff)
:set-language, various other little things
-rw-r--r--README.md22
-rw-r--r--buffer.c2
-rw-r--r--command.c19
-rw-r--r--command.h2
-rw-r--r--main.c2
-rw-r--r--menu.c1
-rw-r--r--syntax.c4
-rw-r--r--ted.cfg18
-rw-r--r--ted.h21
-rw-r--r--ui.c10
10 files changed, 76 insertions, 25 deletions
diff --git a/README.md b/README.md
index 9450b98..726f9b1 100644
--- a/README.md
+++ b/README.md
@@ -19,18 +19,18 @@ in other editors.
## Supported features
- Customization of (pretty much) all colours and keyboard commands.
-- Basic stuff like copy+paste, undo+redo, etc.
+- Basic text editing like copy+paste, undo+redo, etc.
- Multiple tabs, each with a different file
-- Split screen (default: Ctrl+\\, Ctrl+Shift+\\)
+- Split screen
- Auto-indent
- Syntax highlighting for C, C++, HTML, LaTeX, Markdown, Python, and Rust.
- Find and replace (with regular expressions!)
-- Run build command (F4), go to errors
-- Run any shell command (Ctrl+!)
-- Go to definition (Ctrl+click)
-- Go to line (Ctrl+G)
-- Autocomplete (Ctrl+Space)
-- Indent/dedent selection (Tab, Shift+Tab), comment/uncomment selection (Ctrl+/)
+- Run build command, go to errors
+- Run any shell command
+- Go to definition
+- Go to line number
+- Autocomplete
+- Indent/dedent selection, comment/uncomment selection
## Getting started with ted
@@ -81,7 +81,9 @@ in the `[core]` section of the config file.
Jump to definition and autocompletion both depend on [ctags](https://github.com/universal-ctags/ctags). You can press Ctrl+T
at any time to generate or re-generate tags. Once you have a tags file, you can Ctrl+Click on an identifier
to go to its definition. You can also press Ctrl+D to get a searchable list of all functions/types where you can select one to go to
-its definition. Press Ctrl+space to autocomplete. If there is only one possible completion from the tags file, it will be selected automatically.
+its definition.
+
+Press Ctrl+space to autocomplete. If there is only one possible completion from the tags file, it will be selected automatically.
Otherwise, you'll get a popup showing all possible completions. You can press tab to select a completion (or click on it), and press
Ctrl+space/Ctrl+shift+space to cycle between suggestions. Note that autocomplete just completes to stuff in the tags file, so it won't complete local
variable names. Sorry.
@@ -110,7 +112,7 @@ sudo make install -j4
On Windows (64-bit), first you will need to install Microsoft Visual Studio, then find and add vcvarsall.bat to your PATH.
Next you will need the SDL2 VC development libraries: https://www.libsdl.org/download-2.0.php
-Extract the zip, copy SDL2-2.x.y into the ted directory, and rename it to SDL2. Also copy SDL2\lib\x64\SDL2.dll
+Extract the zip, copy SDL2-2.x.y into the ted directory, and rename it to SDL2. Also copy SDL2\\lib\\x64\\SDL2.dll
to the ted directory.
You will also need PCRE2. Download it here: https://ftp.pcre.org/pub/pcre/pcre2-10.36.zip,
unzip it, and put pcre2-10.36 in the same folder as ted.
diff --git a/buffer.c b/buffer.c
index 7e59e06..1e8e697 100644
--- a/buffer.c
+++ b/buffer.c
@@ -250,6 +250,8 @@ static inline Settings const *buffer_settings(TextBuffer *buffer) {
// what programming language is this?
Language buffer_language(TextBuffer *buffer) {
+ if (buffer->manual_language >= 1 && buffer->manual_language <= LANG_COUNT)
+ return (Language)(buffer->manual_language - 1);
Settings const *settings = buffer_settings(buffer);
char const *filename = buffer->filename;
if (!filename)
diff --git a/command.c b/command.c
index b706b2d..34aaf0b 100644
--- a/command.c
+++ b/command.c
@@ -116,6 +116,10 @@ void command_execute(Ted *ted, Command c, i64 argument) {
if (ted->replace && buffer == &ted->find_buffer) {
ted_switch_to_buffer(ted, &ted->replace_buffer);
buffer_select_all(buffer);
+ } else if (ted->menu == MENU_COMMAND_SELECTOR && buffer == &ted->argument_buffer) {
+ buffer = &ted->line_buffer;
+ ted_switch_to_buffer(ted, buffer);
+ buffer_select_all(buffer);
} else if (ted->autocomplete) {
autocomplete_select_cursor_completion(ted);
} else if (buffer) {
@@ -129,6 +133,10 @@ void command_execute(Ted *ted, Command c, i64 argument) {
if (ted->replace && buffer == &ted->replace_buffer) {
ted_switch_to_buffer(ted, &ted->find_buffer);
buffer_select_all(buffer);
+ } else if (ted->menu == MENU_COMMAND_SELECTOR && buffer == &ted->line_buffer) {
+ buffer = &ted->argument_buffer;
+ ted_switch_to_buffer(ted, buffer);
+ buffer_select_all(buffer);
} else if (buffer) {
if (buffer->selection)
buffer_dedent_selection(buffer);
@@ -227,7 +235,15 @@ void command_execute(Ted *ted, Command c, i64 argument) {
}
}
break;
-
+
+ case CMD_SET_LANGUAGE:
+ if (buffer && !buffer->is_line_buffer) {
+ if (argument < 0 || argument >= LANG_COUNT)
+ buffer->manual_language = -1;
+ else
+ buffer->manual_language = (i16)(argument + 1);
+ }
+ break;
case CMD_AUTOCOMPLETE:
if (ted->autocomplete)
++ted->autocomplete_cursor;
@@ -238,6 +254,7 @@ void command_execute(Ted *ted, Command c, i64 argument) {
if (ted->autocomplete)
--ted->autocomplete_cursor;
break;
+
case CMD_UNDO:
if (buffer) buffer_undo(buffer, argument);
break;
diff --git a/command.h b/command.h
index b2da2c5..39f861d 100644
--- a/command.h
+++ b/command.h
@@ -56,6 +56,7 @@ ENUM_U16 {
CMD_RELOAD_ALL, // reload all buffers from file
CMD_QUIT,
+ CMD_SET_LANGUAGE,
CMD_AUTOCOMPLETE,
CMD_AUTOCOMPLETE_BACK,
@@ -143,6 +144,7 @@ static CommandName const command_names[] = {
{"save-all", CMD_SAVE_ALL},
{"reload-all", CMD_RELOAD_ALL},
{"quit", CMD_QUIT},
+ {"set-language", CMD_SET_LANGUAGE},
{"command-selector", CMD_COMMAND_SELECTOR},
{"open-config", CMD_OPEN_CONFIG},
{"undo", CMD_UNDO},
diff --git a/main.c b/main.c
index d140f29..8cf3997 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,3 @@
-// :set-language command; -1 = default language for this extension
-
#include "base.h"
no_warn_start
#if _WIN32
diff --git a/menu.c b/menu.c
index d363b37..6977552 100644
--- a/menu.c
+++ b/menu.c
@@ -275,6 +275,7 @@ static void menu_update(Ted *ted) {
}
}
selector->n_entries = (u32)(entry - entries);
+ selector_sort_entries_by_name(selector);
}
char *chosen_command = selector_update(ted, &ted->command_selector);
diff --git a/syntax.c b/syntax.c
index bc8803c..19aca34 100644
--- a/syntax.c
+++ b/syntax.c
@@ -870,7 +870,7 @@ static void syntax_highlight_markdown(SyntaxState *state, char32_t const *line,
}
static bool is_html_tag_char(char32_t c) {
- return c == '<' || c == '/' || c == '!' || is32_alnum(c);
+ return c == '<' || c == '/' || c == '!' || c == ':' || is32_alnum(c);
}
static void syntax_highlight_html(SyntaxState *state, char32_t const *line, u32 line_len, SyntaxCharType *char_types) {
@@ -1024,7 +1024,7 @@ static void syntax_highlight_config(SyntaxState *state, char32_t const *line, u3
default: {
if (i == 0) // none of the keywords in syntax_all_keywords_config should appear at the start of the line
break;
- if (is32_ident(line[i - 1]) || !is32_ident(line[i]))
+ if (is32_ident(line[i-1]) || line[i-1] == '-' || !is32_ident(line[i]))
break; // can't be a keyword on its own.
u32 keyword_len = syntax_keyword_len(LANG_CONFIG, line, i, line_len);
diff --git a/ted.cfg b/ted.cfg
index bad356e..87b1c95 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -94,6 +94,22 @@ Ctrl+Shift+s = :save-as
Ctrl+q = :quit
Ctrl+Shift+r = :reload-all
+# You can do something like this:
+# Ctrl+Alt+t = 3 :set-language
+# to set the language of the current buffer to Rust, for example. This might be useful if
+# one file extension could be multiple different languages.
+# Here are the numbers corresponding to each language we have syntax highlighting for:
+# 0 Plain text (no syntax highlighting)
+# 1 C
+# 2 C++
+# 3 Rust
+# 4 Python
+# 5 TeX
+# 6 Markdown
+# 7 HTML
+# 8 Config (e.g. ted.cfg)
+# -1 Guess from the file extension (default)
+
Ctrl+Space = :autocomplete
# go to previous completion
Ctrl+Shift+Space = :autocomplete-back
@@ -209,5 +225,5 @@ Rust = .rs
Python = .py
Tex = .tex
Markdown = .md
-HTML = .html, .php
+HTML = .html, .php, .xml, .xhtml
Config = .cfg
diff --git a/ted.h b/ted.h
index e08f222..941508f 100644
--- a/ted.h
+++ b/ted.h
@@ -43,16 +43,18 @@ enum {
typedef u8 SyntaxState;
+// If you are adding new languages, DO NOT change the constant values
+// of the previous languages. It will mess up config files!
ENUM_U16 {
- LANG_NONE,
- LANG_C,
- LANG_CPP,
- LANG_RUST,
- LANG_PYTHON,
- LANG_TEX,
- LANG_MARKDOWN,
- LANG_HTML,
- LANG_CONFIG, // .cfg files, e.g. ted.cfg
+ LANG_NONE = 0,
+ LANG_C = 1,
+ LANG_CPP = 2,
+ LANG_RUST = 3,
+ LANG_PYTHON = 4,
+ LANG_TEX = 5,
+ LANG_MARKDOWN = 6,
+ LANG_HTML = 7,
+ LANG_CONFIG = 8, // .cfg files, e.g. ted.cfg
LANG_COUNT
} ENUM_U16_END(Language);
@@ -159,6 +161,7 @@ typedef struct {
struct Ted *ted; // we keep a back-pointer to the ted instance so we don't have to pass it in to every buffer function
double scroll_x, scroll_y; // number of characters scrolled in the x/y direction
struct timespec last_write_time; // last write time to filename.
+ i16 manual_language; // 1 + the language the buffer has been manually set to, or 0 if it hasn't been manually set to anything
BufferPos cursor_pos;
BufferPos selection_pos; // if selection is true, the text between selection_pos and cursor_pos is selected.
bool is_line_buffer; // "line buffers" are buffers which can only have one line of text (used for inputs)
diff --git a/ui.c b/ui.c
index 0b6a0a0..993a51f 100644
--- a/ui.c
+++ b/ui.c
@@ -56,6 +56,16 @@ static void selector_down(Ted const *ted, Selector *s, i64 n) {
selector_up(ted, s, -n);
}
+static int selectory_entry_cmp_name(void const *av, void const *bv) {
+ SelectorEntry const *a = av, *b = bv;
+ return strcmp(a->name, b->name);
+}
+
+// sort entries alphabetically
+static void selector_sort_entries_by_name(Selector *s) {
+ qsort(s->entries, s->n_entries, sizeof *s->entries, selectory_entry_cmp_name);
+}
+
// returns a null-terminated UTF-8 string of the option selected, or NULL if none was.
// you should call free() on the return value.
static char *selector_update(Ted *ted, Selector *s) {