summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 12:50:54 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 12:50:54 +0300
commita0fefd3856a4f03be0abbc51f7a9a0416db69eb5 (patch)
treea06737c8fcea5ee6d7d20223e9c36272e66b9e26
parent71f0b19476adb170c24d6a8de4ab3133701b1aeb (diff)
Make term standalone library and export Meson dependencies
-rw-r--r--.gitignore6
-rw-r--r--LICENSE21
-rw-r--r--meson.build36
-rw-r--r--src/kernels.h2
-rw-r--r--src/meson.build5
-rw-r--r--src/text.c84
-rw-r--r--tests/extern/kitty/screen.py2
-rw-r--r--tests/meson.build6
8 files changed, 111 insertions, 51 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..90e08a6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+build*/
+.cache/
+*.o
+*.a
+*.so
+*.dylib
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..0d0ad12
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Berke Güzel
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/meson.build b/meson.build
index a78fa68..d23c0b4 100644
--- a/meson.build
+++ b/meson.build
@@ -1,8 +1,13 @@
project('term', 'c',
version: '0.1.0',
+ license: 'MIT',
+ license_files: 'LICENSE',
meson_version: '>=1.1.0',
default_options: [
'c_std=c11',
+ 'buildtype=release',
+ 'optimization=3',
+ 'b_lto=true',
'warning_level=3',
'b_ndebug=if-release',
],
@@ -23,7 +28,7 @@ subdir('src')
term_dep = declare_dependency(
include_directories: term_inc,
- link_with: term_headless_lib.get_static_lib(),
+ link_with: term_lib.get_static_lib(),
dependencies: m_dep,
)
meson.override_dependency('term', term_dep)
@@ -31,7 +36,7 @@ meson.override_dependency('term', term_dep)
# The private headers too. Only the term tests and benchmarks use it.
term_internal_dep = declare_dependency(
include_directories: [term_inc, term_private_inc],
- link_with: term_headless_lib.get_static_lib(),
+ link_with: term_lib.get_static_lib(),
dependencies: m_dep,
)
@@ -41,8 +46,35 @@ term_test_dep = declare_dependency(
include_directories: include_directories('tests/helpers'),
dependencies: term_dep,
)
+meson.override_dependency('term-test', term_test_dep)
+
+install_headers(
+ 'include/term/term.h',
+ 'include/term/term_input.h',
+ 'include/term/term_types.h',
+ subdir: 'term',
+)
+
+install_headers(
+ 'include/term/unicode/grapheme.h',
+ 'include/term/unicode/unicode.h',
+ 'include/term/unicode/unicode_data.inc',
+ 'include/term/unicode/utf8.h',
+ 'include/term/unicode/width.h',
+ subdir: 'term/unicode',
+)
+
+pkg = import('pkgconfig')
+pkg.generate(
+ term_lib.get_shared_lib(),
+ name: 'term',
+ description: 'Headless terminal emulator core library',
+ version: meson.project_version(),
+ subdirs: ['.', 'term'],
+)
if get_option('tests')
subdir('tests')
subdir('benchmarks')
endif
+
diff --git a/src/kernels.h b/src/kernels.h
index 48088b5..45d25b7 100644
--- a/src/kernels.h
+++ b/src/kernels.h
@@ -88,7 +88,7 @@ static inline size_t scan_printable_span(const char *buf, size_t len,
return scan_printable_span_avx512(buf, len, hi);
#endif
#if defined(TERM_KERNEL_AVX2)
- if (len >= 64 && term_use_avx2())
+ if (len >= 32 && term_use_avx2())
return scan_printable_span_avx2(buf, len, hi);
#endif
size_t i = 0;
diff --git a/src/meson.build b/src/meson.build
index 6eaf0d4..694ee0e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -2,7 +2,7 @@ subdir('osc')
# The x86-64 SIMD kernels pick their level at run time (see simd.h), so the
# library needs no ISA flags. -march in c_args sets the lowest level.
-term_headless_lib = both_libraries('term_headless',
+term_lib = both_libraries('term',
'core.c',
'escape.c',
'fastcsi.c',
@@ -23,5 +23,6 @@ term_headless_lib = both_libraries('term_headless',
include_directories: term_private_inc,
dependencies: [m_dep],
gnu_symbol_visibility: 'hidden',
- install: false
+ install: true
)
+
diff --git a/src/text.c b/src/text.c
index 9f73bd3..ad3e7f2 100644
--- a/src/text.c
+++ b/src/text.c
@@ -216,48 +216,6 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne
}
unsigned char ch = (unsigned char)buf[i];
- if ((ch < 0x20 || ch == 0x7f) && t->state == ST_GROUND)
- term_text_utf8_interrupt(t);
-
- if (TERM_EXPECT(ch < 0x20 && t->state == ST_GROUND &&
- ch != 0x1b && ch != '\n' && ch != '\r' && ch != '\b' && ch != '\t' &&
- ch != 0x0e && ch != 0x0f && ch != 0x07 && ch != 0x0b &&
- ch != 0x0c, 0)) {
- continue;
- }
-
- if (TERM_EXPECT(ch == 0x1b && t->state == ST_GROUND &&
- t->utf8_state == UTF8_ACCEPT && i + 1 < len &&
- buf[i + 1] == '[' && !t->insert_mode &&
- !t->lr_margin_mode && !t->graphics, 0)) {
- int fast = term_try_fast_csi(t, buf + i + 2, len - i - 2);
- if (fast > 0) {
- i += 1 + (size_t)fast;
- continue;
- }
- t->state = ST_CSI;
- csi_parser_reset(&t->csi_parser);
- i += 1 + term_escape_csi(t, buf + i + 2, len - i - 2);
- continue;
- }
-
- if (TERM_EXPECT(t->state == ST_GROUND && ch == '\n', 0)) {
- size_t end = i + 1 + scan_byte_run(buf + i + 1, len - i - 1, '\n');
- if (term_lnm(t)) sc_cr(t);
- sc_linefeed(t, end - i);
- i = end - 1;
- continue;
- }
-
- if (TERM_EXPECT(t->state == ST_GROUND && ch == '\r' &&
- i + 1 < len && buf[i + 1] == '\n', 0)) {
- size_t end = i + 2 + scan_crlf_pairs(buf + i + 2, len - i - 2);
- sc_cr(t);
- sc_linefeed(t, (end - i) / 2);
- i = end - 1;
- continue;
- }
-
if (TERM_EXPECT(ch >= 0x20 && ch < 0x7f && !t->insert_mode && !t->lr_margin_mode &&
t->state == ST_GROUND && !t->graphics &&
t->utf8_state == UTF8_ACCEPT, 1)) {
@@ -307,6 +265,48 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne
continue;
}
+ if ((ch < 0x20 || ch == 0x7f) && t->state == ST_GROUND)
+ term_text_utf8_interrupt(t);
+
+ if (TERM_EXPECT(ch < 0x20 && t->state == ST_GROUND &&
+ ch != 0x1b && ch != '\n' && ch != '\r' && ch != '\b' && ch != '\t' &&
+ ch != 0x0e && ch != 0x0f && ch != 0x07 && ch != 0x0b &&
+ ch != 0x0c, 0)) {
+ continue;
+ }
+
+ if (TERM_EXPECT(ch == 0x1b && t->state == ST_GROUND &&
+ t->utf8_state == UTF8_ACCEPT && i + 1 < len &&
+ buf[i + 1] == '[' && !t->insert_mode &&
+ !t->lr_margin_mode && !t->graphics, 0)) {
+ int fast = term_try_fast_csi(t, buf + i + 2, len - i - 2);
+ if (fast > 0) {
+ i += 1 + (size_t)fast;
+ continue;
+ }
+ t->state = ST_CSI;
+ csi_parser_reset(&t->csi_parser);
+ i += 1 + term_escape_csi(t, buf + i + 2, len - i - 2);
+ continue;
+ }
+
+ if (TERM_EXPECT(t->state == ST_GROUND && ch == '\n', 0)) {
+ size_t end = i + 1 + scan_byte_run(buf + i + 1, len - i - 1, '\n');
+ if (term_lnm(t)) sc_cr(t);
+ sc_linefeed(t, end - i);
+ i = end - 1;
+ continue;
+ }
+
+ if (TERM_EXPECT(t->state == ST_GROUND && ch == '\r' &&
+ i + 1 < len && buf[i + 1] == '\n', 0)) {
+ size_t end = i + 2 + scan_crlf_pairs(buf + i + 2, len - i - 2);
+ sc_cr(t);
+ sc_linefeed(t, (end - i) / 2);
+ i = end - 1;
+ continue;
+ }
+
if (TERM_EXPECT(ch == '\r' && t->state == ST_GROUND, 0)) {
sc_cr(t);
continue;
diff --git a/tests/extern/kitty/screen.py b/tests/extern/kitty/screen.py
index 80f8e71..cc7289b 100644
--- a/tests/extern/kitty/screen.py
+++ b/tests/extern/kitty/screen.py
@@ -13,7 +13,7 @@ import os
# Shared library loading
# ---------------------------------------------------------------------------
-_lib = ctypes.CDLL(os.environ.get('WSAP_KITTY_LIB', os.path.join(os.path.dirname(__file__), 'libterm.so')))
+_lib = ctypes.CDLL(os.environ.get('WSAP_KITTY_LIB', os.path.join(os.path.dirname(__file__), 'libkitty_bridge.so')))
# struct term_cell { uint32_t text, fg, bg; uint16_t attrs; uint8_t width, reserved; }
class TermCell(ctypes.Structure):
diff --git a/tests/meson.build b/tests/meson.build
index 0aa78e8..4cf559c 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -95,9 +95,9 @@ foreach entry : term_tests
endforeach
test('term-symbols-test', bash,
- args: [files('symbols_test.sh'), term_headless_lib.get_static_lib(),
+ args: [files('symbols_test.sh'), term_lib.get_static_lib(),
meson.project_source_root() / 'include' / 'term',
- term_headless_lib.get_shared_lib()],
+ term_lib.get_shared_lib()],
env: test_env,
suite: 'unit',
)
@@ -119,7 +119,7 @@ kitty_tests = get_option('kitty').require(
)
term_kitty_tests = kitty_tests.allowed()
if term_kitty_tests
- kitty_bridge = shared_library('term', 'extern/kitty/screen_bridge.c',
+ kitty_bridge = shared_library('kitty_bridge', 'extern/kitty/screen_bridge.c',
dependencies: term_internal_dep,
)
kitty_env = environment()