Clean up previous PR

This commit is contained in:
Kovid Goyal 2021-10-05 11:36:29 +05:30
parent fe42b15ec6
commit 35d4e2d4e0
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
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_logging(PyObject *module);
extern bool init_png_reader(PyObject *module);
#ifdef __unix__
extern bool init_utmp(PyObject *module);
#endif
#ifdef __APPLE__
extern int init_CoreText(PyObject *);
extern bool init_cocoa(PyObject *module);
@ -296,9 +294,7 @@ PyInit_fast_data_types(void) {
if (!init_freetype_render_ui_text(m)) return NULL;
#endif
if (!init_fonts(m)) return NULL;
#if defined(__unix__)
if (!init_utmp(m)) return NULL;
#endif
CellAttrs 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>
import os
import re
import socket
import sys
import termios
import time
from functools import partial
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
@ -15,6 +21,7 @@ from .conf.utils import KeyAction
from .constants import (
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.utils import MouseMap
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)))
is_linux = sys.platform in ('linux', 'linux2')
class IssueData:
if is_linux:
import socket
import time
import re
import termios
from .fast_data_types import num_users
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
def __init__(self) -> None:
self.uname = os.uname()
self.s, self.n, self.r, self.v, self.m = self.uname
self.hostname = self.o = socket.gethostname()
_time = time.localtime()
self.formatted_time = self.d = time.strftime('%a %b %d %Y', _time)
self.formatted_date = self.t = time.strftime('%H:%M:%S', _time)
try:
return issue_mappings[char](ctx)
except KeyError:
return char
self.tty_name = format_tty_name(os.ttyname(sys.stdin.fileno()))
except OSError:
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:
return re.sub(r'^/dev/([^/]+)/([^/]+)$', r'\1\2', raw)
def translate_issue_char(ctx: IssueData, char: str) -> str:
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:
last_char = None
issue_data = IssueData()
while this_char := issue_file.read(1):
if last_char == '\\':
print_fn(translate_issue_char(issue_data, this_char), end='')
elif last_char is not None:
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:
def format_tty_name(raw: str) -> str:
return re.sub(r'^/dev/([^/]+)/([^/]+)$', r'\1\2', raw)
def print_issue(issue_file: IO[str], print_fn: Callable) -> None:
last_char: Optional[str] = None
issue_data = IssueData()
while True:
this_char = issue_file.read(1)
if not this_char:
break
if last_char == '\\':
print_fn(translate_issue_char(issue_data, this_char), end='')
elif last_char is not None:
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:
@ -241,7 +222,7 @@ def debug_config(opts: KittyOpts) -> str:
if is_macos:
import subprocess
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:
print_issue(f, p)
if os.path.exists('/etc/lsb-release'):

View File

@ -1,50 +1,35 @@
#if defined(__unix__)
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <stdbool.h>
#include <utmp.h>
#include "data-types.h"
#ifdef __unix__
#include <utmpx.h>
static PyObject*
num_users(PyObject *const self, PyObject *const args) {
(void)self; (void)args;
num_users(PyObject *const self UNUSED, PyObject *const args UNUSED) {
size_t users = 0;
struct utmpx *ut;
Py_BEGIN_ALLOW_THREADS
#ifdef UTENT_REENTRANT
struct utmp *result = NULL;
struct utmp buffer = { 0, };
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++; }
setutxent();
while ((ut = getutxent())) {
if (ut->ut_type == USER_PROCESS) users++;
}
#else
struct utmp *ut;
setutent();
while ((ut = getutent())) {
if (ut->ut_type == USER_PROCESS) {
users++;
}
}
endutent();
#endif
endutxent();
Py_END_ALLOW_THREADS
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" },
{ NULL, NULL, 0, NULL },
};
bool
init_utmp(PyObject *module) {
// 0 = success
return PyModule_AddFunctions(module, UtmpMethods) == 0;
return PyModule_AddFunctions(module, methods) == 0;
}
#endif