Introduction
Introduction Statistics Contact Development Disclaimer Help
tAdd basic uppercase/lowercase support - ledit - Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
Log
Files
Refs
README
LICENSE
---
commit 4ee5ad27da617738b33a8e5e46aa75afcc2e54d0
parent a3b601c93fde71dd598f855980897a1e3ead492e
Author: lumidify <[email protected]>
Date: Thu, 5 Oct 2023 12:10:03 +0200
Add basic uppercase/lowercase support
Diffstat:
M Makefile | 8 ++++++--
M README | 9 ++++++---
M keys_basic.c | 99 ++++++++++++++++++++++++++++-…
M leditrc.5 | 13 ++++++++++++-
M leditrc.example | 2 ++
5 files changed, 118 insertions(+), 13 deletions(-)
---
diff --git a/Makefile b/Makefile
t@@ -13,6 +13,7 @@ MISCFILES = Makefile README LICENSE IDEAS NOTES TODO
DEBUG=0
SANITIZE=0
+ENABLE_UTF8PROC=1
OBJ = \
assert.o \
t@@ -70,12 +71,15 @@ EXTRA_CFLAGS_DEBUG0 = ${CFLAGS}
EXTRA_LDFLAGS_DEBUG0 = ${LDFLAGS}
EXTRA_CFLAGS_DEBUG1 = -DLEDIT_DEBUG -g
EXTRA_FLAGS_SANITIZE1 = -fsanitize=address
+EXTRA_CFLAGS_UTF8PROC0 = -DENABLE_UTF8PROC=0
+EXTRA_CFLAGS_UTF8PROC1 = `pkg-config --cflags libutf8proc` -DENABLE_UTF8PROC=1
+EXTRA_LDFLAGS_UTF8PROC1 = `pkg-config --libs libutf8proc`
# Xcursor isn't actually needed right now since I'm not using the drag 'n drop…
# of ctrlsel yet, but since it's moderately likely that I will use that in the…
# decided to just leave it in.
-CFLAGS_LEDIT = ${EXTRA_FLAGS_SANITIZE${SANITIZE}} ${EXTRA_CFLAGS_DEBUG${DEBUG}…
-LDFLAGS_LEDIT = ${EXTRA_FLAGS_SANITIZE${SANITIZE}} ${EXTRA_LDFLAGS_DEBUG${DEBU…
+CFLAGS_LEDIT = ${EXTRA_FLAGS_SANITIZE${SANITIZE}} ${EXTRA_CFLAGS_DEBUG${DEBUG}…
+LDFLAGS_LEDIT = ${EXTRA_FLAGS_SANITIZE${SANITIZE}} ${EXTRA_LDFLAGS_DEBUG${DEBU…
all: ${BIN}
diff --git a/README b/README
t@@ -8,15 +8,18 @@ layout.
Additionally, it allows multiple views on a text buffer so that different
parts of a file can be shown at the same time.
-REQUIREMENTS: pango (with xft), xlib (extensions: xkb, xdbe), xcursor
+REQUIREMENTS:
+pango (with xft), xlib (extensions: xkb, xdbe),
+xcursor, libutf8proc (if ENABLE_UTF8PROC is set)
Note: xcursor technically wouldn't be needed since it's just a dependency
of features in ctrlsel that currently aren't being used, but I will
probably use those features later, so I was too lazy to remove those parts.
Packages to install:
-On OpenBSD: pango
-On MX Linux: libpango1.0-dev, libx11-dev, libxkbfile-dev libxcursor-dev
+On OpenBSD: pango, libutf8proc
+On Debian-based systems:
+libpango1.0-dev, libx11-dev, libxkbfile-dev libxcursor-dev, libutf8proc-dev
(this is just from memory, I need to test it with a fresh system sometime)
Installation:
diff --git a/keys_basic.c b/keys_basic.c
t@@ -17,6 +17,7 @@
/* FIXME: sort functions a bit better, maybe split file */
/* FIXME: documentation */
#include <stdio.h>
+#include <ctype.h>
#include <stdlib.h>
#include <X11/Xlib.h>
t@@ -27,6 +28,10 @@
#include <X11/XF86keysym.h>
#include <X11/cursorfont.h>
+#if ENABLE_UTF8PROC
+#include "utf8proc.h"
+#endif
+
#include "util.h"
#include "assert.h"
#include "memory.h"
t@@ -121,6 +126,8 @@ static struct action delete_graphemes_forwards_multiline(l…
static struct action delete_graphemes_backwards_multiline(ledit_view *view, ch…
static struct action yank(ledit_view *view, char *text, size_t len);
static struct action yank_lines(ledit_view *view, char *text, size_t len);
+static struct action uppercase(ledit_view *view, char *text, size_t len);
+static struct action lowercase(ledit_view *view, char *text, size_t len);
static struct action replace(ledit_view *view, char *text, size_t len);
static struct action cursor_to_first_non_ws(ledit_view *view, char *text, size…
static struct action join_lines(ledit_view *view, char *text, size_t len);
t@@ -160,6 +167,7 @@ static struct basic_key_cb basic_key_cb_map[] = {
{"append-after-eol", &append_after_eol, KEY_FLAG_JUMP_TO_CURSOR, NORMA…
{"append-line-above", &append_line_above, KEY_FLAG_JUMP_TO_CURSOR, NOR…
{"append-line-below", &append_line_below, KEY_FLAG_JUMP_TO_CURSOR, NOR…
+ {"break-line", &break_line, KEY_FLAG_JUMP_TO_CURSOR, NORMAL|INSERT},
{"change", &change, KEY_FLAG_JUMP_TO_CURSOR, NORMAL|VISUAL|INSERT},
{"change-to-eol", &change_to_eol, KEY_FLAG_JUMP_TO_CURSOR, NORMAL},
{"clipboard-copy", &clipcopy, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG_LOCK_AL…
t@@ -185,17 +193,17 @@ static struct basic_key_cb basic_key_cb_map[] = {
{"enter-searchedit-backwards", &enter_searchedit_backward, KEY_FLAG_NO…
{"enter-searchedit-forwards", &enter_searchedit_forward, KEY_FLAG_NONE…
{"enter-visual", &enter_visual, KEY_FLAG_JUMP_TO_CURSOR, NORMAL|INSERT…
- {"return-to-normal", &return_to_normal, KEY_FLAG_JUMP_TO_CURSOR|KEY_FL…
{"find-char-backwards", &find_char_backwards, KEY_FLAG_JUMP_TO_CURSOR|…
{"find-char-forwards", &find_char_forwards, KEY_FLAG_JUMP_TO_CURSOR|KE…
{"find-next-char-backwards", &find_next_char_backwards, KEY_FLAG_JUMP_…
{"find-next-char-forwards", &find_next_char_forwards, KEY_FLAG_JUMP_TO…
{"insert-at-beginning", &insert_at_beginning, KEY_FLAG_JUMP_TO_CURSOR,…
+ {"insert-mark", &insert_mark, KEY_FLAG_NONE|KEY_FLAG_LOCK_ALLOWED, NOR…
{"insert-text", &insert_mode_insert_text, KEY_FLAG_JUMP_TO_CURSOR, INS…
{"join-lines", &join_lines, KEY_FLAG_JUMP_TO_CURSOR, NORMAL|INSERT},
{"jump-to-mark", &jump_to_mark, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG_LOCK_…
{"key-0", &key_0, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG_LOCK_ALLOWED, NORMA…
- {"insert-mark", &insert_mark, KEY_FLAG_NONE|KEY_FLAG_LOCK_ALLOWED, NOR…
+ {"lowercase", &lowercase, KEY_FLAG_JUMP_TO_CURSOR, NORMAL|INSERT},
{"move-to-eol", &move_to_eol, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG_LOCK_AL…
{"move-to-line", &move_to_line, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG_LOCK_…
{"next-bigword", &next_bigword, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG_LOCK_…
t@@ -219,7 +227,7 @@ static struct basic_key_cb basic_key_cb_map[] = {
{"redo", &redo, KEY_FLAG_JUMP_TO_CURSOR, NORMAL|INSERT},
{"repeat-command", &repeat_command, KEY_FLAG_JUMP_TO_CURSOR, NORMAL},
{"replace", &replace, KEY_FLAG_JUMP_TO_CURSOR, NORMAL},
- {"break-line", &break_line, KEY_FLAG_JUMP_TO_CURSOR, NORMAL|INSERT},
+ {"return-to-normal", &return_to_normal, KEY_FLAG_JUMP_TO_CURSOR|KEY_FL…
{"screen-down", &screen_down, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG_LOCK_AL…
{"screen-up", &screen_up, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG_LOCK_ALLOWE…
{"scroll-lines-down", &scroll_lines_down, KEY_FLAG_JUMP_TO_CURSOR|KEY_…
t@@ -232,6 +240,7 @@ static struct basic_key_cb basic_key_cb_map[] = {
{"switch-selection-end", &switch_selection_end, KEY_FLAG_JUMP_TO_CURSO…
{"toggle-hard-line-based", &toggle_hard_line_based, KEY_FLAG_NONE|KEY_…
{"undo", &undo, KEY_FLAG_JUMP_TO_CURSOR, NORMAL|INSERT},
+ {"uppercase", &uppercase, KEY_FLAG_JUMP_TO_CURSOR, NORMAL|INSERT},
{"yank", &yank, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG_LOCK_ALLOWED, NORMAL|…
{"yank-lines", &yank_lines, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG_LOCK_ALLO…
};
t@@ -2495,6 +2504,80 @@ GEN_MOVE_TO_CHAR(
)
static struct action
+loweruppercase(ledit_view *view, int upper) {
+ /* FIXME: shouldn't CHECK_VIEW_LOCKED be in a lot more places? */
+ CHECK_VIEW_LOCKED(view);
+ /* FIXME: move most of this to convenience functions in buffer.c */
+ ledit_line *line = buffer_get_line(view->buffer, view->cur_line);
+ if (view->cur_index >= line->len)
+ return (struct action){ACTION_NONE, NULL};
+ buffer_normalize_line(line);
+ size_t start_index = view->cur_index;
+#if ENABLE_UTF8PROC
+ utf8proc_int32_t c;
+ /* FIXME: this cast to utf8proc_uint8_t probably doesn't break anythin…
+ utf8proc_ssize_t origlen = utf8proc_iterate((utf8proc_uint8_t *)line->…
+ /* FIXME: show error message? */
+ if (c < 0 || origlen < 1)
+ return (struct action){ACTION_NONE, NULL};
+ utf8proc_int32_t u;
+ if (upper)
+ u = utf8proc_toupper(c);
+ else
+ u = utf8proc_tolower(c);
+ utf8proc_uint8_t u8[4];
+ utf8proc_ssize_t newlen = utf8proc_encode_char(u, u8);
+ if (newlen < 1)
+ return (struct action){ACTION_NONE, NULL};
+ delete_range(
+ view, 0, 0,
+ view->cur_line, start_index, view->cur_line, start_index + origlen…
+ );
+ insert_text(
+ view, view->cur_line, start_index, (char *)u8, newlen,
+ view->cur_line, start_index, view->cur_line, start_index, 1, 1, 0
+ );
+#else
+ char c;
+ if (upper)
+ c = toupper((unsigned char)line->text[view->cur_index]);
+ else
+ c = tolower((unsigned char)line->text[view->cur_index]);
+ delete_range(
+ view, 0, 0,
+ view->cur_line, start_index, view->cur_line, start_index + 1, 0
+ );
+ insert_text(
+ view, view->cur_line, start_index, &c, 1,
+ view->cur_line, start_index, view->cur_line, start_index, 1, 1, 0
+ );
+#endif
+ /* If the last character on a line is replaced, the cursor would jump
+ backwards due to the deletion, so it has to be set to the original
+ position again */
+ view->cur_index = start_index;
+ push_undo_empty_insert(view, view->cur_line, view->cur_index, 0);
+ if (view->mode == NORMAL)
+ view_set_line_cursor_attrs(view, view->cur_line, view->cur_ind…
+ finalize_repetition_stack();
+ return (struct action){ACTION_NONE, NULL};
+}
+
+static struct action
+uppercase(ledit_view *view, char *text, size_t len) {
+ (void)text;
+ (void)len;
+ return loweruppercase(view, 1);
+}
+
+static struct action
+lowercase(ledit_view *view, char *text, size_t len) {
+ (void)text;
+ (void)len;
+ return loweruppercase(view, 0);
+}
+
+static struct action
replace_cb(ledit_view *view, char *text, size_t len) {
CHECK_VIEW_LOCKED(view);
size_t start_index = view->cur_index;
t@@ -2512,11 +2595,13 @@ replace_cb(ledit_view *view, char *text, size_t len) {
view, view->cur_line, start_index, text, len,
view->cur_line, start_index, view->cur_line, start_index, 1, 1, 0
);
- /* this should not be necessary, but just in case */
- view->cur_index = view_get_legal_normal_pos(
- view, view->cur_line, view->cur_index
- );
+ /* If the last character on a line is replaced, the cursor would jump
+ backwards due to the deletion, so it has to be set to the original
+ position again */
+ view->cur_index = start_index;
push_undo_empty_insert(view, view->cur_line, view->cur_index, 0);
+ if (view->mode == NORMAL)
+ view_set_line_cursor_attrs(view, view->cur_line, view->cur_ind…
grab_char_cb = NULL;
finalize_repetition_stack();
return (struct action){ACTION_NONE, NULL};
diff --git a/leditrc.5 b/leditrc.5
t@@ -1,4 +1,4 @@
-.Dd October 2, 2023
+.Dd October 5, 2023
.Dt LEDITRC 5
.Os
.Sh NAME
t@@ -674,6 +674,17 @@ write, and current line number.
Switch the end of the selection that can be moved.
.It Ar toggle-hard-line-based Op normal, visual, insert
Toggle the line mode between hardline and softline.
+.It Ar uppercase Op normal, insert
+.It Ar lowercase Op normal, insert
+Replace the character at the current cursor position with the uppercase/lowerc…
+If utf8proc support is not enabled, this will use the standard C library funct…
+.Fn toupper
+and
+.Fn tolower ,
+so it will not work with most Unicode characters.
+Note that even with utf8proc, it will not work in all cases because some chara…
+more complex handling (e.g. characters that require multiple characters when c…
+uppercase), which is not supported.
.It Ar undo Oo normal, insert Oc Oo num Oc
Undo
.Ar num
diff --git a/leditrc.example b/leditrc.example
t@@ -107,6 +107,8 @@ bindings = {
bind find-next-char-backwards text "T" modes normal|visual
bind find-char-forwards text "f" modes normal|visual
bind find-char-backwards text "F" modes normal|visual
+ bind uppercase text "U" modes normal|insert mods control
+ bind lowercase text "L" modes normal|insert mods control
bind insert-text catchall modes insert
}
command-keys = {
You are viewing proxied material from lumidify.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.