summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buffer.c156
-rw-r--r--command.c9
-rw-r--r--command.h3
-rw-r--r--control2
-rw-r--r--main.c1
-rw-r--r--ted.cfg30
-rw-r--r--ted.h6
7 files changed, 205 insertions, 2 deletions
diff --git a/buffer.c b/buffer.c
index c440ed4..898dd07 100644
--- a/buffer.c
+++ b/buffer.c
@@ -1791,6 +1791,153 @@ static void buffer_shorten_line(Line *line, u32 new_len) {
line->len = new_len; // @TODO(optimization,memory): decrease line capacity
}
+// returns -1 if c is not a digit of base
+static int base_digit(char c, int base) {
+ int value = -1;
+ if (c >= '0' && c <= '9') {
+ value = c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ value = c - 'a' + 10;
+ } else if (c >= 'A' && c <= 'F') {
+ value = c - 'A' + 10;
+ }
+ return value >= base ? -1 : value;
+}
+
+// e.g. returns "0x1b" for num = "0x1a", by = 1
+// turns out it's surprisingly difficult to handle all cases
+static char *change_number(const char *num, i64 by) {
+ if (!isdigit(*num) && *num != '-') {
+ return NULL;
+ }
+
+ bool negative = *num == '-';
+ if (negative) ++num;
+
+ int start = 0;
+ int base = 10;
+ if (num[0] == '0') {
+ switch (num[1]) {
+ case '\0':
+ start = 0;
+ break;
+ case 'x':
+ case 'X':
+ start = 2;
+ base = 16;
+ break;
+ case 'o':
+ case 'O':
+ start = 2;
+ base = 8;
+ break;
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
+ start = 1;
+ base = 8;
+ break;
+ case 'b':
+ case 'B':
+ // not handling binary yet since sprintf doesnt have binary gah
+ return NULL;
+ default:
+ return NULL;
+ }
+ }
+
+ // find end of number
+ int end;
+ for (end = start + 1; base_digit(num[end], base) != -1; ++end);
+
+ if (base_digit(num[end], 16) != -1) {
+ // we're probably wrong about the base. let's not do anything.
+ return NULL;
+ }
+
+ if (num[end] != '\0'
+ && !isalnum(num[end]) // number suffixes e.g. 0xffu
+ ) {
+ // probably not a number.
+ // at least not one we understand.
+ return NULL;
+ }
+
+ bool uppercase = false;
+ for (int i = 0; i < end; ++i)
+ if (isupper(num[i]))
+ uppercase = true;
+
+ long long number = strtoll(&num[start], NULL, base);
+ if (number == LLONG_MIN || number == LLONG_MAX)
+ return NULL;
+ if (negative) number = -number;
+ // overflow checks
+ if (by > 0 && number > LLONG_MAX - by)
+ return NULL;
+ if (by < 0 && number <= LLONG_MIN - by)
+ return NULL;
+ number += by;
+ printf("%lld\n",number);
+ negative = number < 0;
+ if (negative) number = -number;
+
+ char new_number[128] = {0};
+ switch (uppercase * 1000 + base) {
+ case 1010: case 10: sprintf(new_number, "%lld", number); break;
+ case 1008: case 8: sprintf(new_number, "%llo", number); break;
+ case 1016: sprintf(new_number, "%llX", number); break;
+ case 16: sprintf(new_number, "%llx", number); break;
+ }
+
+ size_t capacity = strlen(num) + 128;
+ char *changed = calloc(1, capacity);
+ printf("%s %.*s %s %s\n",negative ? "-" : "", start, num, new_number, &num[end]);
+ str_printf(changed, capacity, "%s%.*s%s%s", negative ? "-" : "", start, num, new_number, &num[end]);
+ return changed;
+
+}
+
+void buffer_change_number_at_cursor(TextBuffer *buffer, i64 by) {
+ BufferPos pos = buffer->cursor_pos;
+
+ // move to start of number
+ if (is32_alnum(buffer_char_before_pos(buffer, pos))) {
+ buffer_pos_move_left_words(buffer, &pos, 1);
+ }
+ char32_t c = buffer_char_after_pos(buffer, pos);
+ if (c >= 127 || !isdigit((char)c)) {
+ if (c != '-') {
+ // not a number
+ return;
+ }
+ }
+
+ BufferPos end = pos;
+ if (c == '-') {
+ buffer_pos_move_right(buffer, &end, 1);
+ }
+ buffer_pos_move_right_words(buffer, &end, 1);
+ if (buffer_char_at_pos(buffer, end) == '.') {
+ // floating-point number. dont try to increment it
+ return;
+ }
+
+ if (buffer_char_before_pos(buffer, pos) == '-') {
+ // include negative sign
+ buffer_pos_move_left(buffer, &pos, 1);
+ }
+
+ u32 nchars = (u32)buffer_pos_diff(buffer, pos, end);
+ char *word = buffer_get_utf8_text_at_pos(buffer, pos, nchars);
+ char *newnum = change_number(word, by);
+ if (newnum) {
+ buffer_delete_chars_between(buffer, pos, end);
+ buffer_insert_utf8_at_pos(buffer, pos, newnum);
+ buffer_cursor_move_to_pos(buffer, pos);
+ free(newnum);
+ }
+ free(word);
+}
+
// decrease the number of lines in the buffer.
// DOES NOT DO ANYTHING TO THE LINES REMOVED! YOU NEED TO FREE THEM YOURSELF!
static void buffer_shorten(TextBuffer *buffer, u32 new_nlines) {
@@ -2013,6 +2160,15 @@ void buffer_insert_char_at_cursor(TextBuffer *buffer, char32_t c) {
buffer_insert_text_at_cursor(buffer, s);
}
+
+void buffer_insert_utf8_at_pos(TextBuffer *buffer, BufferPos pos, const char *utf8) {
+ String32 s32 = str32_from_utf8(utf8);
+ if (s32.str) {
+ buffer_insert_text_at_pos(buffer, pos, s32);
+ str32_free(&s32);
+ }
+}
+
void buffer_insert_utf8_at_cursor(TextBuffer *buffer, const char *utf8) {
String32 s32 = str32_from_utf8(utf8);
if (s32.str) {
diff --git a/command.c b/command.c
index 168597a..ed42e87 100644
--- a/command.c
+++ b/command.c
@@ -100,6 +100,8 @@ static CommandName command_names[] = {
{"macro-record", CMD_MACRO_RECORD},
{"macro-stop", CMD_MACRO_STOP},
{"macro-execute", CMD_MACRO_EXECUTE},
+ {"increment-number", CMD_INCREMENT_NUMBER},
+ {"decrement-number", CMD_DECREMENT_NUMBER},
};
static_assert_if_possible(arr_count(command_names) == CMD_COUNT)
@@ -177,6 +179,13 @@ void command_execute_ex(Ted *ted, Command c, CommandArgument full_argument, Comm
case CMD_NOOP:
break;
+ case CMD_INCREMENT_NUMBER:
+ buffer_change_number_at_cursor(buffer, argument);
+ break;
+ case CMD_DECREMENT_NUMBER:
+ buffer_change_number_at_cursor(buffer, -argument);
+ break;
+
case CMD_LEFT:
if (buffer) buffer_cursor_move_left(buffer, argument);
autocomplete_close(ted);
diff --git a/command.h b/command.h
index a246439..408bfbe 100644
--- a/command.h
+++ b/command.h
@@ -77,6 +77,9 @@ typedef enum {
CMD_DELETE,
CMD_BACKSPACE_WORD,
CMD_DELETE_WORD,
+
+ CMD_INCREMENT_NUMBER,
+ CMD_DECREMENT_NUMBER,
/// open a file
CMD_OPEN,
diff --git a/control b/control
index a44bba7..0eae890 100644
--- a/control
+++ b/control
@@ -1,5 +1,5 @@
Package: ted
-Version: 2.1r1
+Version: 2.2
Section: text
Priority: optional
Architecture: amd64
diff --git a/main.c b/main.c
index b13a7a3..9e9f1c2 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,6 @@
/*
- ctrl+9/0 to inc/dec number
+- handle leading zeroes
FUTURE FEATURES:
- better undo chaining (dechain on backspace?)
- font setting & support for multiple fonts to cover more characters
diff --git a/ted.cfg b/ted.cfg
index 95f6d33..592cfb4 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -300,6 +300,9 @@ Ctrl+x = :cut
Ctrl+v = :paste
Ctrl+Shift+p = :command-selector
+Ctrl+9 = :decrement-number
+Ctrl+0 = :increment-number
+
# tabs
Ctrl+w = :tab-close
Ctrl+PageUp = :tab-prev
@@ -354,6 +357,33 @@ Ctrl+Shift+tab = :split-swap
Escape = :escape
+# keyboard macros
+Ctrl+F1 = 1 :macro-record
+Ctrl+F2 = 2 :macro-record
+Ctrl+F3 = 3 :macro-record
+Ctrl+F4 = 4 :macro-record
+Ctrl+F5 = 5 :macro-record
+Ctrl+F6 = 6 :macro-record
+Ctrl+F7 = 7 :macro-record
+Ctrl+F8 = 8 :macro-record
+Ctrl+F9 = 9 :macro-record
+Ctrl+F10 = 10 :macro-record
+Ctrl+F11 = 11 :macro-record
+Ctrl+F12 = 12 :macro-record
+
+Shift+F1 = 1 :macro-execute
+Shift+F2 = 2 :macro-execute
+Shift+F3 = 3 :macro-execute
+Shift+F4 = 4 :macro-execute
+Shift+F5 = 5 :macro-execute
+Shift+F6 = 6 :macro-execute
+Shift+F7 = 7 :macro-execute
+Shift+F8 = 8 :macro-execute
+Shift+F9 = 9 :macro-execute
+Shift+F10 = 10 :macro-execute
+Shift+F11 = 11 :macro-execute
+Shift+F12 = 12 :macro-execute
+
[extensions]
# text is the default if the extension doesn't match any of the ones below
Text = .txt
diff --git a/ted.h b/ted.h
index 7dc9602..94660ff 100644
--- a/ted.h
+++ b/ted.h
@@ -28,7 +28,7 @@ extern "C" {
#include "sdl-inc.h"
/// Version number
-#define TED_VERSION "2.1r1"
+#define TED_VERSION "2.2"
/// Version string
#define TED_VERSION_FULL "ted v. " TED_VERSION
/// Maximum path size ted handles.
@@ -1043,6 +1043,8 @@ String32 buffer_word_at_cursor(TextBuffer *buffer);
/// Get a UTF-8 string consisting of the word at the cursor.
/// The return value should be freed.
char *buffer_word_at_cursor_utf8(TextBuffer *buffer);
+/// Used for CMD_INCREMENT_NUMBER/CMD_DECREMENT_NUMBER
+void buffer_change_number_at_cursor(TextBuffer *buffer, i64 argument);
/// Buffer position corresponding to the start of line `line` (0-indexed).
BufferPos buffer_pos_start_of_line(TextBuffer *buffer, u32 line);
/// Buffer position corresponding to the end of line `line` (0-indexed).
@@ -1127,6 +1129,8 @@ i64 buffer_delete_selection(TextBuffer *buffer);
void buffer_insert_text_at_cursor(TextBuffer *buffer, String32 str);
/// Insert a single character at the cursor, and move the cursor past it.
void buffer_insert_char_at_cursor(TextBuffer *buffer, char32_t c);
+/// Insert UTF-8 text at the position.
+void buffer_insert_utf8_at_pos(TextBuffer *buffer, BufferPos pos, const char *utf8);
/// Insert UTF-8 text at the cursor, and move the cursor to the end of it.
void buffer_insert_utf8_at_cursor(TextBuffer *buffer, const char *utf8);
/// Insert a "tab" at the cursor position, and move the cursor past it.