diff --git a/src/dged/keyboard.c b/src/dged/keyboard.c index 1e28066..26eb308 100644 --- a/src/dged/keyboard.c +++ b/src/dged/keyboard.c @@ -31,15 +31,19 @@ struct keyboard keyboard_create_fd(struct reactor *reactor, int fd) { void parse_keys(uint8_t *bytes, uint32_t nbytes, struct key *out_keys, uint32_t *out_nkeys) { - // TODO: can be optimized if "bytes" contains no special chars uint32_t nkps = 0; for (uint32_t bytei = 0; bytei < nbytes; ++bytei) { uint8_t b = bytes[bytei]; bool has_more = bytei + 1 < nbytes; uint8_t next = has_more ? bytes[bytei + 1] : 0; + struct key *prev_kp = nkps > 0 ? &out_keys[nkps - 1] : NULL; struct key *kp = &out_keys[nkps]; if (b == 0x1b) { // meta + // meta key is special since it records as its own + // key press so only set some state of the key press + // and do not advance to the next since it is + // not done yet kp->start = bytei; kp->mod = Meta; } else if (has_more && isalnum(next) && kp->mod & Meta && @@ -47,6 +51,7 @@ void parse_keys(uint8_t *bytes, uint32_t nbytes, struct key *out_keys, b == '0')) { // special char (function keys, pgdn, etc) kp->mod = Spec; } else if (b == 0x7f) { // ? + // For some reason, delete is not a control char kp->mod |= Ctrl; kp->key = '?'; kp->start = bytei; @@ -59,31 +64,35 @@ void parse_keys(uint8_t *bytes, uint32_t nbytes, struct key *out_keys, kp->end = bytei + 1; ++nkps; } else { - if (kp->mod & Spec && b == '~') { + if ((kp->mod & Spec) && b == '~') { // skip tilde in special chars kp->end = bytei + 1; ++nkps; - } else if (kp->mod & Meta || kp->mod & Spec) { + } else if ((kp->mod & Meta) || (kp->mod & Spec)) { + // handle the key press following meta or spec. kp->key = b; kp->end = bytei + 1; - if (kp->mod & Meta || (kp->mod & Spec && next != '~')) { ++nkps; } } else if (utf8_byte_is_unicode_continuation(b)) { // do nothing for these - } else if (utf8_byte_is_unicode_start(b)) { // unicode char - kp->mod = None; - kp->key = 0; - kp->start = bytei; - kp->end = bytei + utf8_nbytes(bytes + bytei, nbytes - bytei, 1); - ++nkps; - } else { // normal ASCII char - kp->mod = None; - kp->key = b; - kp->start = bytei; - kp->end = bytei + 1; - ++nkps; + } else { // ascii char or unicode start byte (self-inserting) + uint32_t nb = utf8_byte_is_unicode_start(b) + ? utf8_nbytes(bytes + bytei, nbytes - bytei, 1) + : 1; + + // "compress" number of keys if previous key was also a + // "simple" key + if (prev_kp != NULL && prev_kp->mod == None) { + prev_kp->end += nb; + } else { + kp->mod = None; + kp->key = b; + kp->start = bytei; + kp->end = bytei + nb; + ++nkps; + } } } } diff --git a/src/dged/syntax.c b/src/dged/syntax.c index f5c80d5..8d0fd1a 100644 --- a/src/dged/syntax.c +++ b/src/dged/syntax.c @@ -20,6 +20,7 @@ #include "s8.h" #include "settings.h" #include "text.h" +#include "timers.h" #include "vec.h" static char *treesitter_path[256] = {0}; @@ -481,6 +482,7 @@ static void buffer_reloaded(struct buffer *buffer, void *userdata) { static void text_inserted(struct buffer *buffer, struct region inserted, uint32_t begin_idx, uint32_t end_idx, void *userdata) { + struct timer *text_inserted = timer_start("syntax.txt-inserted"); struct highlight *h = (struct highlight *)userdata; TSPoint begin = {.row = inserted.begin.line, @@ -512,6 +514,8 @@ static void text_inserted(struct buffer *buffer, struct region inserted, ts_tree_delete(h->tree); h->tree = new_tree; } + + timer_stop(text_inserted); } static void create_parser(struct buffer *buffer, void *userdata) { diff --git a/src/dged/timers.c b/src/dged/timers.c index 37ac367..798c003 100644 --- a/src/dged/timers.c +++ b/src/dged/timers.c @@ -10,6 +10,8 @@ struct timer { char name[32]; + uint64_t max; + uint64_t min; uint64_t samples[NUM_FRAME_SAMPLES]; struct timespec started_at; }; @@ -50,7 +52,8 @@ struct timer *timer_start(const char *name) { namelen = namelen >= 32 ? 31 : namelen; memcpy(new_timer->name, name, namelen); new_timer->name[namelen] = '\0'; - + new_timer->max = 0; + new_timer->min = (uint64_t)-1; memset(new_timer->samples, 0, sizeof(uint64_t) * NUM_FRAME_SAMPLES); t = new_timer; @@ -60,14 +63,23 @@ struct timer *timer_start(const char *name) { return t; } -void timer_stop(struct timer *timer) { +uint64_t timer_stop(struct timer *timer) { struct timespec end; clock_gettime(CLOCK_MONOTONIC, &end); uint64_t elapsed = ((uint64_t)end.tv_sec * 1e9 + (uint64_t)end.tv_nsec) - ((uint64_t)timer->started_at.tv_sec * 1e9 + (uint64_t)timer->started_at.tv_nsec); + if (elapsed > timer->max) { + timer->max = elapsed; + } + + if (elapsed < timer->min) { + timer->min = elapsed; + } + timer->samples[g_timers.frame_index] += elapsed; + return elapsed; } struct timer *timer_get(const char *name) { @@ -82,9 +94,12 @@ float timer_average(const struct timer *timer) { } return (float)sum / NUM_FRAME_SAMPLES; - return 0.f; } +uint64_t timer_max(const struct timer *timer) { return timer->max; } + +uint64_t timer_min(const struct timer *timer) { return timer->min; } + const char *timer_name(const struct timer *timer) { return timer->name; } void timers_for_each(timer_callback callback, void *userdata) { diff --git a/src/dged/timers.h b/src/dged/timers.h index 4911b54..ae79a8b 100644 --- a/src/dged/timers.h +++ b/src/dged/timers.h @@ -1,15 +1,19 @@ #ifndef _TIMERS_H #define _TIMERS_H +#include + struct timer; void timers_init(); void timers_start_frame(); struct timer *timer_start(const char *name); -void timer_stop(struct timer *timer); +uint64_t timer_stop(struct timer *timer); struct timer *timer_get(const char *name); float timer_average(const struct timer *timer); +uint64_t timer_min(const struct timer *timer); +uint64_t timer_max(const struct timer *timer); const char *timer_name(const struct timer *timer); typedef void (*timer_callback)(const struct timer *timer, void *userdata); diff --git a/src/main/cmds.c b/src/main/cmds.c index 4dc84ed..04e42b4 100644 --- a/src/main/cmds.c +++ b/src/main/cmds.c @@ -189,7 +189,9 @@ void timer_to_list_line(const struct timer *timer, void *userdata) { const char *name = timer_name(timer); size_t namelen = strlen(name); size_t len = - snprintf(buf, 128, "%s - %.2f ms", name, (timer_average(timer) / 1e6)); + snprintf(buf, 128, "%s - %.2f ms (min: %.2f, max: %.2f)", name, + (timer_average(timer) / 1e6), timer_min(timer) / (float)1e6, + timer_max(timer) / (float)1e6); buffer_add(target, buffer_end(target), (uint8_t *)buf, len); } diff --git a/src/main/main.c b/src/main/main.c index 169716d..7dab26b 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -429,6 +429,7 @@ int main(int argc, char *argv[]) { } } } else if (k->mod == 0) { + // self-inserting chars buffer_view_add(window_buffer_view(active_window), &kbd_upd.raw[k->start], k->end - k->start); } else { @@ -453,6 +454,7 @@ int main(int argc, char *argv[]) { frame_time = timer_average(update_windows) + timer_average(update_keyboard) + timer_average(update_display); + timers_end_frame(); frame_allocator_clear(&frame_allocator); }