Skip to content

Commit 581db0a

Browse files
committed
Make kitty --version fast
It's now approx 3ms on my system and 1.23 times faster than alacritty --version
1 parent ad328bf commit 581db0a

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

kitty/data-types.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ get_docs_ref_map(PyObject *self UNUSED, PyObject *args UNUSED) {
249249

250250
static PyObject*
251251
wrapped_kittens(PyObject *self UNUSED, PyObject *args UNUSED) {
252-
const char *wrapped_kitten_names = WRAPPED_KITTENS;
252+
static const char *wrapped_kitten_names = WRAPPED_KITTENS;
253253
PyObject *ans = PyUnicode_FromString(wrapped_kitten_names);
254254
if (ans == NULL) return NULL;
255255
PyObject *s = PyUnicode_Split(ans, NULL, -1);

kitty/launcher/main.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,57 @@ delegate_to_kitten_if_possible(int argc, char *argv[], char* exe_dir) {
356356
if (argc > 3 && strcmp(argv[1], "+") == 0 && strcmp(argv[2], "kitten") == 0 && is_wrapped_kitten(argv[3])) exec_kitten(argc - 2, argv + 2, exe_dir);
357357
}
358358

359+
static bool
360+
is_boolean_flag(const char *x) {
361+
static const char *all_boolean_options = KITTY_CLI_BOOL_OPTIONS;
362+
char buf[128];
363+
snprintf(buf, sizeof(buf), " %s ", x);
364+
return strstr(all_boolean_options, buf) != NULL;
365+
}
366+
367+
static void
368+
handle_fast_commandline(int argc, char *argv[]) {
369+
char current_option_expecting_argument[128] = {0};
370+
bool version_requested = false;
371+
for (int i = 1; i < argc; i++) {
372+
const char *arg = argv[i];
373+
if (current_option_expecting_argument[0]) {
374+
current_option_expecting_argument[0] = 0;
375+
} else {
376+
if (!arg || !arg[0] || !arg[1] || arg[0] != '-' || strcmp(arg, "--") == 0) break;
377+
if (arg[1] == '-') { // long opt
378+
const char *equal = strchr(arg, '=');
379+
if (equal == NULL) {
380+
if (strcmp(arg+2, "version") == 0) {
381+
version_requested = true;
382+
} else if (!is_boolean_flag(arg+2)) {
383+
strncpy(current_option_expecting_argument, arg+2, sizeof(current_option_expecting_argument)-1);
384+
}
385+
}
386+
} else {
387+
char buf[2] = {0};
388+
for (int i = 1; arg[i] != 0; i++) {
389+
switch(arg[i]) {
390+
case 'v': version_requested = true; break;
391+
default:
392+
buf[0] = arg[i]; buf[1] = 0;
393+
if (!is_boolean_flag(buf)) { current_option_expecting_argument[0] = arg[i]; current_option_expecting_argument[1] = 0; }
394+
}
395+
}
396+
}
397+
}
398+
}
399+
400+
if (version_requested) {
401+
if (isatty(STDOUT_FILENO)) {
402+
printf("\x1b[3mkitty\x1b[23m \x1b[32m%s\x1b[39m created by \x1b[1;34mKovid Goyal\x1b[22;39m\n", KITTY_VERSION);
403+
} else {
404+
printf("kitty %s created by Kovid Goyal\n", KITTY_VERSION);
405+
}
406+
exit(0);
407+
}
408+
}
409+
359410
int main(int argc, char *argv[], char* envp[]) {
360411
if (argc < 1 || !argv) { fprintf(stderr, "Invalid argc/argv\n"); return 1; }
361412
if (!ensure_working_stdio()) return 1;
@@ -370,6 +421,7 @@ int main(int argc, char *argv[], char* envp[]) {
370421
strncpy(exe_dir_buf, exe, sizeof(exe_dir_buf));
371422
char *exe_dir = dirname(exe_dir_buf);
372423
delegate_to_kitten_if_possible(argc, argv, exe_dir);
424+
handle_fast_commandline(argc, argv);
373425
int num, ret=0;
374426
char lib[PATH_MAX+1] = {0};
375427
if (KITTY_LIB_PATH[0] == '/') {

setup.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,30 @@ def build_static_binaries(args: Options, launcher_dir: str) -> None:
12031203
build_static_kittens(args, launcher_dir, args.dir_for_static_binaries, for_platform=(os_, arch))
12041204

12051205

1206+
@lru_cache(2)
1207+
def kitty_cli_boolean_options() -> Tuple[str, ...]:
1208+
with open(os.path.join(src_base, 'kitty/cli.py')) as f:
1209+
raw = f.read()
1210+
m = re.search(r"^\s*OPTIONS = '''(.+?)'''", raw, flags=re.MULTILINE | re.DOTALL)
1211+
assert m is not None
1212+
ans: List[str] = []
1213+
in_option: List[str] = []
1214+
prev_line_was_blank = False
1215+
for line in m.group(1).splitlines():
1216+
if in_option:
1217+
is_blank = not line.strip()
1218+
if is_blank:
1219+
if prev_line_was_blank:
1220+
in_option = []
1221+
prev_line_was_blank = is_blank
1222+
if line.startswith('type=bool-'):
1223+
ans.extend(x.lstrip('-') for x in in_option)
1224+
else:
1225+
if line.startswith('-'):
1226+
in_option = line.strip().split()
1227+
return tuple(ans)
1228+
1229+
12061230
def build_launcher(args: Options, launcher_dir: str = '.', bundle_type: str = 'source') -> None:
12071231
werror = '' if args.ignore_compiler_warnings else '-pedantic-errors -Werror'
12081232
cflags = f'-Wall {werror} -fpie'.split()
@@ -1260,6 +1284,8 @@ def build_launcher(args: Options, launcher_dir: str = '.', bundle_type: str = 's
12601284
os.makedirs(launcher_dir, exist_ok=True)
12611285
os.makedirs(build_dir, exist_ok=True)
12621286
objects = []
1287+
cppflags.append('-DKITTY_CLI_BOOL_OPTIONS=" ' + ' '.join(kitty_cli_boolean_options()) + ' "')
1288+
cppflags.append('-DKITTY_VERSION="' + '.'.join(map(str, version)) + '"')
12631289
for src in ('kitty/launcher/main.c',):
12641290
obj = os.path.join(build_dir, src.replace('/', '-').replace('.c', '.o'))
12651291
objects.append(obj)

0 commit comments

Comments
 (0)