Clean up previous PR

This commit is contained in:
Kovid Goyal
2021-10-05 11:36:29 +05:30
parent fe42b15ec6
commit 35d4e2d4e0
3 changed files with 72 additions and 110 deletions

View File

@@ -226,9 +226,7 @@ extern bool init_mouse(PyObject *module);
extern bool init_kittens(PyObject *module); extern bool init_kittens(PyObject *module);
extern bool init_logging(PyObject *module); extern bool init_logging(PyObject *module);
extern bool init_png_reader(PyObject *module); extern bool init_png_reader(PyObject *module);
#ifdef __unix__
extern bool init_utmp(PyObject *module); extern bool init_utmp(PyObject *module);
#endif
#ifdef __APPLE__ #ifdef __APPLE__
extern int init_CoreText(PyObject *); extern int init_CoreText(PyObject *);
extern bool init_cocoa(PyObject *module); extern bool init_cocoa(PyObject *module);
@@ -296,9 +294,7 @@ PyInit_fast_data_types(void) {
if (!init_freetype_render_ui_text(m)) return NULL; if (!init_freetype_render_ui_text(m)) return NULL;
#endif #endif
if (!init_fonts(m)) return NULL; if (!init_fonts(m)) return NULL;
#if defined(__unix__)
if (!init_utmp(m)) return NULL; if (!init_utmp(m)) return NULL;
#endif
CellAttrs a; CellAttrs a;
#define s(name, attr) { a.val = 0; a.attr = 1; PyModule_AddIntConstant(m, #name, shift_to_first_set_bit(a)); } #define s(name, attr) { a.val = 0; a.attr = 1; PyModule_AddIntConstant(m, #name, shift_to_first_set_bit(a)); }

View File

@@ -3,10 +3,16 @@
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net> # License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
import os import os
import re
import socket
import sys import sys
import termios
import time
from functools import partial from functools import partial
from pprint import pformat from pprint import pformat
from typing import Callable, Dict, Generator, Iterable, Set, Tuple from typing import (
IO, Callable, Dict, Generator, Iterable, Optional, Set, Tuple
)
from kittens.tui.operations import colored, styled from kittens.tui.operations import colored, styled
@@ -15,6 +21,7 @@ from .conf.utils import KeyAction
from .constants import ( from .constants import (
extensions_dir, is_macos, is_wayland, kitty_base_dir, kitty_exe, shell_path extensions_dir, is_macos, is_wayland, kitty_base_dir, kitty_exe, shell_path
) )
from .fast_data_types import num_users
from .options.types import Options as KittyOpts, defaults from .options.types import Options as KittyOpts, defaults
from .options.utils import MouseMap from .options.utils import MouseMap
from .rgb import Color, color_as_sharp from .rgb import Color, color_as_sharp
@@ -152,84 +159,58 @@ def compare_opts(opts: KittyOpts, print: Callable) -> None:
print('\n\t'.join(sorted(colors))) print('\n\t'.join(sorted(colors)))
is_linux = sys.platform in ('linux', 'linux2') class IssueData:
def __init__(self) -> None:
if is_linux: self.uname = os.uname()
import socket self.s, self.n, self.r, self.v, self.m = self.uname
import time self.hostname = self.o = socket.gethostname()
import re _time = time.localtime()
import termios self.formatted_time = self.d = time.strftime('%a %b %d %Y', _time)
from .fast_data_types import num_users self.formatted_date = self.t = time.strftime('%H:%M:%S', _time)
from typing import IO
class IssueData:
uname: os.uname_result
hostname: str
formatted_date: str
formatted_time: str
tty_name: str
baud_rate: int
num_users: int
def __init__(self):
self.uname = os.uname()
self.hostname = socket.gethostname()
_time = time.localtime()
self.formatted_time = time.strftime('%a %b %d %Y', _time)
self.formatted_date = time.strftime('%H:%M:%S', _time)
try:
self.tty_name = format_tty_name(os.ttyname(sys.stdin.fileno()))
except OSError:
self.tty_name = '(none)'
self.baud_rate = termios.tcgetattr(sys.stdin.fileno())[5]
self.num_users = num_users()
# https://kernel.googlesource.com/pub/scm/utils/util-linux/util-linux/+/v2.7.1/login-utils/agetty.c#790
issue_mappings = {
# ctx = IssueData
's': lambda ctx: ctx.uname.sysname,
'n': lambda ctx: ctx.uname.nodename,
'r': lambda ctx: ctx.uname.release,
'v': lambda ctx: ctx.uname.version,
'm': lambda ctx: ctx.uname.machine,
'o': lambda ctx: ctx.hostname,
'd': lambda ctx: ctx.formatted_date,
't': lambda ctx: ctx.formatted_time,
'l': lambda ctx: ctx.tty_name,
'b': lambda ctx: ctx.baud_rate,
'u': lambda ctx: ctx.num_users,
'U': lambda ctx: str(ctx.num_users) + ' user' + ('' if ctx.num_users == 1 else 's'),
}
def translate_issue_char(ctx: IssueData, char: str) -> str:
assert len(char) == 1
try: try:
return issue_mappings[char](ctx) self.tty_name = format_tty_name(os.ttyname(sys.stdin.fileno()))
except KeyError: except OSError:
return char self.tty_name = '(none)'
self.l = self.tty_name # noqa
self.baud_rate = termios.tcgetattr(sys.stdin.fileno())[5]
self.b = str(self.baud_rate)
try:
self.num_users = num_users()
except RuntimeError:
self.num_users = -1
self.u = str(self.num_users)
self.U = self.u + ' user' + ('' if self.num_users == 1 else 's')
def format_tty_name(raw: str) -> str: def translate_issue_char(ctx: IssueData, char: str) -> str:
return re.sub(r'^/dev/([^/]+)/([^/]+)$', r'\1\2', raw) try:
return str(getattr(ctx, char)) if len(char) == 1 else char
except AttributeError:
return char
def print_issue(issue_file: IO[str], print_fn) -> None: def format_tty_name(raw: str) -> str:
last_char = None return re.sub(r'^/dev/([^/]+)/([^/]+)$', r'\1\2', raw)
issue_data = IssueData()
while this_char := issue_file.read(1):
if last_char == '\\': def print_issue(issue_file: IO[str], print_fn: Callable) -> None:
print_fn(translate_issue_char(issue_data, this_char), end='') last_char: Optional[str] = None
elif last_char is not None: issue_data = IssueData()
print_fn(last_char, end='') while True:
# `\\\a` should not match the last two slashes, this_char = issue_file.read(1)
# so make it look like it was `\?\a` where `?` if not this_char:
# is some character other than `\`. break
last_char = None if last_char == '\\' else this_char if last_char == '\\':
if last_char is not None: print_fn(translate_issue_char(issue_data, this_char), end='')
elif last_char is not None:
print_fn(last_char, end='') print_fn(last_char, end='')
# `\\\a` should not match the last two slashes,
# so make it look like it was `\?\a` where `?`
# is some character other than `\`.
last_char = None if last_char == '\\' else this_char
if last_char is not None:
print_fn(last_char, end='')
def debug_config(opts: KittyOpts) -> str: def debug_config(opts: KittyOpts) -> str:
@@ -241,7 +222,7 @@ def debug_config(opts: KittyOpts) -> str:
if is_macos: if is_macos:
import subprocess import subprocess
p(' '.join(subprocess.check_output(['sw_vers']).decode('utf-8').splitlines()).strip()) p(' '.join(subprocess.check_output(['sw_vers']).decode('utf-8').splitlines()).strip())
if is_linux and os.path.exists('/etc/issue'): if os.path.exists('/etc/issue'):
with open('/etc/issue', encoding='utf-8', errors='replace') as f: with open('/etc/issue', encoding='utf-8', errors='replace') as f:
print_issue(f, p) print_issue(f, p)
if os.path.exists('/etc/lsb-release'): if os.path.exists('/etc/lsb-release'):

View File

@@ -1,50 +1,35 @@
#if defined(__unix__)
#define PY_SSIZE_T_CLEAN #include "data-types.h"
#include <Python.h> #ifdef __unix__
#include <stdbool.h> #include <utmpx.h>
#include <utmp.h>
static PyObject* static PyObject*
num_users(PyObject *const self, PyObject *const args) { num_users(PyObject *const self UNUSED, PyObject *const args UNUSED) {
(void)self; (void)args;
size_t users = 0; size_t users = 0;
struct utmpx *ut;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
#ifdef UTENT_REENTRANT setutxent();
struct utmp *result = NULL; while ((ut = getutxent())) {
struct utmp buffer = { 0, }; if (ut->ut_type == USER_PROCESS) users++;
while (true) {
if (getutent_r(&buffer, &result) == -1) {
Py_BLOCK_THREADS
return PyErr_SetFromErrno(PyExc_OSError);
}
if (result == NULL) { break; }
if (result->ut_type == USER_PROCESS) { users++; }
} }
#else endutxent();
struct utmp *ut;
setutent();
while ((ut = getutent())) {
if (ut->ut_type == USER_PROCESS) {
users++;
}
}
endutent();
#endif
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
return PyLong_FromSize_t(users); return PyLong_FromSize_t(users);
} }
#else
static PyObject*
num_users(PyObject *const self UNUSED, PyObject *const args UNUSED) {
PyErr_SetString(PyExc_RuntimeError, "Counting the number of users is not supported");
return NULL;
}
#endif
static PyMethodDef UtmpMethods[] = { static PyMethodDef methods[] = {
{"num_users", num_users, METH_NOARGS, "Get the number of users using UTMP data" }, {"num_users", num_users, METH_NOARGS, "Get the number of users using UTMP data" },
{ NULL, NULL, 0, NULL }, { NULL, NULL, 0, NULL },
}; };
bool bool
init_utmp(PyObject *module) { init_utmp(PyObject *module) {
// 0 = success return PyModule_AddFunctions(module, methods) == 0;
return PyModule_AddFunctions(module, UtmpMethods) == 0;
} }
#endif