diff --git a/.config/fish/extraterm/exfrom.py b/.config/fish/extraterm/exfrom.py deleted file mode 100755 index 84a5a7b..0000000 --- a/.config/fish/extraterm/exfrom.py +++ /dev/null @@ -1,274 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2014-2018 Simon Edwards -# -# This source code is licensed under the MIT license which is detailed in the LICENSE.txt file. -# - -import argparse -import atexit -import base64 -import hashlib -import json -import os -import sys -import tempfile -import termios -import time -import tty -import uuid -from signal import signal, SIGPIPE, SIG_DFL, SIGTSTP, SIG_IGN, SIGTTOU - - -##@inline -from extratermclient import extratermclient - -HASH_LENGTH = 20 -COMMAND_PREFIX_LENGTH = 3 - - -class Metadata: - def __init__(self, metadata): - self.metadata = metadata - - -class BodyData: - def __init__(self, data): - self.data = data - - -class FrameReadError: - def __init__(self, message): - self.message = message - - -class FrameWriter: - def __init__(self, writeFunction, outputFlushFunction, errorWriteFunction, errorFlushFunction): - self.write = writeFunction - self.flush = outputFlushFunction - self.errorWrite = errorWriteFunction - self.errorFlush = errorFlushFunction - - -def readStdinLine(): - line = sys.stdin.readline() - return line.strip() - - -def requestFrame(frame_name): - """Returns a generator which outputs the frame contents as blocks of binary data. - """ - # We use plain old cooked mode for the transfer. Cygwin is a bit buggy - # and corrupts input when in cbreak or raw mode. Cooked mode also means - # that input lines have limited length defined by the size of the input - # buffer in the terminal driver. Linux supports up to about 4K, OS X is - # about 1K. Cygwin is ???. - - # Turn off echo on the tty. - fd = sys.stdin.fileno() - old_settings = termios.tcgetattr(fd) - new_settings = termios.tcgetattr(fd) - new_settings[3] = new_settings[3] & ~termios.ECHO # lflags - termios.tcsetattr(fd, termios.TCSADRAIN, new_settings) - - # Set up a hook to restore the tty settings at exit. - def restoreTty(): - termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) - sys.stderr.flush() - atexit.register(restoreTty) - - # Request the frame contents from the terminal. - extratermclient.requestFrame(frame_name) - - line = readStdinLine() - - if not line.startswith("#M:"): - yield FrameReadError("Error while reading in frame data. Expected '#M:...', but didn't receive it.") - return - - if len(line) < COMMAND_PREFIX_LENGTH + 1 + HASH_LENGTH: - yield FrameReadError("Error while reading in metadata. Line is too short.") - return - - b64data = line[COMMAND_PREFIX_LENGTH:-HASH_LENGTH-1] - lineHash = line[-HASH_LENGTH:] - - contents = base64.b64decode(b64data) - - hash = hashlib.sha256() - hash.update(contents) - previousHash = hash.digest() - hashHex = hash.hexdigest() - - # Check the hash. - if lineHash.lower() != hash.hexdigest()[:HASH_LENGTH].lower(): - yield FrameReadError("Error: Hash didn't match for metadata line. '"+lineHash+"'") - return - - # Decode the metadata. - yield Metadata(json.loads(str(contents, encoding="utf-8"))) - - # Read stdin until an empty buffer is returned. - try: - while True: - line = readStdinLine() - - if len(line) < COMMAND_PREFIX_LENGTH + 1 + HASH_LENGTH: - return FrameReadError("Error while reading frame body data. Line is too short.") - - if line.startswith("#D:") or line.startswith("#E:") or line.startswith("#A:"): - # Data - b64data = line[COMMAND_PREFIX_LENGTH:-HASH_LENGTH-1] - contents = base64.b64decode(b64data) - lineHash = line[-HASH_LENGTH:].lower() - - hash = hashlib.sha256() - hash.update(previousHash) - hash.update(contents) - previousHash = hash.digest() - - # Check the hash. - computedHashHex = hash.hexdigest()[:HASH_LENGTH].lower() - if lineHash != computedHashHex: - yield FrameReadError("Error: Upload failed. (Hash didn't match for data line. Expected " + computedHashHex + " got " + lineHash + ")") - return - - if line.startswith("#E:"): - # EOF - break - elif line.startswith("#A:"): - yield FrameReadError("Upload aborted") - return - else: - # Send the input to stdout. - yield BodyData(contents) - - - else: - yield FrameReadError("Error while reading frame body data. Line didn't start with '#D:' or '#E:'.") - return - - except OSError as ex: - print(ex.strerror, file=sys.stderr) - - #Ignore further SIG_PIPE signals and don't throw exceptions - signal(SIGPIPE,SIG_DFL) - - -def outputFrame(frame_name): - writer = FrameWriter(sys.stdout.buffer.write, sys.stdout.flush, sys.stderr.buffer.write, sys.stderr.flush) - rc, metadata = writeFrame(frame_name, writer) - return rc - - -def writeFrameToDisk(frame_name): - tmpFileName = str(uuid.uuid4()) + ".tmp" - with open(tmpFileName, "wb") as fhandle: - writer = FrameWriter(fhandle.write, fhandle.flush, sys.stderr.buffer.write, sys.stderr.flush) - rc, metadata = writeFrame(frame_name, writer) - - # Compute the final filename - filename = None - if "filename" in metadata: - filename = os.path.basename(metadata["filename"]) - - else: - if "mimeType" in metadata: - filename = metadata["mimeType"].replace("/", "-") - else: - return rc, tmpFileName - - counter = 0 - basename = filename - - while os.path.exists(filename): - parts = os.path.splitext(basename) - filename = parts[0] + " (" + str(counter) + ")" + parts[1] - counter += 1 - os.rename(tmpFileName, filename) - - return rc, filename - -def writeFrame(frame_name, frameWriter): - rc = 0 - metadata = None - for block in requestFrame(frame_name): - if isinstance(block, Metadata): - metadata = block.metadata - elif isinstance(block, BodyData): - frameWriter.write(block.data) - else: - # FrameReadError - frameWriter.errorWrite.write(bytes(block.message, 'utf8')) - frameWriter.errorWrite.write(bytes("\n", "utf8")) - frameWriter.errorFlush.flush() - rc = 1 - frameWriter.flush() - return rc, metadata - - -def xargs(frame_names, command_list): - temp_files = [] - rc = 0 - try: - # Fetch the contents of each frame and put them in tmp files. - for frame_name in frame_names: - rc, next_temp_file = readFrameToTempFile(frame_name) - temp_files.append(next_temp_file) - if rc != 0: - break - else: - # Build the complete command and args. - args = command_list[:] - for temp_file in temp_files: - args.append(temp_file.name) - - os.spawnvp(os.P_WAIT, args[0], [os.path.basename(args[0])] + args[1:]) - - finally: - # Clean up any temp files. - for temp_file in temp_files: - os.unlink(temp_file.name) - return rc - - -def readFrameToTempFile(frame_name): - fhandle = tempfile.NamedTemporaryFile('w+b', delete=False) - def noop(): pass - writer = FrameWriter(fhandle.write, noop, sys.stderr.buffer.write, sys.stderr.flush) - rc, metadata = writeFrame(writer) - fhandle.close() - return rc, fhandle - - -def main(): - parser = argparse.ArgumentParser(prog='from', description='Fetch data from an Extraterm frame.') - parser.add_argument('frames', metavar='frame_ID', type=str, nargs='+', help='a frame ID') - parser.add_argument('-s', '--save', dest='save', action='store_true', default=None, help='write frames to disk') - parser.add_argument('--xargs', metavar='xargs', type=str, nargs=argparse.REMAINDER, help='execute a command with frame contents as temp file names') - args = parser.parse_args() - - if not extratermclient.isExtraterm(): - print("[Error] 'from' command can only be run inside Extraterm.", file=sys.stderr) - sys.exit(1) - - # make sure that stdin is a tty. - if not os.isatty(sys.stdin.fileno()): - print("[Error] 'from' command must be connected to tty on stdin.", file=sys.stderr) - sys.exit(1) - - if args.xargs is None: - # Normal execution. Output the frames. - for frame_name in args.frames: - if args.save: - rc, filename = writeFrameToDisk(frame_name) - print("Wrote " +filename) - else: - rc = outputFrame(frame_name) - if rc != 0: - sys.exit(rc) - sys.exit(0) - else: - sys.exit(xargs(args.frames, args.xargs)) - -main() diff --git a/.config/fish/extraterm/exshow.py b/.config/fish/extraterm/exshow.py deleted file mode 100755 index f58dcc5..0000000 --- a/.config/fish/extraterm/exshow.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2014-2017 Simon Edwards -# -# This source code is licensed under the MIT license which is detailed in the LICENSE.txt file. -# -import argparse -import atexit -import base64 -import hashlib -import os -import os.path -import sys -import termios - -##@inline -from extratermclient import extratermclient - -MAX_CHUNK_BYTES = 3 * 1024 # This is kept a multiple of 3 to avoid padding in the base64 representation. - -def SendMimeTypeDataFromFile(filename, mimeType, charset, filenameMeta=None, download=False): - filesize = os.path.getsize(filename) - with open(filename,'rb') as fhandle: - SendMimeTypeData(fhandle, - filename if filenameMeta is None else filenameMeta, - mimeType, - charset, - filesize=filesize, - download=download) - -def SendMimeTypeDataFromStdin(mimeType, charset, filenameMeta=None, download=False): - SendMimeTypeData(sys.stdin.buffer, filenameMeta, mimeType, charset, download) - -def SendMimeTypeData(fhandle, filename, mimeType, charset, filesize=-1, download=False): - TurnOffEcho() - - extratermclient.startFileTransfer(mimeType, charset, filename, filesize=filesize, download=download) - contents = fhandle.read(MAX_CHUNK_BYTES) - - previousHash = b"" - previousHashHex = "" - while len(contents) != 0: - hash = hashlib.sha256() - hash.update(previousHash) - hash.update(contents) - print("D:", end='') - print(base64.b64encode(contents).decode(), end='') - print(":", end='') - previousHashHex = hash.hexdigest() - print(previousHashHex) - previousHash = hash.digest() - contents = fhandle.read(MAX_CHUNK_BYTES) - print("E::", end='') - hash = hashlib.sha256() - hash.update(previousHash) - print(hash.hexdigest()) - - extratermclient.endFileTransfer() - -def ShowFile(filename, mimeType=None, charset=None, filenameMeta=None, download=False): - if os.path.exists(filename): - SendMimeTypeDataFromFile(filename, mimeType, charset, filenameMeta, download) - return 0 - else: - print("Unable to open file {0}.".format(filename)) - return 3 - -def ShowStdin(mimeType=None, charset=None, filenameMeta=None, download=False): - SendMimeTypeDataFromStdin(mimeType, charset, filenameMeta, download) - -def TurnOffEcho(): - # Turn off echo on the tty. - fd = sys.stdin.fileno() - if not os.isatty(fd): - return - old_settings = termios.tcgetattr(fd) - new_settings = termios.tcgetattr(fd) - new_settings[3] = new_settings[3] & ~termios.ECHO # lflags - termios.tcsetattr(fd, termios.TCSADRAIN, new_settings) - - # Set up a hook to restore the tty settings at exit. - def restoreTty(): - termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) - sys.stderr.flush() - atexit.register(restoreTty) - -def main(): - parser = argparse.ArgumentParser(prog='show', description='Show a file inside Extraterm.') - parser.add_argument('--charset', dest='charset', action='store', default=None, help='the character set of the input file (default: UTF8)') - parser.add_argument('-d', '--download', dest='download', action='store_true', default=None, help='download the file and don\'t show it') - parser.add_argument('--mimetype', dest='mimetype', action='store', default=None, help='the mime-type of the input file (default: auto-detect)') - parser.add_argument('--filename', dest='filename', action='store', default=None, help='sets the file name in the metadata sent to the terminal (useful when reading from stdin).') - parser.add_argument('-t', '--text', dest='text', action='store_true', default=None, help='Treat the file as plain text.') - parser.add_argument('files', metavar='file', type=str, nargs='*', help='file name. The file data is read from stdin if no files are specified.') - args = parser.parse_args() - - if not extratermclient.isExtraterm(): - print("Sorry, you're not using Extraterm as your terminal.") - return 1 - - mimetype = args.mimetype - if args.text: - mimetype = "text/plain" - - if len(args.files) != 0: - for filename in args.files: - result = ShowFile(filename, mimeType=mimetype, charset=args.charset, filenameMeta=args.filename, - download=args.download) - if result != 0: - return result - return 0 - else: - return ShowStdin(mimeType=mimetype, charset=args.charset, filenameMeta=args.filename, - download=args.download) - -main() diff --git a/.config/fish/extraterm/extratermclient.py b/.config/fish/extraterm/extratermclient.py deleted file mode 100644 index ad19cb0..0000000 --- a/.config/fish/extraterm/extratermclient.py +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2014-2017 Simon Edwards -# -# This source code is licensed under the MIT license which is detailed in the LICENSE.txt file. -# - -import os -import sys -import json - - -class extratermclient: - - INTRO = "\x1b&" - - def cookie(): - if "LC_EXTRATERM_COOKIE" in os.environ: - return os.environ["LC_EXTRATERM_COOKIE"] - else: - return None - - def isExtraterm(): - return extratermclient.cookie() is not None - - def startHtml(): - print(extratermclient.INTRO + extratermclient.cookie() + "\x07", end="") - - def endHtml(): - print("\x00", end="") - - def startCommand(): - pass - - def markEndCommand(rc=None): - print(extratermclient.INTRO + extratermclient.cookie() + ";3\x07", end="") - if rc is not None: - print(rc, end="") - print("\x00", end="") - - def startFileTransfer(mimeType, charset, filename, filesize=-1, download=False): - payload = {} - if mimeType is not None: - payload["mimeType"] = mimeType - if filename is not None: - payload["filename"] = filename - if charset is not None: - payload["charset"] = charset - if filesize != -1: - payload["filesize"] = filesize - if download: - payload["download"] = "true" - jsonPayload = json.dumps(payload) - print(extratermclient.INTRO + extratermclient.cookie() + ";5;" + str(len(jsonPayload)) + "\x07" + jsonPayload, end="") - - def endFileTransfer(): - print("\x00", end="") - - def requestFrame(frameName): - print(extratermclient.INTRO + extratermclient.cookie() + ";4\x07" + frameName + "\x00", end="", file=sys.stderr) - sys.stderr.flush() diff --git a/.config/fish/extraterm/setup_extraterm_bash.sh b/.config/fish/extraterm/setup_extraterm_bash.sh deleted file mode 100644 index b24e99a..0000000 --- a/.config/fish/extraterm/setup_extraterm_bash.sh +++ /dev/null @@ -1,66 +0,0 @@ -# This file should be sourced from your .bashrc file. -# -# Copyright 2014-2019 Simon Edwards -# -# This source code is licensed under the MIT license which is detailed in the LICENSE.txt file. -# - -# Early-out in case this has been sourced and enabled already -# https://github.com/sedwards2009/extraterm/pull/148 - -isfunction () { - type $1 2> /dev/null | head -n1 | grep "$1 is a function" > /dev/null -} - -if ( isfunction "postexec" ); then return 0; fi -if ( isfunction "preexec" ); then return 0; fi -if ( isfunction "preexec_invoke_exec" ); then return 0; fi - -# Early-out if LC_EXTRATERM_COOKIE is not set -if [ -z "$LC_EXTRATERM_COOKIE" ]; then return 0; fi -if [[ "$TERM" =~ 'screen' ]]; then - unset -v LC_EXTRATERM_COOKIE - return 0; -fi - -echo "Setting up Extraterm support." - -# Put our enhanced commands at the start of the PATH. -filedir=`dirname "$BASH_SOURCE"` -if [ ${filedir:0:1} != "/" ] -then - filedir="$PWD/$filedir" -fi - -export PATH="$filedir:$PATH" - -PREVIOUS_PROMPT_COMMAND=$PROMPT_COMMAND -postexec () { - echo -n -e "\033&${LC_EXTRATERM_COOKIE};3\007" - echo -n $1 - echo -n -e "\000" - $PREVIOUS_PROMPT_COMMAND -} -export PROMPT_COMMAND="postexec \$?" - -preexec () { - echo -n -e "\033&${LC_EXTRATERM_COOKIE};2;bash\007" - echo -n $1 - echo -n -e "\000" -} - -preexec_invoke_exec () { - [ -n "$COMP_LINE" ] && return # do nothing if completing - [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND - local this_command=`history 1`; # obtain the command from the history - preexec "$this_command" -} -trap 'preexec_invoke_exec' DEBUG - -# Look for Python 3 support. -if ! which python3 > /dev/null; then - echo "Unable to find the Python3 executable!" -else - alias from="exfrom.py" - alias show="exshow.py" -fi diff --git a/.config/fish/extraterm/setup_extraterm_fish.fish b/.config/fish/extraterm/setup_extraterm_fish.fish deleted file mode 100644 index 6c81ab9..0000000 --- a/.config/fish/extraterm/setup_extraterm_fish.fish +++ /dev/null @@ -1,41 +0,0 @@ -# This file should be sourced from your ~/.config/config.fish file. -# -# Copyright 2014-2019 Simon Edwards -# -# This source code is licensed under the MIT license which is detailed in the LICENSE.txt file. -# - -if test -z "$LC_EXTRATERM_COOKIE" - exit 0 -end - -if echo "$TERM" | grep -q -E '^screen' - set -e LC_EXTRATERM_COOKIE - exit 0 -end - -#echo "Setting up Extraterm support." - -set -l filedir (dirname (status -f)) -set COMMAND_DIR (python3 -c import\ os.path\nimport\ sys\nprint\(os.path.abspath\(sys.argv\[1\]\)\)\n "$filedir") - -function extraterm_preexec -e fish_preexec - echo -n -e -s "\033&" $LC_EXTRATERM_COOKIE ";2;fish\007" - echo -n $argv[1] - echo -n -e "\000" -end - -function extraterm_postexec -e fish_postexec - set -l status_backup $status - echo -n -e -s "\033" "&" $LC_EXTRATERM_COOKIE ";3\007" - echo -n $status_backup - echo -n -e "\000" -end - -function from - python3 $COMMAND_DIR/exfrom.py $argv -end - -function show - python3 $COMMAND_DIR/exshow.py $argv -end diff --git a/.config/fish/extraterm/setup_extraterm_zsh.zsh b/.config/fish/extraterm/setup_extraterm_zsh.zsh deleted file mode 100644 index c5a14ca..0000000 --- a/.config/fish/extraterm/setup_extraterm_zsh.zsh +++ /dev/null @@ -1,53 +0,0 @@ -# This file should be sourced from your .zshrc file. -# -# Copyright 2016-2019 Simon Edwards -# -# This source code is licensed under the MIT license which is detailed in the LICENSE.txt file. -# - -if [ -z "$LC_EXTRATERM_COOKIE" ]; then - return 0 -fi -if [[ "$TERM" =~ "screen" ]]; then - unset -v LC_EXTRATERM_COOKIE - return 0 -fi - -autoload -Uz add-zsh-hook - -echo "Setting up Extraterm support." - -# Put our enhanced commands at the start of the PATH. -filedir=`dirname "${(%):-%x}"` -if [ "${filedir:0:1}" = "/" ] -then - export PATH="$filedir:$PATH" -else - export PATH="$PWD/$filedir:$PATH" -fi - -# Insert our special code to communicate to Extraterm the status of the last command. -extraterm_install_prompt_integration () { - local prefix - - if [[ ! "$PS1" =~ "$LC_EXTRATERM_COOKIE" ]] ; then - prefix=`echo -n -e "%{\0033&${LC_EXTRATERM_COOKIE};3\0007%}%?%{\0000%}"` - export PS1="${prefix}${PS1}" - fi -} -extraterm_install_prompt_integration -add-zsh-hook precmd extraterm_install_prompt_integration - -preexec () { - echo -n -e "\0033&${LC_EXTRATERM_COOKIE};2;zsh\0007" - echo -n $1 - echo -n -e "\0000" -} - -# Look for Python 3 support. -if ! which python3 > /dev/null; then - echo "Unable to find the Python3 executable!" -else - alias from="exfrom.py" - alias show="exshow.py" -fi diff --git a/.config/fish/functions/__fastdir_cd_num.fish b/.config/fish/functions/__fastdir_cd_num.fish old mode 100755 new mode 100644 diff --git a/.config/flake8 b/.config/flake8 old mode 100755 new mode 100644 diff --git a/.config/pep8 b/.config/pep8 old mode 100755 new mode 100644 diff --git a/.github/workflows/ubuntu-latest.yml b/.github/workflows/ubuntu-latest.yml index 16f2ac7..6c7a466 100644 --- a/.github/workflows/ubuntu-latest.yml +++ b/.github/workflows/ubuntu-latest.yml @@ -1,16 +1,22 @@ name: validate-dotfiles -on: [push] +on: [push, pull_request] + jobs: - fish-syntax-check: + pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: fish-actions/install-fish@v1.1.0 - - run: fish -n fish/.config/fish/config.fish - vimlint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - - run: npm install vimlint --save - - run: ./node_modules/vimlint/bin/vimlint vim/.vimrc + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.13' # Use 3.13 for better compatibility + - name: Install fish shell + run: | + sudo apt-add-repository ppa:fish-shell/release-3 -y + sudo apt-get update + sudo apt-get install -y fish + - name: Cache pre-commit environments + uses: actions/cache@v4 + with: + path: ~/.cache/pre-commit + key: pre-commit-3|${{ runner.os }}|${{ hashFiles('.pre-commit-config.yaml') }} + - uses: pre-commit/action@v3.0.1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9c78a54..cb4c91d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,8 +1,19 @@ +# Pre-commit hooks - Modernized for 2026 +# Using ruff for Python (replaces flake8, isort, black, pyupgrade, etc.) + default_install_hook_types: - pre-commit - commit-msg +# Global excludes for third-party/generated files +exclude: | + (?x)^( + .*__bass\.py$| # bass plugin (third-party) + .*/ipython_config\.py$ # IPython generated config + )$ + repos: + # Standard pre-commit hooks - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: @@ -10,17 +21,60 @@ repos: - id: end-of-file-fixer - id: check-yaml - id: check-added-large-files + - id: check-executables-have-shebangs + - id: check-shebang-scripts-are-executable + - id: check-merge-conflict + - id: check-json + - id: check-toml + + # Conventional commits - repo: https://github.com/compilerla/conventional-pre-commit rev: v4.2.0 hooks: - id: conventional-pre-commit stages: [commit-msg] + + # Markdown linting - repo: https://github.com/igorshubovych/markdownlint-cli rev: v0.45.0 hooks: - id: markdownlint files: \.(md|markdown)$ + + # Secret scanning - repo: https://github.com/gitleaks/gitleaks rev: v8.28.0 hooks: - id: gitleaks + + # YAML linting + - repo: https://github.com/adrienverge/yamllint + rev: v1.35.1 + hooks: + - id: yamllint + args: ['-c', 'linters/.yamllint'] + + # Shell script validation + - repo: https://github.com/shellcheck-py/shellcheck-py + rev: v0.10.0.1 + hooks: + - id: shellcheck + files: ^setup-.*$|\.sh$ + args: ['--severity=warning'] + + # Fish syntax checking (local hook) + - repo: local + hooks: + - id: fish-syntax-check + name: fish syntax check + entry: fish --no-execute + language: system + files: \.fish$ + + # Ruff - Modern Python linter & formatter (replaces flake8, isort, black, pyupgrade) + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.15.0 + hooks: + - id: ruff + args: ['--fix'] + - id: ruff-format diff --git a/.vim/autoload/pathogen.vim b/.vim/autoload/pathogen.vim old mode 100755 new mode 100644 diff --git a/README.md b/README.md index 48d2961..8edcbec 100644 --- a/README.md +++ b/README.md @@ -10,3 +10,36 @@ Run `./setup-debian` ## MacOS Run `./setup-macos` + +## Development + +This repository uses [pre-commit](https://pre-commit.com/) to validate changes. + +### Setup + +```bash +pip install pre-commit +pre-commit install +``` + +### Usage + +```bash +# Run all hooks on all files +pre-commit run --all-files + +# Run on staged files only +pre-commit run +``` + +### Configured Hooks + +- Shell script validation (shellcheck) +- Fish syntax checking +- Python linting & formatting (ruff) +- YAML linting (yamllint) +- Markdown linting (markdownlint) +- JSON/TOML validation +- Trailing whitespace/EOF fixes +- Secret detection (gitleaks) +- Conventional commit messages diff --git a/fish/.config/fish/functions/__fastdir_cd_num.fish b/fish/.config/fish/functions/__fastdir_cd_num.fish old mode 100755 new mode 100644 diff --git a/linters/.config/flake8 b/linters/.config/flake8 old mode 100755 new mode 100644 diff --git a/linters/.config/pep8 b/linters/.config/pep8 old mode 100755 new mode 100644 diff --git a/linters/.config/pycodestyle b/linters/.config/pycodestyle old mode 100755 new mode 100644 diff --git a/linters/.yamllint b/linters/.yamllint index 0b7dcdc..24e65b6 100644 --- a/linters/.yamllint +++ b/linters/.yamllint @@ -3,8 +3,10 @@ rules: colons: max-spaces-after: 1 max-spaces-before: 1 - key-ordering: {} + # Disabled - too strict for practical use + key-ordering: disable line-length: + max: 120 allow-non-breakable-inline-mappings: true yaml-files: - '*.yaml' diff --git a/setup-generic b/setup-generic index 2188f91..93342f2 100755 --- a/setup-generic +++ b/setup-generic @@ -6,7 +6,7 @@ if ! command -v pipx >/dev/null 2>&1; then echo "Installing pipx..." brew install pipx pipx ensurepath - set -gx PATH "$HOME/.local/bin" $PATH # Add manually once, or add to fish config permanently + export PATH="$HOME/.local/bin:$PATH" # Add manually once, or add to fish config permanently fi # Upgrade/install Python CLI tools with pipx @@ -76,9 +76,9 @@ if ! command -v kubectl-krew 2>/dev/null 2>&1; then ( set -x cd "$(mktemp -d)" - set OS=$(uname | tr '[:upper:]' '[:lower:]') - set ARCH=$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/') - set KREW "krew-${OS}_${ARCH}" + OS="$(uname | tr '[:upper:]' '[:lower:]')" + ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" + KREW="krew-${OS}_${ARCH}" curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz" tar zxvf "${KREW}.tar.gz" ./"${KREW}" install krew