maybe wezterm

master
Jordan Orelli 2 months ago
parent 0a7f70ba74
commit b2f4e57538

@ -3,3 +3,5 @@
email = jordanorelli@gmail.com email = jordanorelli@gmail.com
[pull] [pull]
rebase = true rebase = true
[rebase]
instructionFormat = (%an <%ae>) %s

@ -45,6 +45,11 @@ when: host.has('kitty') and host.is_linux
files: files:
desktop/kitty.desktop > .local/share/applications/kitty.desktop desktop/kitty.desktop > .local/share/applications/kitty.desktop
[home wezterm]
when: host.has('WezTerm.app')
files:
wezterm/config.lua > .wezterm.lua
[link-files nix-config] [link-files nix-config]
when: host.has('nix') when: host.has('nix')
target_root: ~/.config target_root: ~/.config

@ -0,0 +1 @@
print("You are in lua")

@ -11,38 +11,40 @@ import pathlib
import shutil import shutil
from functools import cached_property from functools import cached_property
class Host: class Host:
""" """
hacking the python module system a little to make the module look like a hacking the python module system a little to make the module look like a
singleton object so that it can have properties singleton object so that it can have properties
""" """
@cached_property @cached_property
def is_wsl(self): def is_wsl(self):
""" """
true if we're running Linux on WSL true if we're running Linux on WSL
""" """
return 'WSL2' in platform.platform() return "WSL2" in platform.platform()
@cached_property @cached_property
def is_linux(self): def is_linux(self):
""" """
true if we're on linux (including WSL), false otherwise true if we're on linux (including WSL), false otherwise
""" """
return platform.system() == 'Linux' return platform.system() == "Linux"
@cached_property @cached_property
def is_windows(self): def is_windows(self):
""" """
true if we're on Windows (and running Python from Windows) true if we're on Windows (and running Python from Windows)
""" """
return platform.system() == 'Windows' return platform.system() == "Windows"
@cached_property @cached_property
def is_darwin(self): def is_darwin(self):
""" """
true if we're on MacOS true if we're on MacOS
""" """
return platform.system() == 'Darwin' return platform.system() == "Darwin"
@cached_property @cached_property
def is_admin(self): def is_admin(self):
@ -69,10 +71,16 @@ class Host:
""" """
return pathlib.Path.home() return pathlib.Path.home()
def has(self, cmd): def has(self, cmd: str):
""" """
whether or not the machine has the specified command whether or not the machine has the specified command
""" """
if self.is_darwin and cmd.endswith(".app"):
app_dir = pathlib.Path("/Applications")
app_path = app_dir / cmd
if app_path.exists():
return True
return shutil.which(cmd) is not None return shutil.which(cmd) is not None
sys.modules[__name__] = Host() sys.modules[__name__] = Host()

@ -1,27 +1,23 @@
import configparser from configparser import ConfigParser, SectionProxy
import json
import pathlib
import sys
from functools import cached_property from functools import cached_property
from . import host
from . import sections
from . import targets
from .options import Options from .options import Options
from .resource import Resource from .resource import Resource
class Installer: class Installer:
""" """
manages the installation of preferences files manages the installation of preferences files
""" """
def __init__(self): def __init__(self):
self.options = Options.from_cli_args() self.options = Options.from_cli_args()
@cached_property @cached_property
def config(self): def config(self) -> ConfigParser:
path = self.options.config_path path = self.options.config_path
with open(path, 'r', encoding='utf-8') as config_file: with open(path, "r", encoding="utf-8") as config_file:
parser = configparser.ConfigParser() parser = ConfigParser()
# make keys case-sensitive # make keys case-sensitive
parser.optionxform = str parser.optionxform = str
parser.read_file(config_file) parser.read_file(config_file)
@ -37,7 +33,14 @@ class Installer:
else: else:
print(f"SKIP [{name}]") print(f"SKIP [{name}]")
def when(self, section): def when(self, section: SectionProxy) -> bool:
if clause := section.get('when', None): if clause := section.get("when", None):
return eval(clause) from . import host
given_locals = {
"host": host,
}
v = eval(clause, None, given_locals)
return bool(v)
return True return True

@ -4,10 +4,12 @@ import os
from . import host from . import host
class Linker: class Linker:
""" """
Linker links files from soome source to some target Linker links files from soome source to some target
""" """
def __init__(self, source_root, target_root): def __init__(self, source_root, target_root):
self.source_root = source_root self.source_root = source_root
self.target_root = target_root self.target_root = target_root
@ -23,8 +25,6 @@ class Linker:
parent_dir = target_path.parent parent_dir = target_path.parent
parent_dir.mkdir(parents=True) parent_dir.mkdir(parents=True)
exists = os.path.exists(str(target_path))
is_link = os.path.islink(str(target_path))
if target_path.exists(): if target_path.exists():
if target_path.is_symlink(): if target_path.is_symlink():
if target_path.resolve() == source_path: if target_path.resolve() == source_path:
@ -38,7 +38,9 @@ class Linker:
print(f"rm {target_path} (dir)") print(f"rm {target_path} (dir)")
shutil.rmtree(target_path) shutil.rmtree(target_path)
else: else:
print(f"skip {source_path}: unable to handle target at {target_path}: is not a symlink, file, or directory") print(
f"skip {source_path}: unable to handle target at {target_path}: is not a symlink, file, or directory"
)
return return
else: else:
if target_path.is_symlink(): if target_path.is_symlink():
@ -51,14 +53,15 @@ class Linker:
print(f"ERROR creating link: {e}") print(f"ERROR creating link: {e}")
print(f"link {target_path} -> {source_path}") print(f"link {target_path} -> {source_path}")
class LinkFiles: class LinkFiles:
resource_name = 'link-files' resource_name = "link-files"
def __init__(self, label, section): def __init__(self, label, section):
self.label = label self.label = label
self.target_root = pathlib.Path(section['target_root']).expanduser() self.target_root = pathlib.Path(section["target_root"]).expanduser()
self.source_root = host.dotfiles_root self.source_root = host.dotfiles_root
self.parse_files(section.get('files', '')) self.parse_files(section.get("files", ""))
def parse_files(self, text): def parse_files(self, text):
self.files = [] self.files = []
@ -73,8 +76,8 @@ class LinkFiles:
def __repr__(self): def __repr__(self):
if self.label: if self.label:
return f'<LinkFiles: {self.label}>' return f"<LinkFiles: {self.label}>"
return '<LinkFiles>' return "<LinkFiles>"
def run(self): def run(self):
linker = Linker(host.dotfiles_root, self.target_root) linker = Linker(host.dotfiles_root, self.target_root)

@ -1,14 +1,22 @@
from configparser import SectionProxy
from .home import Home from .home import Home
from .linker import LinkFiles from .linker import LinkFiles
from .cargo import CargoInstall from .cargo import CargoInstall
from .run import Run from .run import Run
from . import git from . import git
class Resource: class Resource:
resource_types = [Home, LinkFiles, CargoInstall, Run, git.Repo] resource_types: list[type] = [
Home,
LinkFiles,
CargoInstall,
Run,
git.Repo,
]
@classmethod @classmethod
def from_name(cls, name): def from_name(cls, name: str) -> type:
""" """
from_name is to be implemented by resource classes from_name is to be implemented by resource classes
""" """
@ -18,8 +26,8 @@ class Resource:
raise ValueError(f"No section type has name {name}") raise ValueError(f"No section type has name {name}")
@classmethod @classmethod
def from_section(cls, name, section): def from_section(cls, name: str, section: SectionProxy):
parts = name.split(' ') parts = name.split(" ")
name = parts[0] name = parts[0]
try: try:
label = parts[1] label = parts[1]

@ -1,16 +1,15 @@
import subprocess import subprocess
import os
import shutil
from . import host from . import host
class Run: class Run:
resource_name = 'run' resource_name = "run"
def __init__(self, label, section): def __init__(self, label, section):
self.label = label or None self.label = label or None
self.cmd = section.get('cmd', '').split() self.cmd = section.get("cmd", "").split()
self.cwd = section.get('cwd', host.dotfiles_root) self.cwd = section.get("cwd", host.dotfiles_root)
self.shell = section.get('shell', False) self.shell = section.get("shell", False)
def run(self): def run(self):
kwargs = { kwargs = {
@ -20,6 +19,7 @@ class Run:
"shell": self.shell, "shell": self.shell,
} }
with subprocess.Popen(self.cmd, **kwargs) as proc: with subprocess.Popen(self.cmd, **kwargs) as proc:
line = proc.stdout.read() if proc.stdout is not None:
if line: line = proc.stdout.read()
print(line) if line:
print(line)

@ -0,0 +1,15 @@
from typing import Sequence, Tuple
from pathlib import Path
def parse_files(text: str) -> Sequence[Tuple[Path, Path]]:
files = []
lines = [s for s in text.splitlines() if s]
for line in lines:
parts = line.split(">", 2)
if len(parts) == 1:
pair = (Path(parts[0].strip()), Path(parts[0].strip()))
else:
pair = (Path(parts[0].strip()), Path(parts[1].strip()))
files.append(pair)
return files

@ -0,0 +1,47 @@
local wezterm = require 'wezterm'
local config = wezterm.config_builder()
-- JellyBeans is not recognized
-- config.color_scheme = 'JellyBeans'
config.adjust_window_size_when_changing_font_size = false
-- Set the default starting directory when opening the terminal
-- config.default_cwd
-- The scroll bar is disabled by default but sometimes when you have really
-- long output I like it.
config.enable_scroll_bar = true
-- whether or not the tab bar is shown
config.enable_tab_bar = true
-- hide the tab bar in windows that have only one tab
config.hide_tab_bar_if_only_one_tab = true
config.font_size = 14
config.launch_menu = {
{
args = { 'lazydocker' },
}
}
config.keys = {
{
key = 'Enter',
mods = 'CMD',
action = wezterm.action.ToggleFullScreen,
},
}
config.native_macos_fullscreen_mode = true
config.scrollback_lines = 10000
config.tab_bar_at_bottom = true
-- config.initial_cols = 90
-- config.initial_rows = 24
return config
Loading…
Cancel
Save