diff --git a/.emacs.d/init.el b/.emacs.d/init.el index 11bfab5..3c8b9c2 100644 --- a/.emacs.d/init.el +++ b/.emacs.d/init.el @@ -1,46 +1,100 @@ +;;; init.el --- Coast's ~/.emacs.d/init.el +;; +;;; Commentary: +;; This is my GNU/Emacs configuration -- +;; It has: +;; - (TEMPORARY) Evil mode; as I've gotten used to Vim binds when I was away from GNU/Emacs for a bit. +;; - Automatic syntax-highlighting. +;; - Has a minimap. +;; - Bad theme; it's fine on my eyes, though -- I like the 'solarized' theme >:3 +;; - It's also gay. +;; +;;; Code: +;; (require 'package) (setq package-archives - '(("gnu" . "https://elpa.gnu.org/packages/") + '(("gnu" . "https://elpa.gnu.org/packages/") ("melpa" . "https://melpa.org/packages/"))) (package-initialize) (unless package-archive-contents (package-refresh-contents)) (require 'use-package) +;;; Message: +;; "run" command (M-x / evil) +(defun coast/run-current-file () + (interactive) + (let ((file (buffer-file-name))) + (cond + ((not file) + (message "no file to run!")) + ((string-match "\\.py\\'" file) + (compile (format "python3 %s" file))) + ((string-match "\\.c\\'" file) + (let* ((out (concat (file-name-sans-extension file) ".out"))) + (compile (format "gcc %s -o %s && %s" file out out)))) + ((string-match "\\.sh\\'" file) + (compile (format "bash %s" file))) + ((string-match "\\.rs\\'" file) + (let* ((out (file-name-sans-extension file))) + (compile (format "rustc %s && %s" file out)))) + ((string-match "\\.lua\\'" file) + (compile (format "lua %s" file))) + ((string-match "\\.js\\'" file) + (compile (format "node %s" file))) + ((coast/file-has-shebang-p file) + (compile (format "%s" file))) + (t (message "dunno how to run this file >:("))))) + +(defun coast/file-has-shebang-p (file) + (when (and file (file-readable-p file)) + (with-temp-buffer + (insert-file-contents-literally file nil 0 128) + (goto-char (point-min)) + (looking-at "^#!")))) + +(defalias 'run #'coast/run-current-file) + (menu-bar-mode -1) (tool-bar-mode -1) (scroll-bar-mode -1) (global-display-line-numbers-mode 1) (global-hl-line-mode 1) +(electric-pair-mode 1) -(use-package rainbow-mode :ensure t :hook (prog-mode . rainbow-mode)) -(use-package all-the-icons :ensure t :if (display-graphic-p)) -(use-package elcord :ensure t :config (elcord-mode 1)) +(setq-default electric-pair-pairs + '((?\" . ?\") + (?\{ . ?\}) + (?\( . ?\)) + (?\[ . ?\]) + (?\< . ?\>))) -(load-theme 'doom-ir-black t) +(setq-default electric-pair-text-pairs electric-pair-pairs) -(set-frame-parameter (selected-frame) 'alpha '(90 . 90)) -(add-to-list 'default-frame-alist '(alpha . (90 . 90))) +(set-frame-parameter (selected-frame) 'alpha '(95 . 95)) +(add-to-list 'default-frame-alist '(alpha . (95 . 95))) -(set-face-attribute 'default nil :family "Departure Mono" :height 130) +(set-face-attribute 'default nil :family "Inconsolata" :height 180) -(setq backup-directory-alist - `((".*" . "~/.local/tmp/emacsbackup/"))) +(setq backup-directory-alist `((".*" . "~/.local/tmp/emacsbackup/"))) (setq make-backup-files t) (setq backup-by-copying t) -(use-package neotree :ensure t :bind ("" . neotree-toggle)) +(use-package solarized-theme :ensure t) +(load-theme 'solarized-selenized-dark t) -(use-package vertico - :ensure t - :config - (vertico-mode 1)) +(use-package all-the-icons :ensure t :if (display-graphic-p)) +(use-package rainbow-mode :ensure t :hook (prog-mode . rainbow-mode)) +(use-package elcord :ensure t :config (elcord-mode 1)) -(use-package marginalia :ensure t :hook (vertico-mode . marginalia-mode)) +(use-package neotree :ensure t :bind ("" . neotree-toggle)) +(use-package vertico :ensure t :config (vertico-mode 1)) +(use-package marginalia :ensure t :hook (vertico-mode . marginalia-mode)) (use-package consult :ensure t - :bind (("C-s" . consult-line) ("C-x b" . consult-buffer))) + :bind (("C-x b" . consult-buffer) + ("C-s" . consult-line))) (use-package which-key :ensure t :config (which-key-mode 1)) @@ -48,19 +102,7 @@ (use-package yasnippet :ensure t :hook (prog-mode . yas-minor-mode)) (use-package flycheck :ensure t :hook (prog-mode . flycheck-mode)) -(use-package lsp-mode - :ensure t - :commands lsp - :init (setq lsp-keymap-prefix "C-c l") - :hook ((java-mode c-mode sh-mode python-mode rust-mode go-mode typescript-mode - lua-mode zig-mode web-mode) . lsp)) - -(use-package lsp-ui - :ensure t - :config (require 'lsp-java-boot)) - (global-set-key (kbd "C-c t") 'ansi-term) -(global-set-key (kbd "C-s") 'swiper) (use-package web-mode :ensure t @@ -76,95 +118,131 @@ :config (setq emmet-expand-jsx-className? t)) -(electric-pair-mode 1) -(setq electric-pair-pairs '((?\" . ?\") (?\{ . ?\}) (?\( . ?\)) (?\[ . ?\]) (?\< . ?\>))) -(setq electric-pair-text-pairs electric-pair-pairs) - -(use-package nix-mode :ensure t :mode "\\.nix\\'") (use-package python :mode "\\.py\\'") (use-package sh-script :mode "\\.sh\\'") -(use-package fennel-mode :ensure t :mode "\\.fnl\\'" :hook (fennel-mode . macrostep-mode)) -(use-package macrostep :ensure t) -(use-package zig-mode :ensure t :mode "\\.zig\\'" :hook (zig-mode . lsp-deferred)) (use-package cc-mode) (use-package markdown-mode :ensure t :mode "\\.md\\'") -(use-package lua-mode :ensure t :mode "\\.lua\\'") -(use-package rust-mode :ensure t :mode "\\.rs\\'") -(use-package go-mode :ensure t :mode "\\.go\\'") -(use-package typescript-mode :ensure t :mode "\\.ts\\'") -(use-package toml-mode :ensure t :mode "\\.toml\\'") (use-package yaml-mode :ensure t :mode "\\.ya?ml\\'") -(use-package tuareg - :ensure t - :mode ("\\.ml\\'" "\\.mli\\'") - :hook (tuareg-mode . merlin-mode)) +(use-package macrostep :ensure t) -(use-package merlin +;;; Message: +;; Language-setup. +(use-package python + :mode ("\\.py\\'" . python-mode) + :interpreter ("python" . python-mode)) + +(use-package rust-mode :ensure t - :hook ((tuareg-mode caml-mode) . merlin-mode) - :config - (setq merlin-command 'opam)) + :mode ("\\.rs\\'" . rust-mode)) + +(use-package sh-script + :mode (("\\.sh\\'" . sh-mode) + ("\\.bash\\'" . sh-mode) + ("\\.zsh\\'" . sh-mode)) + :interpreter (("bash" . sh-mode) + ("sh" . sh-mode) + ("zsh" . sh-mode))) -(use-package merlin-eldoc +(use-package lua-mode :ensure t - :hook (merlin-mode . merlin-eldoc-setup)) + :mode ("\\.lua\\'" . lua-mode)) -(use-package utop +(use-package cc-mode + :mode (("\\.c\\'" . c-mode) + ("\\.h\\'" . c-mode) + ("\\.cpp\\'" . c++-mode) + ("\\.hpp\\'" . c++-mode)) + :interpreter (("c" . c-mode) + ("cpp" . c++-mode))) + +(use-package markdown-mode :ensure t - :hook (tuareg-mode . utop-minor-mode) - :config - (setq utop-command "utop -emacs")) + :mode ("\\.md\\'" . markdown-mode)) -(use-package ocamlformat +(use-package yaml-mode :ensure t - :hook (tuareg-mode . ocamlformat-setup-indent) - :custom - (ocamlformat-enable 'enable-outside-detected-project)) + :mode ("\\.ya?ml\\'" . yaml-mode)) +;;; Message +;; -- Set window title -- +(setq frame-title-format '("%b —— GNU/Emacs")) + +;;; Message: +;; -- The below may have been temporarily added -- (use-package doom-modeline :ensure t :init - (setq doom-modeline-height 25) - (setq doom-modeline-bar-width 3) - (setq doom-modeline-buffer-file-name-style 'truncate-with-project) - (setq doom-modeline-icon t) - (setq doom-modeline-major-mode-icon t) - (setq doom-modeline-enable-word-count t) - (setq doom-modeline-vcs-max-length 12) - (setq doom-modeline-mode-icon nil) - (setq doom-modeline-minor-modes nil) + (setq doom-modeline-height 25 + doom-modeline-bar-width 3 + doom-modeline-buffer-file-name-style 'truncate-with-project + doom-modeline-icon t + doom-modeline-major-mode-icon t + doom-modeline-enable-word-count t + doom-modeline-vcs-max-length 12 + doom-modeline-minor-modes nil) + :config + (doom-modeline-mode 1)) + +(setq evil-want-keybinding nil) + +(use-package evil + :ensure t + :init (setq evil-want-integration t + evil-want-C-u-scroll t) + :config (evil-mode 1)) + +(use-package evil-collection + :after evil + :ensure t + :config (evil-collection-init)) + +(use-package evil-leader + :ensure t :config - (doom-modeline-mode 1) - (set-face-attribute 'mode-line nil - :background "#000000" - :foreground "#ffffff" - :box nil) - (set-face-attribute 'mode-line-inactive nil - :background "#111111" - :foreground "#888888" - :box nil)) + (global-evil-leader-mode) + (evil-leader/set-leader "") + (evil-leader/set-key + "f" 'find-file + "b" 'switch-to-buffer + "k" 'kill-buffer + "t" 'ansi-term + "e" 'eval-buffer + "r" 'coast/run-current-file)) + +(use-package evil-surround :ensure t :config (global-evil-surround-mode 1)) +(use-package evil-commentary :ensure t :config (evil-commentary-mode 1)) + +(use-package corfu + :ensure t + :custom + (corfu-auto t) + (corfu-cycle t) + (corfu-quit-no-match nil) + :init + (global-corfu-mode)) + +(use-package cape + :ensure t) + +(defun my/evil-ex-corfu-setup () + (setq-local completion-at-point-functions + (list (cape-super-capf #'completion-at-point)))) + +(add-hook 'evil-ex-completion-hook #'my/evil-ex-corfu-setup) (custom-set-variables ;; custom-set-variables was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. - '(custom-safe-themes - '("014cb63097fc7dbda3edf53eb09802237961cbb4c9e9abd705f23b86511b0a69" - "c5801b68568b59976a8e58104c40c9b052d46cca72e367c2e43c1f36a9e79abb" - default)) - '(package-selected-packages - '(all-the-icons company consult doom-modeline doom-themes elcord - emmet-mode fennel-mode flycheck go-mode lsp-java - lsp-ui lua-mode macrostep marginalia merlin - merlin-eldoc nano-modeline neotree nix-mode - ocaml-eglot ocamlformat rainbow-mode rust-mode - swiper toml-mode tuareg typescript-mode utop - vertico web-mode yaml-mode yasnippet zig-mode))) + '(warning-suppress-log-types '((use-package)))) (custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. ) + +(provide 'init) +;;; init.el ends here diff --git a/local/bin/math b/local/bin/math index b61e07b..a817382 100755 --- a/local/bin/math +++ b/local/bin/math @@ -49,7 +49,7 @@ _CONSTANTS = { "nan": math.nan, } -class MathEvaluator(ast.NodeVisitor): +class matheval(ast.NodeVisitor): def visit(self, node): if isinstance(node, ast.Expression): return self.visit(node.body) @@ -110,7 +110,7 @@ def main(): try: tree = ast.parse(expr, mode="eval") - evaluator = MathEvaluator() + evaluator = matheval() result = evaluator.visit(tree) if isinstance(result, float) and result.is_integer(): print(int(result)) diff --git a/local/bin/screenie b/local/bin/screenie index cc8c43a..38ddb21 100755 --- a/local/bin/screenie +++ b/local/bin/screenie @@ -1,72 +1,92 @@ -#!/usr/bin/env bash -set -euo pipefail -export DISPLAY="${DISPLAY:-:0}" +#!/usr/bin/env python3 +import os +import sys +import subprocess +import tempfile +from pathlib import Path +from datetime import datetime -# Dependencies check -for cmd in xclip import notify-send; do command -v "$cmd" &>/dev/null || { echo "Missing: $cmd" >&2; exit 1; }; done +def check_cmds(cmds): + for cmd in cmds: + if subprocess.call(["which", cmd], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) != 0: + print(f"Missing: {cmd}", file=sys.stderr) + sys.exit(1) -OUTDIR="${2:-$HOME/files/pics/screenies}"; mkdir -p "$OUTDIR" -FILE="$OUTDIR/$(date +%Y%m%d_%H%M%S).png" -TMP=$(mktemp --suffix=.png); trap 'rm -f "$TMP"' EXIT +def show_help(): + print(f"""Usage: {sys.argv[0]} [color|full|window] [output_dir]\nEnvironment options:\n WATERMARK=1\n WATERMARK_TEXT='text'\n WATERMARK_POS=position\n WATERMARK_SIZE=px\n WATERMARK_BG='#rrggbbaa'\n""") -show_help(){ - cat </dev/null || { echo "Missing: magick" >&2; exit 1; } - # Watermark subsystem (env overrides supported) - magick "$FILE" \ - -gravity "${WATERMARK_POS:-southeast}" \ - -pointsize "${WATERMARK_SIZE:-28}" \ - -fill white -undercolor "${WATERMARK_BG:-#00000080}" \ - -annotate +20+20 "${WATERMARK_TEXT:-$(date '+%Y-%m-%d %H:%M')}" \ - "$FILE" - } - xclip -selection clipboard -t image/png -i "$FILE" && notify-send -i "$FILE" "Screenshot: $(basename "$FILE")" -} +def colorpicker(tmp): + check_cmds(["magick"]) + if subprocess.call(["which", "slop"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0: + slop = subprocess.run(["slop", "--tolerance=0"], capture_output=True, text=True) + if slop.returncode != 0: + sys.exit(1) + crop = slop.stdout.strip() + subprocess.run(["import", "-window", "root", "-crop", crop, tmp], check=True) + else: + subprocess.run(["import", tmp], check=True) + try: + hexcolor = subprocess.check_output([ + "magick", tmp, "-scale", "1x1!", "-format", "#%[hex:p{0,0}]", "info:" + ], stderr=subprocess.DEVNULL, text=True).strip() + except subprocess.CalledProcessError: + hexcolor = "#??????" + subprocess.run(["xclip", "-selection", "clipboard", "-i"], input=hexcolor.encode(), check=True) + subprocess.run(["notify-send", "-i", tmp, f"Color: {hexcolor}"], check=True) -colorpicker(){ - command -v magick &>/dev/null || { notify-send "Missing: magick"; exit 1; } - if command -v slop &>/dev/null; then - import -window root -crop "$(slop --tolerance=0 || exit 1)" "$TMP" - else - import "$TMP" - fi - hex=$(magick "$TMP" -scale 1x1\! -format "#%[hex:p{0,0}]" info: 2>/dev/null || echo "#??????") - echo "$hex" | xclip -selection clipboard -i && notify-send -i "$TMP" "Color: $hex" -} +def capture_full(file): + subprocess.run(["import", "-window", "root", file], check=True) + post(file) -capture_full(){ - import -window root "$FILE" && post -} +def capture_window(file): + check_cmds(["xdotool"]) + winid = subprocess.check_output(["xdotool", "getwindowfocus", "-f"], text=True).strip() + subprocess.run(["import", "-window", winid, file], check=True) + post(file) -capture_window(){ - command -v xdotool &>/dev/null || { echo "Missing: xdotool" >&2; exit 1; } - import -window "$(xdotool getwindowfocus -f)" "$FILE" && post -} +def capture_selection(file): + subprocess.run(["import", file], check=True) + post(file) -capture_selection(){ - import "$FILE" && post -} +def main(): + check_cmds(["xclip", "import", "notify-send"]) + outdir = Path(sys.argv[2]) if len(sys.argv) > 2 else Path.home() / "files" / "pics" / "screenies" + outdir.mkdir(parents=True, exist_ok=True) + file = str(outdir / (datetime.now().strftime("%Y%m%d_%H%M%S") + ".png")) + with tempfile.NamedTemporaryFile(suffix=".png", delete=True) as tmp: + if len(sys.argv) > 1: + arg = sys.argv[1] + else: + arg = "" + if arg in ("-h", "--help"): + show_help() + elif arg.startswith("color"): + colorpicker(tmp.name) + elif arg == "full": + capture_full(file) + elif arg == "window": + capture_window(file) + else: + capture_selection(file) -main(){ - case "${1:-}" in - -h|--help) show_help ;; - color*) colorpicker ;; - full) capture_full ;; - window) capture_window ;; - *) capture_selection ;; - esac -} - -main "$@" +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/local/bin/yellusb b/local/bin/yellusb new file mode 100755 index 0000000..1f53ecd --- /dev/null +++ b/local/bin/yellusb @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import pyudev +import subprocess + +context = pyudev.Context() +monitor = pyudev.Monitor.from_netlink(context) +monitor.filter_by(subsystem='block') + +for device in iter(monitor.poll, None): + if device.action == 'add': + print(f"New device detected: {device.device_node}") + subprocess.run(f"notify-send 'New device connected: {device.device_node}'", shell=True) \ No newline at end of file