Compare commits
6 Commits
Author | SHA1 | Date |
---|---|---|
Riley Housden | 44555fc84e | |
Riley Housden | 067ab48de0 | |
Riley Housden | eedecb34d5 | |
Riley Housden | cc6bbe937f | |
Riley Housden | 67fd1b3cf4 | |
Riley Housden | 0f5bbd78ad |
|
@ -1,5 +1,3 @@
|
|||
import:
|
||||
- /home/riley/.config/alacritty/dracula.yml
|
||||
# Configuration for Alacritty, the GPU enhanced terminal emulator.
|
||||
|
||||
# Import additional configuration files
|
||||
|
@ -16,16 +14,11 @@ import:
|
|||
# Any items in the `env` entry below will be added as
|
||||
# environment variables. Some entries may override variables
|
||||
# set by alacritty itself.
|
||||
#env:
|
||||
# TERM variable
|
||||
#
|
||||
# This value is used to set the `$TERM` environment variable for
|
||||
# each instance of Alacritty. If it is not present, alacritty will
|
||||
# check the local terminfo database and use `alacritty` if it is
|
||||
# available, otherwise `xterm-256color` is used.
|
||||
#TERM: alacritty
|
||||
env:
|
||||
WINIT_X11_SCALE_FACTOR: '1.0'
|
||||
|
||||
window:
|
||||
opacity: 0.95
|
||||
# Window dimensions (changes require restart)
|
||||
#
|
||||
# Number of lines/columns (not pixels) in the terminal. The number of columns
|
||||
|
@ -178,142 +171,120 @@ window:
|
|||
#draw_bold_text_with_bright_colors: false
|
||||
|
||||
# Colors (Tomorrow Night)
|
||||
#colors:
|
||||
# Default colors
|
||||
#primary:
|
||||
# background: '#1d1f21'
|
||||
# foreground: '#c5c8c6'
|
||||
schemes:
|
||||
dracula: &dracula
|
||||
colors:
|
||||
primary:
|
||||
background: '0x282a36'
|
||||
foreground: '0xf8f8f2'
|
||||
cursor:
|
||||
text: CellBackground
|
||||
cursor: CellForeground
|
||||
vi_mode_cursor:
|
||||
text: CellBackground
|
||||
cursor: CellForeground
|
||||
search:
|
||||
matches:
|
||||
foreground: '0x44475a'
|
||||
background: '0x50fa7b'
|
||||
focused_match:
|
||||
foreground: '0x44475a'
|
||||
background: '0xffb86c'
|
||||
bar:
|
||||
background: '0x282a36'
|
||||
foreground: '0xf8f8f2'
|
||||
line_indicator:
|
||||
foreground: None
|
||||
background: None
|
||||
selection:
|
||||
text: CellForeground
|
||||
background: '0x44475a'
|
||||
normal:
|
||||
black: '0x000000'
|
||||
red: '0xff5555'
|
||||
green: '0x50fa7b'
|
||||
yellow: '0xf1fa8c'
|
||||
blue: '0xbd93f9'
|
||||
magenta: '0xff79c6'
|
||||
cyan: '0x8be9fd'
|
||||
white: '0xbfbfbf'
|
||||
bright:
|
||||
black: '0x4d4d4d'
|
||||
red: '0xff6e67'
|
||||
green: '0x5af78e'
|
||||
yellow: '0xf4f99d'
|
||||
blue: '0xcaa9fa'
|
||||
magenta: '0xff92d0'
|
||||
cyan: '0x9aedfe'
|
||||
white: '0xe6e6e6'
|
||||
dim:
|
||||
black: '0x14151b'
|
||||
red: '0xff2222'
|
||||
green: '0x1ef956'
|
||||
yellow: '0xebf85b'
|
||||
blue: '0x4d5b86'
|
||||
magenta: '0xff46b0'
|
||||
cyan: '0x59dffc'
|
||||
white: '0xe6e6d1'
|
||||
# Tokyo Night theme, based on both:
|
||||
# https://github.com/ghifarit53/tokyonight-vim
|
||||
# https://github.com/enkia/tokyo-night-vscode-theme
|
||||
tokyo-night: &tokyo-night
|
||||
# Default colors
|
||||
primary:
|
||||
background: '0x1a1b26'
|
||||
foreground: '0xa9b1d6'
|
||||
|
||||
# Bright and dim foreground colors
|
||||
#
|
||||
# The dimmed foreground color is calculated automatically if it is not
|
||||
# present. If the bright foreground color is not set, or
|
||||
# `draw_bold_text_with_bright_colors` is `false`, the normal foreground
|
||||
# color will be used.
|
||||
#dim_foreground: '#828482'
|
||||
#bright_foreground: '#eaeaea'
|
||||
# Normal colors
|
||||
normal:
|
||||
black: '0x32344a'
|
||||
red: '0xf7768e'
|
||||
green: '0x9ece6a'
|
||||
yellow: '0xe0af68'
|
||||
blue: '0x7aa2f7'
|
||||
magenta: '0xad8ee6'
|
||||
cyan: '0x449dab'
|
||||
white: '0x787c99'
|
||||
|
||||
# Cursor colors
|
||||
#
|
||||
# Colors which should be used to draw the terminal cursor.
|
||||
#
|
||||
# Allowed values are CellForeground/CellBackground, which reference the
|
||||
# affected cell, or hexadecimal colors like #ff00ff.
|
||||
#cursor:
|
||||
# text: CellBackground
|
||||
# cursor: CellForeground
|
||||
# Bright colors
|
||||
bright:
|
||||
black: '0x444b6a'
|
||||
red: '0xff7a93'
|
||||
green: '0xb9f27c'
|
||||
yellow: '0xff9e64'
|
||||
blue: '0x7da6ff'
|
||||
magenta: '0xbb9af7'
|
||||
cyan: '0x0db9d7'
|
||||
white: '0xacb0d0'
|
||||
|
||||
# Vi mode cursor colors
|
||||
#
|
||||
# Colors for the cursor when the vi mode is active.
|
||||
#
|
||||
# Allowed values are CellForeground/CellBackground, which reference the
|
||||
# affected cell, or hexadecimal colors like #ff00ff.
|
||||
#vi_mode_cursor:
|
||||
# text: CellBackground
|
||||
# cursor: CellForeground
|
||||
tokyo-night-storm: &tokyo-night-storm
|
||||
# Default colors
|
||||
primary:
|
||||
background: '0x24283b'
|
||||
foreground: '0xa9b1d6'
|
||||
|
||||
# Search colors
|
||||
#
|
||||
# Colors used for the search bar and match highlighting.
|
||||
#search:
|
||||
# Allowed values are CellForeground/CellBackground, which reference the
|
||||
# affected cell, or hexadecimal colors like #ff00ff.
|
||||
#matches:
|
||||
# foreground: '#000000'
|
||||
# background: '#ffffff'
|
||||
#focused_match:
|
||||
# foreground: '#ffffff'
|
||||
# background: '#000000'
|
||||
|
||||
#bar:
|
||||
# background: '#c5c8c6'
|
||||
# foreground: '#1d1f21'
|
||||
|
||||
# Keyboard regex hints
|
||||
#hints:
|
||||
# First character in the hint label
|
||||
#
|
||||
# Allowed values are CellForeground/CellBackground, which reference the
|
||||
# affected cell, or hexadecimal colors like #ff00ff.
|
||||
#start:
|
||||
# foreground: '#1d1f21'
|
||||
# background: '#e9ff5e'
|
||||
|
||||
# All characters after the first one in the hint label
|
||||
#
|
||||
# Allowed values are CellForeground/CellBackground, which reference the
|
||||
# affected cell, or hexadecimal colors like #ff00ff.
|
||||
#end:
|
||||
# foreground: '#e9ff5e'
|
||||
# background: '#1d1f21'
|
||||
|
||||
# Line indicator
|
||||
#
|
||||
# Color used for the indicator displaying the position in history during
|
||||
# search and vi mode.
|
||||
#
|
||||
# By default, these will use the opposing primary color.
|
||||
#line_indicator:
|
||||
# foreground: None
|
||||
# background: None
|
||||
|
||||
# Selection colors
|
||||
#
|
||||
# Colors which should be used to draw the selection area.
|
||||
#
|
||||
# Allowed values are CellForeground/CellBackground, which reference the
|
||||
# affected cell, or hexadecimal colors like #ff00ff.
|
||||
#selection:
|
||||
# text: CellBackground
|
||||
# background: CellForeground
|
||||
|
||||
# Normal colors
|
||||
#normal:
|
||||
# black: '#1d1f21'
|
||||
# red: '#cc6666'
|
||||
# green: '#b5bd68'
|
||||
# yellow: '#f0c674'
|
||||
# blue: '#81a2be'
|
||||
# magenta: '#b294bb'
|
||||
# cyan: '#8abeb7'
|
||||
# white: '#c5c8c6'
|
||||
|
||||
# Bright colors
|
||||
#bright:
|
||||
# black: '#666666'
|
||||
# red: '#d54e53'
|
||||
# green: '#b9ca4a'
|
||||
# yellow: '#e7c547'
|
||||
# blue: '#7aa6da'
|
||||
# magenta: '#c397d8'
|
||||
# cyan: '#70c0b1'
|
||||
# white: '#eaeaea'
|
||||
|
||||
# Dim colors
|
||||
#
|
||||
# If the dim colors are not set, they will be calculated automatically based
|
||||
# on the `normal` colors.
|
||||
#dim:
|
||||
# black: '#131415'
|
||||
# red: '#864343'
|
||||
# green: '#777c44'
|
||||
# yellow: '#9e824c'
|
||||
# blue: '#556a7d'
|
||||
# magenta: '#75617b'
|
||||
# cyan: '#5b7d78'
|
||||
# white: '#828482'
|
||||
|
||||
# Indexed Colors
|
||||
#
|
||||
# The indexed colors include all colors from 16 to 256.
|
||||
# When these are not set, they're filled with sensible defaults.
|
||||
#
|
||||
# Example:
|
||||
# `- { index: 16, color: '#ff00ff' }`
|
||||
#
|
||||
#indexed_colors: []
|
||||
# Normal colors
|
||||
normal:
|
||||
black: '0x32344a'
|
||||
red: '0xf7768e'
|
||||
green: '0x9ece6a'
|
||||
yellow: '0xe0af68'
|
||||
blue: '0x7aa2f7'
|
||||
magenta: '0xad8ee6'
|
||||
cyan: '0x449dab'
|
||||
white: '0x9699a8'
|
||||
|
||||
# Bright colors
|
||||
bright:
|
||||
black: '0x444b6a'
|
||||
red: '0xff7a93'
|
||||
green: '0xb9f27c'
|
||||
yellow: '0xff9e64'
|
||||
blue: '0x7da6ff'
|
||||
magenta: '0xbb9af7'
|
||||
cyan: '0x0db9d7'
|
||||
white: '0xacb0d0'
|
||||
colors: *tokyo-night-storm
|
||||
# Bell
|
||||
#
|
||||
# The bell is rung every time the BEL control character is received.
|
||||
|
|
3
.vimrc
3
.vimrc
|
@ -12,7 +12,6 @@ if $TERM == 'tmux-256color'
|
|||
let &t_8b = "\033[48;2;%lu;%lu;%lum"
|
||||
endif
|
||||
|
||||
set termguicolors
|
||||
set background=dark
|
||||
syntax enable
|
||||
|
||||
|
@ -66,5 +65,7 @@ Plug 'preservim/nerdtree'
|
|||
Plug 'chiel92/vim-autoformat'
|
||||
Plug 'natebosch/vim-lsc'
|
||||
Plug 'https://tildegit.org/sloum/gemini-vim-syntax'
|
||||
Plug 'meatballs/vim-xonsh'
|
||||
Plug 'davidhalter/jedi-vim'
|
||||
|
||||
call plug#end()
|
||||
|
|
5
.xonshrc
5
.xonshrc
|
@ -6,15 +6,12 @@ elif $HOSTNAME == "riley-server":
|
|||
elif $HOSTNAME == "riley-desktop":
|
||||
$PROMPT = '{RED} >< {RESET}| {BOLD_GREEN}{cwd_base}{RESET} ) '
|
||||
$XONSH_COLOR_STYLE = 'default'
|
||||
xontrib load argcomplete autovox jedi z bashisms
|
||||
xontrib load argcomplete autovox jedi z bashisms jds
|
||||
|
||||
source "~/xsh/functions.xsh"
|
||||
source "~/xsh/exceptions.xsh"
|
||||
source "~/xsh/aliases.xsh"
|
||||
|
||||
# TODO: Fix with Arch-based distros
|
||||
# import addins # my extra stuffs :p
|
||||
|
||||
# Windows Subsystem for Linux stuff
|
||||
if in_wsl():
|
||||
$GPG_TTY=$(tty) # allows gpg to work inside WSL
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
"""
|
||||
Backup Module:
|
||||
|
||||
Classes:
|
||||
- BackupManager
|
||||
"""
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from zipfile import ZipFile
|
||||
|
||||
from . import Storage
|
||||
|
||||
__all__ = ["BackupManager"]
|
||||
|
||||
class BackupManager:
|
||||
"""
|
||||
Facilitates backup creation. Stores all backups in ~/.storage/backups
|
||||
|
||||
Methods:
|
||||
- create_backup()
|
||||
- get_backups()
|
||||
- get_delete_candidates()
|
||||
- delete_excess_backups()
|
||||
"""
|
||||
def __init__(self, target_path: Path, backup_storage: Storage = Storage("backups"),
|
||||
date_format: str = "%d_%m_%y__%H%M%S", separator: str = "-") -> None:
|
||||
"""
|
||||
Test
|
||||
"""
|
||||
self.target_path = target_path
|
||||
self.backup_storage = backup_storage
|
||||
self.date_format = date_format
|
||||
self.separator = separator
|
||||
|
||||
@property
|
||||
def target_path(self) -> Path:
|
||||
"""
|
||||
Target to create backups of. This could be a file or folder.
|
||||
"""
|
||||
return self._target_path
|
||||
|
||||
@target_path.setter
|
||||
def target_path(self, new_path: Path):
|
||||
if isinstance(new_path, Path):
|
||||
if new_path.exists() and (new_path.is_dir() or new_path.is_file()):
|
||||
self._target_path = new_path
|
||||
else:
|
||||
raise ValueError(new_path)
|
||||
else:
|
||||
raise TypeError(new_path)
|
||||
|
||||
@property
|
||||
def backup_storage(self) -> Storage:
|
||||
"""
|
||||
Storage object to store created backups in.
|
||||
"""
|
||||
return self._backup_storage
|
||||
|
||||
@backup_storage.setter
|
||||
def backup_storage(self, new_storage: Storage):
|
||||
if isinstance(new_storage, Storage):
|
||||
self._backup_storage = new_storage
|
||||
else:
|
||||
raise TypeError(new_storage)
|
||||
|
||||
@property
|
||||
def date_format(self) -> str:
|
||||
"""The datetime format string used to date the backups."""
|
||||
return self._date_format
|
||||
|
||||
@date_format.setter
|
||||
def date_format(self, new_format):
|
||||
if isinstance(new_format, str):
|
||||
self._date_format = new_format
|
||||
else:
|
||||
raise TypeError(new_format)
|
||||
|
||||
@property
|
||||
def separator(self) -> str:
|
||||
"""The separator that separates the archive name from the date"""
|
||||
return self._separator
|
||||
|
||||
@separator.setter
|
||||
def separator(self, new_separator):
|
||||
if isinstance(new_separator, str):
|
||||
if new_separator not in self.target_path.name and new_separator not in self.date_format:
|
||||
self._separator = new_separator
|
||||
else:
|
||||
raise ValueError(new_separator)
|
||||
else:
|
||||
raise TypeError(new_separator)
|
||||
|
||||
def create_backup(self):
|
||||
"""
|
||||
Create a backup of the target path, stored in the backup storage folder.
|
||||
"""
|
||||
date_string = datetime.now().strftime(self.date_format)
|
||||
backup_name = f"{self.target_path.name}{self.separator}{date_string}.zip"
|
||||
backup_path = self.backup_storage.get_file(backup_name)
|
||||
with ZipFile(backup_path, mode="w") as zip_file:
|
||||
for item in self.target_path.glob("**/*"):
|
||||
zip_file.write(item, item.relative_to(self.target_path))
|
||||
|
||||
def get_backups(self):
|
||||
"""
|
||||
Get all backups found in the given folder.
|
||||
"""
|
||||
return self.backup_storage.list_files(f"{self.target_path.stem}{self.separator}*.zip")
|
||||
|
||||
def get_delete_candidates(self, max_backup_count) -> list[Path]:
|
||||
"""
|
||||
Get all candidates for deletion with the given max_backup_count.
|
||||
If none are available for deletion, returns None.
|
||||
"""
|
||||
def get_date(file: Path) -> datetime:
|
||||
"""
|
||||
Turns the datetime string in the file name into a datetime object.
|
||||
"""
|
||||
date_string = file.name.split(self.separator)[1].replace(file.suffix, "")
|
||||
return datetime.strptime(date_string, self.date_format)
|
||||
|
||||
backups = self.get_backups()
|
||||
backups.sort(key=get_date)
|
||||
return backups[:(len(backups)-max_backup_count)] # returns the oldest excess backups
|
||||
|
||||
def delete_excess_backups(self, max_backup_count: int):
|
||||
"""Delete all excess backups"""
|
||||
for file in self.get_delete_candidates(max_backup_count):
|
||||
file.unlink()
|
|
@ -0,0 +1,137 @@
|
|||
"""
|
||||
Storage Module:
|
||||
|
||||
Classes:
|
||||
- Storage
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import shutil
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
__all__ = ['Storage']
|
||||
|
||||
class Storage:
|
||||
"""
|
||||
Unifies all filesystem access methods under a single class.
|
||||
Minimizes room for mistakes and improves reusability.
|
||||
|
||||
Methods:
|
||||
- get_file()
|
||||
- get_folder()
|
||||
- write_file()
|
||||
- read_file()
|
||||
- delete_file()
|
||||
- rename_file()
|
||||
- add_file()
|
||||
- list_files()
|
||||
"""
|
||||
|
||||
def __init__(self, folder: str, root_folder: str = ".storage") -> None:
|
||||
"""
|
||||
Create a new storage instance, it automatically creates and manages a folder in the user's home directory, all you have to do is supply a subfolder to store files in.
|
||||
|
||||
Args:
|
||||
folder (str): the name of the folder to use.
|
||||
"""
|
||||
self.root = Path.home().joinpath(root_folder)
|
||||
self.folder = self.root.joinpath(folder)
|
||||
self.folder.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
def get_file(self, path: str) -> Path:
|
||||
"""Get the fully qualified path of a file in the folder.
|
||||
|
||||
Args:
|
||||
path (str): the name of the file to grab.
|
||||
|
||||
Returns:
|
||||
Path: the path of the file.
|
||||
"""
|
||||
return self.folder.joinpath(path)
|
||||
|
||||
def get_folder(self, name: str) -> Storage:
|
||||
"""
|
||||
Get a folder inside the Storage directory.
|
||||
Returns a Storage object representing that folder.
|
||||
"""
|
||||
return Storage(name, root_folder=self.folder.name)
|
||||
|
||||
def write_file(self, name: str, data: dict):
|
||||
"""Write data to the given file in JSON format.
|
||||
|
||||
Args:
|
||||
name (str): the name of the file.
|
||||
data (dict): the data to write.
|
||||
"""
|
||||
file = self.get_file(name)
|
||||
file.touch(exist_ok=True)
|
||||
with file.open("w+", encoding="utf-8") as f:
|
||||
json.dump(data, f, indent=4)
|
||||
|
||||
def read_file(self, name: str) -> dict:
|
||||
"""Read data from the given file in JSON format.
|
||||
|
||||
Args:
|
||||
name (str): the name of the file.
|
||||
|
||||
Returns:
|
||||
dict: the data from the file.
|
||||
"""
|
||||
file = self.get_file(name)
|
||||
if not file.exists():
|
||||
return {}
|
||||
with file.open("r+", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
return data
|
||||
|
||||
def delete_file(self, name: str):
|
||||
"""Delete the given file from the folder.
|
||||
|
||||
Args:
|
||||
name (str): the name of the file.
|
||||
"""
|
||||
file = self.get_file(name)
|
||||
file.unlink(missing_ok=True)
|
||||
|
||||
def rename_file(self, old_name: str, new_name: str):
|
||||
"""Rename a file in the folder.
|
||||
|
||||
Args:
|
||||
old_name (str): the current name of the file.
|
||||
new_name (str): the new name of the file.
|
||||
"""
|
||||
file = self.get_file(old_name)
|
||||
new_file = self.folder.joinpath(new_name)
|
||||
file.rename(new_file)
|
||||
|
||||
def add_file(self, name: str, path: Path | None = None, binary: bytes | None = None):
|
||||
"""Add a copy of a file to the folder.
|
||||
If a binary stream is given, it is saved directly to the named location.
|
||||
|
||||
Args:
|
||||
name (str): The name to save it under.
|
||||
path (Path): The path of the file to copy from.
|
||||
binary (BinaryIO): The binary stream to copy from.
|
||||
"""
|
||||
if path is not None and binary is not None:
|
||||
raise ValueError(binary, "Cannot supply both a path and a binary stream.")
|
||||
elif path is not None:
|
||||
shutil.copy(path, self.folder.joinpath(name))
|
||||
elif binary is not None:
|
||||
with self.folder.joinpath(name).open("wb+") as f:
|
||||
f.write(binary)
|
||||
|
||||
def list_files(self, pattern: str | None = None) -> list[Path]:
|
||||
"""
|
||||
Return a list of all files in the directory.
|
||||
"""
|
||||
files: list[Path] = []
|
||||
if pattern is None:
|
||||
for file in self.folder.iterdir():
|
||||
files.append(file)
|
||||
else:
|
||||
for file in self.folder.glob(pattern):
|
||||
files.append(file)
|
||||
return files
|
|
@ -0,0 +1,52 @@
|
|||
"""Integrates Johnny Decimal Notation into Xonsh"""
|
||||
from pathlib import Path
|
||||
|
||||
from xonsh.built_ins import XSH
|
||||
|
||||
HOME = Path("/run/media/riley/drive")
|
||||
|
||||
def find_category(number: int, path, regex: str):
|
||||
"""Find matching JDN folder when given notation"""
|
||||
import re
|
||||
folders = path.iterdir()
|
||||
for folder in folders:
|
||||
if not folder.is_dir():
|
||||
continue
|
||||
folder_category = re.match(regex, folder.name)
|
||||
if folder_category is None:
|
||||
continue
|
||||
if len(folder_category.groups()) == 2:
|
||||
if number >= int(folder_category.group(1)) and number <= int(folder_category.group(2)):
|
||||
return folder
|
||||
elif len(folder_category.groups()) == 1:
|
||||
if number == int(folder_category.group((1))):
|
||||
return folder
|
||||
return path
|
||||
|
||||
@XSH.builtins.events.on_transform_command
|
||||
def jds_preproc(cmd: str, **kw):
|
||||
"""processes command strings starting with "`" to cd to matching folder."""
|
||||
if cmd.startswith("`") and "." in cmd and not cmd.strip().endswith("`"):
|
||||
try:
|
||||
johnny_decimal_notation = cmd.replace("`", "")
|
||||
bucket = find_category(int(johnny_decimal_notation.split(".")[0]), HOME, r"(^\d0)-(\d9)")
|
||||
category = find_category(int(johnny_decimal_notation.split(".")[0]), bucket, r"^(\d\d)")
|
||||
folder = find_category(int(johnny_decimal_notation.split(".")[1]), category, r"^(\d\d)")
|
||||
cmd = f"cd '{folder.resolve()}'"
|
||||
except FileNotFoundError:
|
||||
cmd = f'print("\'{HOME}\' not found.")'
|
||||
except ValueError:
|
||||
cmd = f'print("\'{cmd.strip().replace("`", "")}\' is not a valid JDN.")'
|
||||
elif cmd.startswith("`") and not (len(cmd.strip()) >= 2 and cmd.strip().endswith("`")):
|
||||
try:
|
||||
johnny_decimal_notation = cmd.replace("`", "")
|
||||
if johnny_decimal_notation == "\n":
|
||||
return f"cd '{HOME.resolve()}'"
|
||||
bucket = find_category(int(johnny_decimal_notation.split(".")[0]), HOME, r"(^\d0)-(\d9)")
|
||||
category = find_category(int(johnny_decimal_notation.split(".")[0]), bucket, r"^(\d\d)")
|
||||
cmd = f"cd '{category.resolve()}'"
|
||||
except FileNotFoundError:
|
||||
cmd = f'print("\'{HOME}\' not found.")'
|
||||
except ValueError:
|
||||
cmd = f'print("\'{cmd.strip().replace("`", "")}\' is not a valid JDN.")'
|
||||
return cmd
|
|
@ -1,4 +1,5 @@
|
|||
source xsh/functions.xsh
|
||||
import lib
|
||||
source ~/xsh/functions.xsh
|
||||
|
||||
def _debug():
|
||||
if $XONSH_SHOW_TRACEBACK:
|
||||
|
@ -41,19 +42,60 @@ def _bwc(args: list):
|
|||
else:
|
||||
print(f"copied {i}")
|
||||
|
||||
def _mcrcon(args: list):
|
||||
if p"~/.mcrcon".exists():
|
||||
source "~/.mcrcon"
|
||||
else:
|
||||
raise FileNotFoundError("~/.mcrcon")
|
||||
$(mcrcon @(" ".join(args)))
|
||||
def _backup(args: list):
|
||||
from pathlib import Path
|
||||
target_path = Path(args[0])
|
||||
max_backup_count: int = 3
|
||||
if len(args) == 2 and isinstance(args[1], int):
|
||||
max_backup_count = int(args[1])
|
||||
bm = lib.BackupManager(target_path)
|
||||
bm.create_backup()
|
||||
bm.delete_excess_backups(max_backup_count)
|
||||
|
||||
def _mcterm():
|
||||
if p"~/.mcrcon".exists():
|
||||
source "~/.mcrcon"
|
||||
else:
|
||||
raise FileNotFoundError("~/.mcrcon")
|
||||
mcrcon -t
|
||||
def _mcrcon(args: list):
|
||||
import json
|
||||
try:
|
||||
with p"~/.mcrcon.json".open("r") as fp:
|
||||
servers_data = json.load(fp)
|
||||
server_data = servers_data[args[0]]
|
||||
$MCRCON_HOST = server_data["address"]
|
||||
$MCRCON_PORT = server_data["port"]
|
||||
$MCRCON_PASS = server_data["password"]
|
||||
$(mcrcon @(" ".join(args[1:])))
|
||||
except IndexError:
|
||||
print("Please indicate which server to connect to.")
|
||||
except KeyError:
|
||||
print("Server configuration not found.")
|
||||
except FileNotFoundError:
|
||||
print("Server configuration file '.mcrcon.json' is not found.")
|
||||
|
||||
def _mcterm(args: list):
|
||||
import json
|
||||
try:
|
||||
with p"~/.mcrcon.json".open("r") as fp:
|
||||
servers_data = json.load(fp)
|
||||
server_data = servers_data[args[0]]
|
||||
$MCRCON_HOST = server_data["address"]
|
||||
$MCRCON_PORT = server_data["port"]
|
||||
$MCRCON_PASS = server_data["password"]
|
||||
mcrcon -t
|
||||
except IndexError:
|
||||
print("Please indicate which server to connect to.")
|
||||
except KeyError:
|
||||
print("Server configuration not found.")
|
||||
except FileNotFoundError:
|
||||
print("Server configuration file '.mcrcon.json' is not found.")
|
||||
|
||||
def _mclist():
|
||||
import json
|
||||
try:
|
||||
with p"~/.mcrcon.json".open("r") as fp:
|
||||
servers_data = json.load(fp)
|
||||
print("Servers:")
|
||||
for key in servers_data:
|
||||
print("\t-", key)
|
||||
except FileNotFoundError:
|
||||
print("Server configuration file '.mcrcon.json' is not found.")
|
||||
|
||||
def _alias():
|
||||
for alias in aliases:
|
||||
|
@ -91,12 +133,15 @@ def _ls():
|
|||
|
||||
def load_aliases():
|
||||
aliases.update({
|
||||
'bu': _backup,
|
||||
'backup': _backup,
|
||||
'bwg': _bwc,
|
||||
'colortest': _colortest,
|
||||
'debug': _debug,
|
||||
'ls': 'ls -alhs --color=auto',
|
||||
'mc': _mcrcon,
|
||||
'mct': _mcterm,
|
||||
'mcl': _mclist,
|
||||
':q': 'exit',
|
||||
'ensure-tmux': _ensure_tmux,
|
||||
'aliases': _alias,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
source xsh/exceptions.xsh
|
||||
source ~/xsh/exceptions.xsh
|
||||
|
||||
def in_wsl() -> bool:
|
||||
"""Determines if the system is running inside a WSL environment."""
|
||||
|
|
Loading…
Reference in New Issue