1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
#!/usr/bin/env bun
import { $, spawn } from 'bun';
type Workspace = {
workspaceId: number;
language: string;
};
let savedWorkspaces: Array<Workspace> = [];
setInitialWorkspaceData();
updateConfigOnLanguageChange();
const availableLanguages = (await $`setxkbmap -query | grep layout | awk '{print $2}'`.text()).split(',');
const i3Socket = (await Bun.$`sh -c 'ls /run/user/1000/i3/ipc-socket.*'`.text()).trim();
const { stdout } = spawn(['i3-msg', '-m', `--socket=${i3Socket}`, '-t', 'subscribe', '[ "workspace" ]']);
for await (const data of stdout.pipeThrough(new TextDecoderStream())) {
for (const dataLine of data.split('\n')) {
if (!dataLine) continue;
const workspaceData = JSON.parse(dataLine);
const event = workspaceData.change;
if (event !== "focus") continue;
await switchLanguageOnWorkspaceChange(workspaceData.current.num);
}
}
async function updateConfigOnLanguageChange() {
const { stdout } = spawn(['xkb-switch', '-W']);
for await (const data of stdout.pipeThrough(new TextDecoderStream())) {
const currentLanguage = data.trim();
const currentWorkspace = await getWorkspace();
const existing = tryGetSavedWorkspace(currentWorkspace);
if (!!existing) {
setSavedWorkspace(currentWorkspace, currentLanguage);
} else {
savedWorkspaces.push({ workspaceId: currentWorkspace, language: currentLanguage });
}
}
}
async function setInitialWorkspaceData() {
savedWorkspaces.push({ workspaceId: await getWorkspace(), language: await getLanguage() });
}
async function getWorkspace() {
const json = await $`i3-msg -t get_workspaces`.json();
const focused = json.find((w: any) => w.focused);
return focused.num;
}
function tryGetSavedWorkspace(workspaceId: number) {
return savedWorkspaces.find((w: Workspace) => w.workspaceId === workspaceId);
}
function setSavedWorkspace(workspaceId: number, language: string) {
const workspace = tryGetSavedWorkspace(workspaceId);
if (workspace) {
workspace.language = language;
} else {
savedWorkspaces.push({ workspaceId, language });
}
}
async function getLanguage() {
return await $`xkblayout-state print %s`.text();
}
async function setLanguage(language: string) {
await $`xkblayout-state set ${availableLanguages.indexOf(language)}`;
}
async function switchLanguageOnWorkspaceChange(focusedWorkspaceId: number) {
let currentLayout = await getLanguage();
let savedWorkspace = tryGetSavedWorkspace(focusedWorkspaceId);
if (!tryGetSavedWorkspace(focusedWorkspaceId)) {
savedWorkspaces.push({ workspaceId: focusedWorkspaceId, language: currentLayout });
savedWorkspace = tryGetSavedWorkspace(focusedWorkspaceId);
}
if (savedWorkspace.language !== currentLayout) {
await setLanguage(savedWorkspace.language);
}
}
|