├── .bash_profile ├── .config ├── X11 │ └── Xmodmap ├── abook │ └── abookrc ├── alacritty │ └── alacritty.yml ├── bash_profile ├── beets │ ├── .gitignore │ └── config.yaml ├── calcurse │ ├── conf │ ├── hooks │ │ ├── post-save │ │ └── pre-load │ └── keys ├── clone-repos.yaml ├── clone-repos │ ├── computer-clone-repos.yaml │ ├── hpi-clone-repos.yaml │ ├── ranger-plugins.yaml │ ├── todotxt-actions.yaml │ └── update-forks.yaml ├── codespell │ └── codespell.conf ├── cookiecutterrc ├── directories ├── dunst │ └── dunstrc ├── flake8 ├── fontconfig │ └── conf.d │ │ └── 01-emoji.conf ├── fzf_preview ├── gh-dash │ └── config.yml ├── gh │ └── config.yml ├── git_doc_history │ ├── frinkconv │ ├── mysql │ ├── newsboat │ ├── node │ ├── plaintext_playlist │ ├── ranger │ └── todo ├── glow │ └── glow.yml ├── htop │ └── htoprc ├── hypr │ ├── hyprland.conf │ └── hyprlock.conf ├── i3 │ ├── config │ ├── config.j2 │ └── config.yaml ├── i3blocks │ ├── blocks │ │ ├── b-battery │ │ ├── b-calendar │ │ ├── b-calories │ │ ├── b-comments │ │ ├── b-date │ │ ├── b-mail │ │ ├── b-mpv-description │ │ ├── b-mpv-paused │ │ ├── b-network │ │ ├── b-page-hits │ │ ├── b-reminder-sink │ │ ├── b-reminder-sink-json │ │ ├── b-reminders │ │ ├── b-rss │ │ ├── b-to-watch │ │ ├── b-todo │ │ ├── b-volume │ │ ├── b-water │ │ └── b-water-perc │ └── config ├── inputrc ├── irbrc ├── kitty │ ├── .gitignore │ ├── bgproc.conf │ ├── custom.conf │ ├── kitty.conf │ └── themes │ │ ├── Dark.conf │ │ └── Light.conf ├── lftp │ └── rc ├── lynx │ └── lynx.cfg ├── mpv │ ├── input.conf │ ├── mpv.conf │ ├── script-opts │ │ └── encode_web.conf │ └── scripts │ │ └── encode.lua ├── muttc │ ├── mailcap │ └── muttrc ├── my │ ├── .gitignore │ ├── .stignore │ └── my │ │ └── config │ │ ├── __init__.py │ │ ├── common.py │ │ ├── feed.py │ │ ├── pura │ │ ├── .gitignore │ │ ├── __init__.pyi │ │ ├── py.typed │ │ └── ttally_types.py │ │ └── reorder_path.py ├── newsboat │ └── config ├── newsraft │ └── config ├── nsxiv │ └── exec │ │ ├── image-info │ │ ├── key-handler │ │ └── win-title ├── nvim │ ├── .gitignore │ ├── after │ │ ├── ftplugin │ │ │ ├── gitcommit.lua │ │ │ ├── help.lua │ │ │ ├── lua.lua │ │ │ ├── markdown.lua │ │ │ ├── qf.lua │ │ │ ├── query.lua │ │ │ ├── sshconfig.lua │ │ │ └── zsh.lua │ │ └── plugin │ │ │ ├── helpers.lua │ │ │ ├── highlight.lua │ │ │ └── key_descriptions.lua │ ├── init.lua │ ├── lazy-lock.json │ ├── lua │ │ ├── plugins │ │ │ ├── cloak.lua │ │ │ ├── cmp.lua │ │ │ ├── codeium.lua │ │ │ ├── color.lua │ │ │ ├── comment.lua │ │ │ ├── conform.lua │ │ │ ├── dial.lua │ │ │ ├── gitsigns.lua │ │ │ ├── init.lua │ │ │ ├── language.lua │ │ │ ├── lint.lua │ │ │ ├── lsp.lua │ │ │ ├── luasnip.lua │ │ │ ├── mini.lua │ │ │ ├── neogit.lua │ │ │ ├── octo.lua │ │ │ ├── spectre.lua │ │ │ ├── telescope.lua │ │ │ ├── treesitter.lua │ │ │ ├── trouble.lua │ │ │ └── ui.lua │ │ └── user │ │ │ ├── autocmds.lua │ │ │ ├── codespell.lua │ │ │ ├── init.lua │ │ │ ├── key_mappings.lua │ │ │ ├── mapping_helpers.lua │ │ │ ├── patch_codeium.lua │ │ │ ├── remsync.lua │ │ │ ├── settings.lua │ │ │ ├── snippets.lua │ │ │ ├── telescope.lua │ │ │ └── terminal.lua │ ├── queries │ │ ├── bash │ │ │ ├── highlights.scm │ │ │ └── injections.scm │ │ ├── go │ │ │ └── injections.scm │ │ ├── markdown │ │ │ └── injections.scm │ │ ├── python │ │ │ └── injections.scm │ │ ├── query │ │ │ └── injections.scm │ │ └── rifleconfig │ │ │ └── injections.scm │ ├── selene.toml │ ├── snippets │ │ ├── cfg.snippets │ │ ├── python.snippets │ │ └── sh.snippets │ ├── stylua.toml │ └── vim.toml ├── picom.conf ├── plus1_blacklist.txt ├── promnesia │ └── config.py ├── pura_lua │ ├── pura_utils.lua │ └── terminal_colorscheme.lua ├── pyflyby │ └── imports.py ├── pythonrc ├── ranger │ ├── .gitignore │ ├── Makefile │ ├── commands.py │ ├── dir-aliases │ ├── generate_filter │ ├── generate_image_preview │ ├── hidden_template.rc │ ├── make │ ├── rc.conf │ ├── rifle.conf │ └── scope.sh ├── rifleman │ ├── format.conf │ ├── image.conf │ ├── lint.conf │ └── run.conf ├── rofi │ ├── config.rasi │ └── dracula.rasi ├── scramble_history │ ├── files.yaml │ └── sourcemap.json ├── screenlayout │ ├── auto.sh │ ├── desk_dual_monitor.sh │ └── single_laptop_screen.sh ├── shortcuts.toml ├── skhd │ └── skhdrc ├── so │ └── colors.toml ├── supervisord.conf ├── sway │ └── config ├── termite │ └── config ├── thefuck │ └── settings.py ├── todo │ └── config ├── tree-sitter │ └── config.json ├── ttally.py ├── user-dirs.dirs ├── user-dirs.locale ├── waybar │ ├── config.jsonc │ └── style.css ├── wezterm │ ├── clipboard.lua │ └── wezterm.lua ├── yadm │ ├── android_bootstrap │ ├── bootstrap │ ├── computer_bootstrap │ ├── copy-system-config │ ├── dotfiles_ignore_words.txt │ ├── hooks │ │ ├── commit-msg │ │ ├── post-merge │ │ └── pre-commit │ ├── linux_bootstrap │ ├── mac │ │ ├── set-default-apps │ │ └── set-macos-defaults │ ├── mac_bootstrap │ ├── package_lists │ │ ├── Brewfile │ │ ├── android_packages.txt │ │ ├── arch_packages.txt │ │ ├── arch_packages_wayland.txt │ │ ├── arch_packages_x11.txt │ │ ├── bash_packages.txt │ │ ├── cargo_packages.txt │ │ ├── computer_node_packages.txt │ │ ├── computer_python.txt │ │ ├── dart_packages.txt │ │ ├── gh_extension_packages.txt │ │ ├── go_packages.txt │ │ ├── linux_python3_packages.txt │ │ ├── mix_archive_packages.txt │ │ ├── node_packages.txt │ │ ├── ocaml_packages.txt │ │ ├── pipx_packages.txt │ │ ├── python3_packages.txt │ │ ├── ruby_packages.txt │ │ └── wsl_packages.txt │ ├── windows_bootstrap │ └── yadm-with-README.md └── zsh │ ├── .gitignore │ ├── .zshrc │ ├── aliases │ ├── aliases │ ├── dev_aliases │ ├── git_aliases │ └── project_aliases │ ├── android.zsh │ ├── cache_aliases.zsh │ ├── cd.zsh │ ├── completion.zsh │ ├── completions │ ├── _binary_completion │ ├── _plainplay │ ├── _services │ ├── _trackpad │ ├── _transparent │ └── _volume │ ├── env_config.zsh │ ├── functions.zsh │ ├── functions │ ├── add-to-path │ ├── cdp │ ├── cdtmp │ ├── duck │ ├── fkill │ ├── flocate │ ├── fpick │ ├── fwait │ ├── mkcd │ ├── ranger │ ├── tm │ ├── tmpick │ ├── update │ └── which-cat │ ├── generate_completion │ ├── global_env.sh │ ├── hpi.zsh │ ├── lazy.zsh │ ├── linux.zsh │ ├── mac.zsh │ ├── progressive_enhancement.zsh │ ├── prompt.zsh │ ├── source_aliases.zsh │ ├── ssh.zsh │ ├── updates.zsh │ └── windows.zsh ├── .gitignore ├── .keynavrc ├── .local ├── scripts │ ├── README.md │ ├── cross-platform │ │ ├── attached-to-terminal │ │ ├── editor │ │ ├── launch │ │ ├── lock-screen │ │ ├── playping │ │ └── print-or-notify │ ├── generic │ │ ├── abz │ │ ├── albumify-singles │ │ ├── ansicolors │ │ ├── audio2m4a │ │ ├── audio2mp3 │ │ ├── audio2ogg │ │ ├── audio2wav │ │ ├── audio2wavmono │ │ ├── audio2webm │ │ ├── audio2wma │ │ ├── auto-subtitle-install │ │ ├── autoformat-json │ │ ├── backup-keepass-db │ │ ├── basher-upgrade-all │ │ ├── bashx │ │ ├── beet-search │ │ ├── birthdays │ │ ├── blurred-html │ │ ├── bookmark-open │ │ ├── calcurse-nth │ │ ├── calcurse-upcoming │ │ ├── center-text │ │ ├── chafa-cache │ │ ├── click-repeat │ │ ├── clp │ │ ├── compile │ │ ├── copy-status │ │ ├── cstimer │ │ ├── current-week │ │ ├── datenow │ │ ├── decode64 │ │ ├── describe-evry-json │ │ ├── dict │ │ ├── discord-currently-listening-presence │ │ ├── discord-suppress │ │ ├── docx-md │ │ ├── dragon-sink │ │ ├── edit-github-readme │ │ ├── emoji │ │ ├── env-shebangs │ │ ├── exifalbumrename │ │ ├── exifattr │ │ ├── exifinfo │ │ ├── favorite-picture │ │ ├── ffmpeg-then-notify │ │ ├── figlet-one-line │ │ ├── file-modified-ago │ │ ├── file-modified-within │ │ ├── flipflop.py │ │ ├── generate-subs │ │ ├── genpass │ │ ├── ghstars │ │ ├── gifpreview │ │ ├── git-has-untracked-or-changes │ │ ├── git-https-ssh-swap │ │ ├── git-swap-remote │ │ ├── github-linguist │ │ ├── giturl │ │ ├── give │ │ ├── google-contacts-csv-extract │ │ ├── gpxsplit │ │ ├── gron-to-csv │ │ ├── havecmd │ │ ├── heart │ │ ├── how-old-am-i │ │ ├── image-shrink │ │ ├── in-path │ │ ├── install-nerd-font │ │ ├── jqc │ │ ├── jsonc-to-json │ │ ├── jumplist │ │ ├── kindle-send │ │ ├── linkhandler │ │ ├── list-git-dirs │ │ ├── list-my-git-repos │ │ ├── localize-datetimes │ │ ├── macho │ │ ├── mal_sources_toggle │ │ ├── manual_on_os │ │ ├── mbox-email-date │ │ ├── mbox-extract-text │ │ ├── mpv-album-playback │ │ ├── mpv-ffmpeg-extract │ │ ├── mpv-pause-all │ │ ├── mpv_signal_daemon │ │ ├── ms │ │ ├── mv-classify-videos-by-rotation │ │ ├── norg-to-markdown │ │ ├── nth-of-the-month │ │ ├── optigif │ │ ├── optijpg │ │ ├── org-to-md │ │ ├── photo-doc │ │ ├── photos-unsync-recent │ │ ├── picofy │ │ ├── plainplay-m3u │ │ ├── print-json │ │ ├── prompt_type │ │ ├── prune-folders-without-ext │ │ ├── qr │ │ ├── recompress-zip │ │ ├── reminder-sink-silence │ │ ├── remove-leading-spaces │ │ ├── rename-image-dt │ │ ├── rename-mpv-images │ │ ├── repos-dirty │ │ ├── repos-list │ │ ├── repos-pull-all │ │ ├── rg-nvim │ │ ├── rifleman-extract │ │ ├── rread │ │ ├── run_window_watcher │ │ ├── server_clipboard_notify │ │ ├── setup-cfg-fmt-tempfile │ │ ├── show-pickle │ │ ├── sign-canvas │ │ ├── spell-dotfiles │ │ ├── srt-to-text │ │ ├── star │ │ ├── status-code │ │ ├── sub-rename │ │ ├── super │ │ ├── sync-conflicts │ │ ├── terminal-set-theme │ │ ├── tiktok-local-rss │ │ ├── timer-till │ │ ├── tmux-kill-detached │ │ ├── to-github │ │ ├── to-gitlab │ │ ├── to-json-objects │ │ ├── todo-new │ │ ├── todo-prompt │ │ ├── todos │ │ ├── treesitter-not-ensured │ │ ├── ttt │ │ ├── tttlist │ │ ├── unstarred-nvim-plugins │ │ ├── update-my-stars │ │ ├── urlhandler │ │ ├── urlview │ │ ├── video2avi │ │ ├── video2mkv │ │ ├── video2mp4 │ │ ├── video2mp4-1080p │ │ ├── video2mp4-rotate │ │ ├── video2mpg │ │ ├── video2webm │ │ ├── videomp4-hardsub │ │ ├── vimdiff-syncthing-conflict │ │ ├── vitamin │ │ ├── wait-till-files │ │ ├── water-should-drink │ │ ├── wca-comps │ │ ├── wca-upcoming-competitions │ │ ├── weather │ │ ├── windows-ppas │ │ ├── with-secrets │ │ ├── youtube-dl-section │ │ ├── youtube-thumbnail │ │ ├── youtube-user-id │ │ └── youtube-user-rss-feed │ ├── linux │ │ ├── afk │ │ ├── battery │ │ ├── brightness │ │ ├── check-music-extensions │ │ ├── colorize_number │ │ ├── cstimer-server │ │ ├── flashlight │ │ ├── flatpak-run │ │ ├── focused-screen-index │ │ ├── focused-screen-resolution │ │ ├── gammastep-loc │ │ ├── gpg_autoclick │ │ ├── housekeeping │ │ ├── housekeeping-info │ │ ├── housekeeping-offline │ │ ├── hy │ │ ├── i3-is-floating-window │ │ ├── i3-launcher │ │ ├── i3-picture-in-picture │ │ ├── i3-resize │ │ ├── i3-sticky │ │ ├── i3blocks-parse-signals │ │ ├── i3blocks-refresh │ │ ├── i3blocks-refresh-all │ │ ├── i3blocks-refresh-mk │ │ ├── i3blocks-refresh-mpv │ │ ├── i3blocks-watch-mpv-daemon-logs │ │ ├── image-working-dir │ │ ├── launch-waybar │ │ ├── linux_tasks │ │ ├── mailsync-loop │ │ ├── main-screen-resolution │ │ ├── mpv-last-screenshot │ │ ├── notify-mpv-song-description │ │ ├── randomize-wallpaper │ │ ├── redshift-loc │ │ ├── refresh-block │ │ ├── restic-backup │ │ ├── screenshot │ │ ├── services │ │ ├── sonic-pi-run │ │ ├── stream-media │ │ ├── sw │ │ ├── sway-display-off │ │ ├── sway-resize │ │ ├── termcolors │ │ ├── tiktok-update-rss-feeds │ │ ├── timedatectl-timezone │ │ ├── timezone-has-changed │ │ ├── trackpad │ │ ├── trackpad-tap-to-click │ │ ├── transparent │ │ ├── update-rss │ │ ├── volume │ │ ├── warn-battery │ │ ├── waybar-refresh-all │ │ ├── waybar-refresh-block │ │ ├── waybar-signals │ │ ├── webcam-pic │ │ └── xmodmap-reset │ ├── notes_rendered │ │ ├── Makefile │ │ └── cache-srt-to-text │ ├── reminder-sink │ │ ├── flipflop │ │ ├── guestbook │ │ ├── last-export-dates │ │ └── listen_to_album │ ├── supervisor_jobs │ │ ├── all │ │ │ ├── cached_repo_bases.job │ │ │ ├── offline_listens_cache.job │ │ │ ├── promnesia_index.job │ │ │ ├── pull_dotfiles.job │ │ │ ├── sync_datafiles.job │ │ │ └── ttally_cache.job │ │ ├── android │ │ │ ├── backup_images.job │ │ │ ├── create_playlists.job │ │ │ └── delete_trash.job │ │ └── linux │ │ │ ├── build_exobrain.job │ │ │ ├── copy_images.job │ │ │ ├── generate_notes_journal_vlogs.job │ │ │ ├── linkmusic.job │ │ │ ├── my_feed_index_bg.job │ │ │ ├── mystars.job │ │ │ ├── tiktok.job │ │ │ ├── update_rss.job │ │ │ └── warn_mailsync.job │ └── todo-actions │ │ ├── Makefile │ │ ├── full │ │ └── interactive ├── share │ ├── firefox_addons.txt │ ├── gpg_autoclick │ │ ├── ok.png │ │ └── tick_box.png │ ├── ipython │ │ ├── profile_calculator │ │ │ └── startup │ │ │ │ └── 00-load-modules.py │ │ └── profile_default │ │ │ └── startup │ │ │ └── 00-pyflyby.ipy │ └── shortcuts │ │ ├── abookc │ │ ├── alacritty-tmux │ │ ├── alarm │ │ ├── albums │ │ ├── beet-export-all │ │ ├── beet-fix-renamed-files │ │ ├── boxes-nvim │ │ ├── boxes-python │ │ ├── boxes-vim │ │ ├── calcursed │ │ ├── camera │ │ ├── cheat │ │ ├── cl │ │ ├── cl-quickfix │ │ ├── clipedit │ │ ├── clipreset │ │ ├── clp-args │ │ ├── clr │ │ ├── clrs │ │ ├── codespell-conf │ │ ├── core │ │ ├── create-youtube-dl-resolution-str │ │ ├── curdir │ │ ├── current-city │ │ ├── cycle │ │ ├── dark-theme │ │ ├── discogs-search │ │ ├── discord-browser │ │ ├── dotfiles │ │ ├── draglastpic │ │ ├── drive-mount │ │ ├── ec │ │ ├── edit-clipboard │ │ ├── exo-web │ │ ├── extracturls │ │ ├── fdf │ │ ├── feed-open │ │ ├── file-mime │ │ ├── flake8c │ │ ├── fzf-edit │ │ ├── fzfp │ │ ├── genpass-phrase │ │ ├── gi │ │ ├── git-color │ │ ├── google-chrome-wifi-captive │ │ ├── google-search │ │ ├── grep-dotfiles │ │ ├── heart-cl │ │ ├── html-head-all │ │ ├── i3-jinja │ │ ├── i3binds │ │ ├── i3binds-prompt │ │ ├── img-download-drag │ │ ├── ipinfo │ │ ├── largechar-clipboard │ │ ├── lastpic │ │ ├── lastpicdrag │ │ ├── lastpicpreview │ │ ├── lessi │ │ ├── light-theme │ │ ├── list-config │ │ ├── list-config-no-hist │ │ ├── list-images │ │ ├── list-videos │ │ ├── listens-desc │ │ ├── longest-video │ │ ├── lynx │ │ ├── lynx-dump │ │ ├── lynx-from-stdin │ │ ├── mal-recent │ │ ├── markdown-list │ │ ├── mediasearch │ │ ├── moviesearch │ │ ├── moviesearch-letterboxd │ │ ├── moviesearch-trakt │ │ ├── mpv-corner │ │ ├── mpv-drag-screenshot │ │ ├── mpv-last-screenshot-upload │ │ ├── mpv-logfile │ │ ├── mtotal │ │ ├── mvlastpic │ │ ├── mypy-single-lines │ │ ├── mystarsfzf │ │ ├── mz │ │ ├── neomuttr │ │ ├── pinta │ │ ├── pipehtml │ │ ├── play-music │ │ ├── play-shortest-video │ │ ├── playping-loop │ │ ├── primes │ │ ├── printer-server │ │ ├── pygmentize-html-style │ │ ├── pygmentize-styles │ │ ├── qf │ │ ├── qr-clipboard │ │ ├── realbasename │ │ ├── reload-browser │ │ ├── reminder-sink-notify │ │ ├── render-notes │ │ ├── repos │ │ ├── reshortcuts │ │ ├── rgqf │ │ ├── rj │ │ ├── screenshot-upload │ │ ├── screenshots │ │ ├── shortest-video │ │ ├── shuffle-music │ │ ├── sort-by-line-length │ │ ├── spell │ │ ├── spell-fd │ │ ├── spell-interactive │ │ ├── spell-list │ │ ├── sqlitebrowser- │ │ ├── ssh-keygen-good │ │ ├── stream-audio │ │ ├── stream-corner │ │ ├── stream-corner-1080 │ │ ├── stream-corner-480 │ │ ├── stream-corner-720 │ │ ├── stream-corner-at │ │ ├── stream-from-firefox │ │ ├── styluac │ │ ├── sync-neomutt │ │ ├── syncgui │ │ ├── synonym │ │ ├── text2html │ │ ├── timer-till-playping │ │ ├── tmpfile │ │ ├── to-icon │ │ ├── todo │ │ ├── trakt-progress │ │ ├── tstamp │ │ ├── tvsearch │ │ ├── twitch-stream │ │ ├── tz │ │ ├── unicode │ │ ├── unlines │ │ ├── up-live │ │ ├── update-forks │ │ ├── url-echo-redirect │ │ ├── urldrag │ │ ├── urlpicpreview │ │ ├── usdate │ │ ├── vic │ │ ├── vix │ │ ├── watchtwitch │ │ ├── webcam-pic │ │ ├── webcam-test │ │ ├── wfi │ │ ├── wfib │ │ ├── which-cat │ │ ├── yadm-format │ │ ├── yadm-lint │ │ ├── yh │ │ ├── youtube-dl │ │ ├── youtube-dl-480 │ │ ├── youtube-dl-720 │ │ └── youtube-dl-at └── system-config │ └── etc │ ├── X11 │ └── xorg.conf.d │ │ ├── 20-amdgpu.conf │ │ └── 30-trackpad-options.conf │ ├── pacman.conf │ ├── pacman.d │ └── hooks │ │ └── mirrorupgrade.hook │ ├── systemd │ └── system │ │ └── lockscreen@.service │ └── tlp.conf ├── .profile ├── .termux ├── colors.properties └── termux.properties ├── .tmux.conf ├── .xinitrc └── README.md /.bash_profile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # bash is usually called from zsh to do some testing, so don't do path configuration 4 | 5 | export HISTTIMEFORMAT="%s " 6 | export HISTFILESIZE=-1 7 | export HISTSIZE=-1 8 | shopt -s histappend # dont overwrite history 9 | shopt -s cmdhist # save al-lines of multi-line commands in the same entry 10 | shopt -s lithist # embedded newlines for multi-line commands 11 | 12 | source "${HOME}/.config/zsh/source_aliases.zsh" 2>/dev/null 13 | -------------------------------------------------------------------------------- /.config/X11/Xmodmap: -------------------------------------------------------------------------------- 1 | remove Lock = Caps_Lock 2 | keysym Caps_Lock = Escape 3 | -------------------------------------------------------------------------------- /.config/beets/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !config.yaml 4 | -------------------------------------------------------------------------------- /.config/calcurse/conf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purarue/dotfiles/77843d62e8357579d7e8c8e3cd0033cfce803ff6/.config/calcurse/conf -------------------------------------------------------------------------------- /.config/calcurse/hooks/post-save: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd "$(dirname "$0")" || exit 1 4 | 5 | python3 -m calcurse_load --post-save todotxt >/dev/null 2>&1 6 | -------------------------------------------------------------------------------- /.config/calcurse/hooks/pre-load: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd "$(dirname "$0")" || exit 1 4 | 5 | python3 -m calcurse_load --pre-load gcal --pre-load todotxt --pre-load json >/dev/null 2>&1 6 | -------------------------------------------------------------------------------- /.config/clone-repos/hpi-clone-repos.yaml: -------------------------------------------------------------------------------- 1 | "https://github.com/purarue/HPI": 2 | # this install script also HPI-karlicoss, git clones into the directory 3 | # its already managed there because it was needed for CI 4 | postinstall: ./install 5 | "https://github.com/purarue/HPI-personal": 6 | postinstall: ./install 7 | "https://github.com/purarue/HPI-fork": 8 | dirname: "HPI-karlicoss" # name of directory to clone into 9 | postinstall: 10 | - pip install pyfzf_iter logzero colorlog cachew 11 | - python3 -c 'import my.config' 12 | - git remote add upstream "https://github.com/karlicoss/HPI" 13 | pipefail: false # don't fail if the postinstall commands fail 14 | -------------------------------------------------------------------------------- /.config/clone-repos/ranger-plugins.yaml: -------------------------------------------------------------------------------- 1 | "https://github.com/alexanderjeurissen/ranger_devicons": 2 | base: ~/.config/ranger/plugins/ 3 | postinstall: "git pull" 4 | -------------------------------------------------------------------------------- /.config/clone-repos/todotxt-actions.yaml: -------------------------------------------------------------------------------- 1 | "https://git.sr.ht/~proycon/todotxt-more": 2 | base: ~/.cache/todotxt-addons/ 3 | preinstall: git pull 4 | postinstall: 5 | - pip install -r ./requirements.txt 6 | - rsync -Pavh ./todo.actions.d/ "$HOME/.local/share/todo-actions/" 7 | - sed -i -e 's#0 - Start task.*#\\#' "$HOME/.local/share/todo-actions/actionmenu" # patch actionmenu to remove the first option (timetrack), this makes complete the default option 8 | -------------------------------------------------------------------------------- /.config/clone-repos/update-forks.yaml: -------------------------------------------------------------------------------- 1 | "https://github.com/purarue/HPI-fork": 2 | dirname: "HPI-karlicoss" 3 | preinstall: git pull 4 | postinstall: 5 | - git checkout master 6 | - git pull 7 | - git pull upstream master 8 | - git push 9 | pipefail: true 10 | "https://github.com/purarue/promnesia-fork": 11 | preinstall: git pull 12 | postinstall: 13 | - git checkout master 14 | - git pull 15 | - git pull upstream master 16 | - git push 17 | pipefail: true 18 | "https://github.com/purarue/bleanser-fork": 19 | preinstall: git pull 20 | postinstall: 21 | - git checkout master 22 | - git pull 23 | - git pull upstream master 24 | - git push 25 | pipefail: true 26 | -------------------------------------------------------------------------------- /.config/codespell/codespell.conf: -------------------------------------------------------------------------------- 1 | # vim: ft=dosini 2 | # this is not an official location for the codespell config file, 3 | # I just have a wrapper script that does: 4 | # codespell --config-file ~/.config/codespell/codespell.conf 5 | # https://purarue.xyz/d/codespell-conf?dark 6 | [codespell] 7 | skip = *.lock 8 | -------------------------------------------------------------------------------- /.config/cookiecutterrc: -------------------------------------------------------------------------------- 1 | default_context: 2 | -------------------------------------------------------------------------------- /.config/directories: -------------------------------------------------------------------------------- 1 | # shortcuts to commonly used directories 2 | # used in dir-aliases-ranger 3 | # to create bookmarks 4 | D ~/Documents 5 | M ~/Movies 6 | S ~/Pictures/Screenshots 7 | e ~/.local/share/evry/data/ 8 | b ~/Files/Books 9 | d ~/Downloads 10 | f ~/Documents/PicturesFavorites 11 | m ~/Music 12 | n ~/Documents/Notes 13 | p ~/data/playlists 14 | P ~/Pictures 15 | r ~/Repos 16 | s ~/Downloads/Sort 17 | y ~/.config/yadm 18 | z ~/.config/zsh 19 | -------------------------------------------------------------------------------- /.config/flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = E501,E402,W503,E266,E203 3 | -------------------------------------------------------------------------------- /.config/fontconfig/conf.d/01-emoji.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Noto Emoji 7 | emoji 8 | 9 | 10 | Noto Color Emoji 11 | emoji 12 | 13 | 14 | -------------------------------------------------------------------------------- /.config/gh/config.yml: -------------------------------------------------------------------------------- 1 | # What protocol to use when performing git operations. Supported values: ssh, https 2 | git_protocol: https 3 | # What editor gh should run when creating issues, pull requests, etc. If blank, will refer to environment. 4 | editor: 5 | # When to interactively prompt. This is a global config that cannot be overridden by hostname. Supported values: enabled, disabled 6 | prompt: enabled 7 | # A pager program to send command output to, e.g. "less". Set the value to "cat" to disable the pager. 8 | pager: 9 | # Aliases allow you to create nicknames for gh commands 10 | aliases: 11 | co: pr checkout 12 | rc: repo create 13 | prc: pr create 14 | rcl: repo clone 15 | ci: run watch 16 | version: "1" 17 | -------------------------------------------------------------------------------- /.config/git_doc_history/frinkconv: -------------------------------------------------------------------------------- 1 | SOURCE_DIR=~/.local/share/frinkconv 2 | BACKUP_DIR="${HPIDATA}/doc/${ON_OS}/frinkconv_history" 3 | COPY_FILES="history.txt" 4 | -------------------------------------------------------------------------------- /.config/git_doc_history/mysql: -------------------------------------------------------------------------------- 1 | SOURCE_DIR=~/.cache 2 | BACKUP_DIR="${HPIDATA}/doc/${ON_OS}/mysql_history" 3 | COPY_FILES="mysql_history" 4 | -------------------------------------------------------------------------------- /.config/git_doc_history/newsboat: -------------------------------------------------------------------------------- 1 | SOURCE_DIR=~/.config/newsboat 2 | BACKUP_DIR="${HPIDATA}/doc/${ON_OS}/newsboat_git" 3 | COPY_FILES="urls" 4 | -------------------------------------------------------------------------------- /.config/git_doc_history/node: -------------------------------------------------------------------------------- 1 | SOURCE_DIR=~/.cache 2 | BACKUP_DIR="${HPIDATA}/doc/${ON_OS}/node_repl" 3 | COPY_FILES="node_repl_history" 4 | -------------------------------------------------------------------------------- /.config/git_doc_history/plaintext_playlist: -------------------------------------------------------------------------------- 1 | SOURCE_DIR=~/.cache 2 | BACKUP_DIR="${HPIDATA}/doc/${ON_OS}/plaintext_playlist_history" 3 | COPY_FILES="plaintext_playlist_history.txt" 4 | -------------------------------------------------------------------------------- /.config/git_doc_history/ranger: -------------------------------------------------------------------------------- 1 | SOURCE_DIR=~/.local/share/ranger 2 | BACKUP_DIR="${HPIDATA}/doc/${ON_OS}/ranger" 3 | COPY_FILES="history" 4 | -------------------------------------------------------------------------------- /.config/git_doc_history/todo: -------------------------------------------------------------------------------- 1 | SOURCE_DIR=~/data/todo # copy from 2 | BACKUP_DIR="${HPIDATA}/doc/${ON_OS}/todo_git_history" # copy to 3 | COPY_FILES="todo.txt 4 | done.txt" 5 | -------------------------------------------------------------------------------- /.config/glow/glow.yml: -------------------------------------------------------------------------------- 1 | # style name or JSON path (default "auto") 2 | style: "auto" 3 | # show local files only; no network (TUI-mode only) 4 | local: true 5 | # mouse support (TUI-mode only) 6 | mouse: false 7 | # use pager to display markdown 8 | pager: false 9 | -------------------------------------------------------------------------------- /.config/hypr/hyprlock.conf: -------------------------------------------------------------------------------- 1 | # BACKGROUND 2 | background { 3 | monitor = 4 | path = ~/Files/wallpaper.png 5 | blur_passes = 2 6 | contrast = 0.8916 7 | brightness = 0.8172 8 | vibrancy = 0.1696 9 | vibrancy_darkness = 0.0 10 | } 11 | 12 | # GENERAL 13 | general { 14 | no_fade_in = false 15 | no_fade_out = true 16 | grace = 1 17 | disable_loading_bar = false 18 | hide_cursor = true 19 | ignore_empty_input = true 20 | } 21 | 22 | # INPUT FIELD 23 | input-field { 24 | monitor = 25 | size = 250, 80 26 | outer_color = rgba(0, 0, 0, 0) 27 | inner_color = rgba(0, 0, 0, 0.3) 28 | font_color = rgb(200, 200, 200) 29 | placeholder_text = '...' 30 | fade_on_empty = true 31 | hide_input = false 32 | position = 0, -120 33 | halign = center 34 | valign = center 35 | } 36 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-calories: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # how many calories I've eaten today 3 | 4 | [[ -n "$BLOCK_BUTTON" ]] && clrs 5 | 6 | { 7 | ttally recent food -o json "${@:-1d}" | jq -r '(.quantity)*(.calories)' 8 | echo 0 9 | } | datamash sum 1 | cut -d'.' -f1 10 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-comments: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # https://purarue.xyz/ 3 | # display a count if I have any unapproved comments on my website 4 | 5 | # remove the https://github.com/purarue/evry 6 | # file onclick, causes https://github.com/purarue/bgproc/blob/master/personal_jobs/guestbook_comments.job 7 | # to run again in the next minute or so, which updates the icon 8 | [ -n "$BLOCK_BUTTON" ] && rm -f "$(evry location -guestbook_comments)" 9 | 10 | colorize_number <"${HOME}/.cache/guestbook-comments" 11 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-date: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | case $BLOCK_BUTTON in 4 | 1) notify-send --expire-time=20000 "$(cal)" ;; 5 | 3) notify-send --expire-time=20000 "$(cal -n 2 | cut -c 23-)" ;; 6 | esac 7 | 8 | date '+%b %d (%a) %I:%M%p' 9 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-mail: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # https://github.com/LukeSmithxyz/voidrice/blob/master/.local/bin/statusbar/sb-mailbox 3 | 4 | # background job checks if mailsync hasn't run in a 5 | # while and creates this file 6 | MAILSYNC_WARN_FILE="${HOME}/.cache/mailsync_warn" 7 | 8 | # if I click with any button, remove the warn file 9 | [[ -n "$BLOCK_BUTTON" ]] && rm -f "${MAILSYNC_WARN_FILE}" 10 | 11 | case $BLOCK_BUTTON in 12 | 3) setsid launch neomuttr ;; 13 | esac 14 | 15 | if [[ -f "${MAILSYNC_WARN_FILE}" ]]; then 16 | echo 'RUN MAILSYNC!' 17 | exit 0 18 | fi 19 | 20 | unread="$(find "${XDG_DATA_HOME:-$HOME/.local/share}"/mail/*/[Ii][Nn][Bb][Oo][Xx]/new/ -type f | wc -l 2>/dev/null)" 21 | 22 | if [[ "${unread}" == "0" ]]; then 23 | echo "📪0" 24 | else 25 | printf '📬%s\n' "$(colorize_number "${unread}")" 26 | fi 27 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-mpv-description: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # grab the description -- if nothing is playing; exit 4 | desc="$(MPV_DESC_SKIP_ALBUM=1 mpv-song-description-py 2>/dev/null)" || exit 0 5 | # escape HTML characters (otherwise & in artist names breaks this) 6 | # truncate lines over 70 characters 7 | sed 's_&_&_g; s_<_<_g; s_>_>_g; s/\(.\{67\}\).*/\1.../' <<<"$desc" 8 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-mpv-paused: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # list any paused mpv instances, so I remember I have stuff paused 3 | # waiting in the background 4 | 5 | case "$BLOCK_BUTTON" in 6 | 1) 7 | # left click: send a location of currently playing media 8 | notify-send "$(mpv-currently-playing --all)" 9 | ;; 10 | 3) 11 | # cycle play/pause on current mpv instance 12 | mpv-play-pause >/dev/null 2>&1 13 | i3blocks-refresh-mpv >/dev/null 14 | ;; 15 | esac 16 | 17 | paused_count="$(diff -y --suppress-common-lines <(mpv-currently-playing --socket) <(mpv-active-sockets) | wc -l)" 18 | 19 | colorize_number "${paused_count}" 20 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-network: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # opens rofi interface for networkmanager on click 3 | 4 | # onclick, open networkmanager menu in rofi 5 | [ "$BLOCK_BUTTON" = "3" ] && networkmanager_dmenu 6 | 7 | iwgetid -r || echo "no connection..." 8 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-page-hits: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ -n "$BLOCK_BUTTON" ]]; then 4 | notify 'page-hits' 'updating...' 5 | update-recent-page-hits >/dev/null 2>&1 6 | fi 7 | 8 | today="$(date +'%Y-%m-%d')" 9 | jq <"$XDG_CACHE_HOME/recent_page_hits.json" '.epochs.[]' -r | dateq parse - | grep -c "$today" 10 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-reminder-sink: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | case "${BLOCK_BUTTON}" in 4 | 1) 5 | reminder-sink-notify 6 | ;; 7 | 3) 8 | launch reminder-sink-silence 9 | ;; 10 | esac 11 | 12 | reminder-sink run | wc -l | colorize_number 13 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-reminder-sink-json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | items="$(reminder-sink run)" 4 | if [[ -z "$items" ]]; then 5 | count=0 6 | else 7 | count="$(awk 'NF > 0 { count++ } END { print count }' <<<"$items")" 8 | fi 9 | text="$(colorize_number "$count")" 10 | exec jq --null-input --compact-output --raw-output --monochrome-output --arg text " $text" --arg items "$items" '{"text": $text, "tooltip": $items}' 11 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-reminders: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # checks the bgproc (my background process manager) cachefile 3 | # to make no tasks are hanging 4 | # also reminds me to run housekeeping (https://purarue.xyz/d/.local/scripts/linux/housekeeping?redirect) 5 | # if it hasn't been run in the last day 6 | 7 | declare OUT='' 8 | OUT="$({ 9 | ttally_warnings 10 | file-modified-within ~/.cache/bgproc.lastrun 1h || echo " bgproc" 11 | file-modified-within ~/.cache/housekeeping.lastrun 1d || echo " housekeeping" 12 | file-modified-within ~/.cache/restic-backup.lastrun 7d || echo " restic-backup" 13 | } | paste -sd' ')" 14 | 15 | if [[ -n "$OUT" ]]; then 16 | printf "%s\n" "$OUT" 17 | fi 18 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-rss: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # If clicked, updates rss 3 | # Else, prints the number of unread RSS items from 4 | # the cached info in ~/.cache/rss-unread 5 | 6 | case "$BLOCK_BUTTON" in 7 | 1) 8 | notify "Updating RSS feeds..." 9 | wait-for-internet >/dev/null 2>&1 10 | if update-rss; then 11 | notify "Updated RSS feeds" 12 | else 13 | notify -u critical "Couldn't update RSS feeds..." 14 | fi 15 | ;; 16 | 3) 17 | # https://purarue.xyz/d/cross-platform/launch?dark 18 | # https://purarue.xyz/d/newsraft-force?dark 19 | launch newsraft-force 20 | ;; 21 | esac 22 | 23 | colorize_number <"${HOME}/.cache/rss-unread" 24 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-to-watch: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [[ "$BLOCK_BUTTON" == 1 ]] && notify "$(to-watch duration) minutes" 4 | 5 | to-watch || true 6 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-todo: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -n "$1" ]; then 4 | TODO_DIR="$XDG_DOCUMENTS_DIR/todos/$1" 5 | fi 6 | 7 | if [ -z "$TODO_DIR" ]; then 8 | notify -u critical "TODO_DIR not set" 9 | fi 10 | 11 | case "$BLOCK_BUTTON" in 12 | 1) 13 | todo.sh interactive 14 | ;; 15 | 3) 16 | launch 'todo.sh full' 17 | ;; 18 | esac 19 | 20 | COUNT="$(chomp <"${TODO_DIR}/todo.txt" | wc -l)" 21 | SYNC_CONFLICTS="$(sync-conflicts "$TODO_DIR" | wc -l)" 22 | 23 | if [ "$SYNC_CONFLICTS" -gt 0 ]; then 24 | echo "$COUNT " 25 | else 26 | echo "$COUNT" 27 | fi 28 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-volume: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # https://github.com/LukeSmithxyz/voidrice/blob/archi3/.local/bin/statusbar/volume 3 | 4 | [ "$(pamixer --get-mute)" = "true" ] && printf "🔇\\n" && exit 5 | 6 | vol=$(pamixer --get-volume | tr -d "\n") 7 | 8 | if [ "$vol" -gt "70" ]; then 9 | icon="🔊" 10 | elif [ "$vol" -lt "30" ]; then 11 | icon="🔈" 12 | else 13 | icon="🔉" 14 | fi 15 | 16 | printf "%s %s%%\\n" "$icon" "$vol" 17 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-water: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # how many water I've drank today 3 | 4 | { 5 | ttally recent food -o json "${@:-1d}" | jq '(.quantity)*(.water)' 6 | echo 0 7 | } | datamash sum 1 | cut -d'.' -f1 8 | -------------------------------------------------------------------------------- /.config/i3blocks/blocks/b-water-perc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Set default value for the HTML flag 4 | declare WATER SHOULD print_html='' 5 | 6 | # Check if the '-h' flag is present 7 | if [[ "$1" == "-h" ]]; then 8 | print_html=1 9 | fi 10 | 11 | WATER="$(b-water)" 12 | SHOULD="$(water-should-drink)" 13 | 14 | if [[ "$WATER" -lt "$SHOULD" ]]; then 15 | if [[ -n "$print_html" ]]; then 16 | printf '%d/%d\n' "$WATER" "$SHOULD" 17 | else 18 | printf '%d/%d\n' "$WATER" "$SHOULD" 19 | fi 20 | else 21 | printf '%d/%d\n' "$WATER" "$SHOULD" 22 | fi 23 | -------------------------------------------------------------------------------- /.config/inputrc: -------------------------------------------------------------------------------- 1 | set editing-mode vi 2 | -------------------------------------------------------------------------------- /.config/irbrc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | # custom irbrc to change ruby history location 4 | # frozen_string_literal: true 5 | 6 | require 'irb' 7 | IRB.conf[:SAVE_HISTORY] = 1000 8 | IRB.conf[:HISTORY_FILE] = "#{ENV['XDG_CACHE_HOME']}/irb_history" 9 | IRB.start 10 | -------------------------------------------------------------------------------- /.config/kitty/.gitignore: -------------------------------------------------------------------------------- 1 | current-theme.conf 2 | # this is generated by 'yadm bootstrap', and just 3 | # includes the current theme 4 | # 5 | # that file changes whenver I change my theme so its 6 | # not useful to sync to git 7 | # 8 | # it looks like: 9 | # 10 | # # BEGIN_KITTY_THEME 11 | # # Light 12 | # include current-theme.conf 13 | # # END_KITTY_THEME 14 | theme.conf 15 | -------------------------------------------------------------------------------- /.config/kitty/bgproc.conf: -------------------------------------------------------------------------------- 1 | action_alias rJ launch_window with-secrets rj -o 2 | action_alias hk launch_window with-secrets housekeeping-offline 3 | 4 | # launch housekeeping/bgproc_on_machine simultaneously in 8 windows 5 | # typically I run this when first booting my machine, to run all my jobs in parallel quickly 6 | map kitty_mod+p>kitty_mod+u combine : rJ : rJ : rJ : rJ : hk : hk : hk : hk : goto_layout grid 7 | 8 | -------------------------------------------------------------------------------- /.config/kitty/custom.conf: -------------------------------------------------------------------------------- 1 | # custom bindings in a separate file so they're easier to find 2 | #: Browse output of the last shell command in pager 3 | 4 | map kitty_mod+r launch_window ranger 5 | map kitty_mod+e launch_window editor 6 | map kitty_mod+x send_text all CD-Repos\r 7 | 8 | map kitty_mod+o show_last_command_output 9 | 10 | action_alias copy_last_cmd_output launch --stdin-source=@last_cmd_output --type=clipboard 11 | 12 | # Copy output of last command to clipboard 13 | map kitty_mod+g copy_last_cmd_output 14 | 15 | # custom command to send last buffer to a quickfix list 16 | # https://purarue.xyz/d/cl-quickfix?dark 17 | map kitty_mod+p>kitty_mod+q combine : copy_last_cmd_output : launch_window cl-quickfix 18 | -------------------------------------------------------------------------------- /.config/lftp/rc: -------------------------------------------------------------------------------- 1 | set ssl:verify-certificate no 2 | -------------------------------------------------------------------------------- /.config/mpv/input.conf: -------------------------------------------------------------------------------- 1 | # increase subtitle font size 2 | ALT+k add sub-scale +0.1 3 | 4 | # decrease subtitle font size 5 | ALT+j add sub-scale -0.1 6 | 7 | # encode.lua 8 | # https://github.com/occivink/mpv-scripts/tree/master 9 | e script-message-to encode set-timestamp encode_web 10 | 11 | # vim:ft=conf 12 | -------------------------------------------------------------------------------- /.config/mpv/mpv.conf: -------------------------------------------------------------------------------- 1 | # most recent mpv instance connects to socket 2 | # to be controllable through socat 3 | # see mpv --list-properties 4 | # https://stackoverflow.com/q/35013075/9348376 5 | # https://stackoverflow.com/q/62582594/9348376 6 | # input-ipc-server=/tmp/mpvsocket 7 | # replaced by https://github.com/purarue/mpv-sockets 8 | 9 | screenshot-template="%f-%wH.%wM.%wS.%wT" 10 | script-opts=ytdl_path=~/.local/bin/yt-dlp 11 | 12 | # vim:ft=conf 13 | -------------------------------------------------------------------------------- /.config/muttc/mailcap: -------------------------------------------------------------------------------- 1 | # to track 'shell-like' history https://github.com/purarue/ttt 2 | # most of these just forward to rifle, my file manager 3 | # for config see https://github.com/purarue/dotfiles/blob/master/.config/ranger/rifle.conf 4 | text/plain; rifle %s ; 5 | text/html; rifle %s ; nametemplate=%s.html 6 | text/html; ttt lynx -assume_charset=%{charset} -display_charset=utf-8 -dump %s; nametemplate=%s.html; copiousoutput; 7 | text/csv; rifle %s ; 8 | image/*; rifle %s ; 9 | video/*; rifle %s ; copiousoutput 10 | audio/*; rifle %s ; 11 | application/zip; ttt unzip %s ; 12 | application/pdf; rifle %s ; 13 | application/pgp-encrypted; ttt gpg -d '%s'; copiousoutput; 14 | application/pgp-keys; ttt gpg --import '%s'; copiousoutput; 15 | -------------------------------------------------------------------------------- /.config/my/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .mypy_cache 3 | -------------------------------------------------------------------------------- /.config/my/.stignore: -------------------------------------------------------------------------------- 1 | .mypy_cache 2 | __pycache__ 3 | __init__.py 4 | -------------------------------------------------------------------------------- /.config/my/my/config/common.py: -------------------------------------------------------------------------------- 1 | from os import environ, path 2 | from my.core.warnings import high 3 | 4 | 5 | def repo(name: str) -> str: 6 | """ 7 | e.g., converts to ~/Repos/name 8 | ~/Repos/ is where I store a lot of my git repositories 9 | """ 10 | if "REPOS" in environ: 11 | return path.join(environ["REPOS"], name) 12 | else: 13 | high( 14 | r"Hey I use the $REPOS environment variable to determine where repositories are on my computer. If you have some directory you put those -- set something like 'export REPOS=~/projects' in your shell config. Otherwise, you can edit this 'def repo' function, or remove it from whatevers using it -- its probably some of my personal config" 15 | ) 16 | return name 17 | -------------------------------------------------------------------------------- /.config/my/my/config/pura/.gitignore: -------------------------------------------------------------------------------- 1 | *secret.py 2 | -------------------------------------------------------------------------------- /.config/my/my/config/pura/__init__.pyi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purarue/dotfiles/77843d62e8357579d7e8c8e3cd0033cfce803ff6/.config/my/my/config/pura/__init__.pyi -------------------------------------------------------------------------------- /.config/my/my/config/pura/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purarue/dotfiles/77843d62e8357579d7e8c8e3cd0033cfce803ff6/.config/my/my/config/pura/py.typed -------------------------------------------------------------------------------- /.config/nsxiv/exec/image-info: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Example for $XDG_CONFIG_HOME/nsxiv/exec/image-info 4 | # Called by nsxiv(1) whenever an image gets loaded. 5 | # The output is displayed in nsxiv's status bar. 6 | # Arguments: 7 | # $1: path to image file 8 | # $2: image width 9 | # $3: image height 10 | 11 | s=" " # field separator 12 | 13 | exec 2>/dev/null 14 | 15 | filename=$(basename -- "$1") 16 | filesize=$(du -Hh -- "$1" | cut -f 1) 17 | geometry="${2}x${3}" 18 | 19 | echo "${filesize}${s}${geometry}${s}${filename}" 20 | -------------------------------------------------------------------------------- /.config/nvim/.gitignore: -------------------------------------------------------------------------------- 1 | plugin/packer_compiled.lua 2 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/gitcommit.lua: -------------------------------------------------------------------------------- 1 | vim.opt_local.spell = true 2 | -- Follow 50/72 rule like described here: 3 | -- https://stackoverflow.com/q/2290016 4 | -- I set 72 here for the description 5 | vim.opt_local.textwidth = 72 6 | vim.opt_local.colorcolumn = "+1" 7 | vim.b.codeium_enabled = false 8 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/help.lua: -------------------------------------------------------------------------------- 1 | -- Close help buffer with q 2 | vim.keymap.set("n", "q", "bdelete", { buffer = 0 }) 3 | -- 'gd' to go to definition (Ctrl-]) 4 | vim.keymap.set("n", "gd", "", { buffer = 0 }) 5 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/lua.lua: -------------------------------------------------------------------------------- 1 | vim.bo.shiftwidth = 4 2 | vim.bo.tabstop = 4 3 | vim.bo.expandtab = true 4 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/markdown.lua: -------------------------------------------------------------------------------- 1 | vim.b.codeium_enabled = false 2 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/qf.lua: -------------------------------------------------------------------------------- 1 | -- Close quickfix buffer with q 2 | vim.keymap.set("n", "q", "bdelete", { buffer = 0 }) 3 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/query.lua: -------------------------------------------------------------------------------- 1 | -- for treesitter query 2 | vim.bo.shiftwidth = 2 3 | vim.bo.tabstop = 2 4 | vim.bo.expandtab = true 5 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/sshconfig.lua: -------------------------------------------------------------------------------- 1 | vim.bo.shiftwidth = 2 2 | vim.bo.tabstop = 2 3 | vim.bo.expandtab = true 4 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/zsh.lua: -------------------------------------------------------------------------------- 1 | -- if this is in a directory called 'tmp', this is probably me using the 2 | -- zsh edit-command-line widget set it to bash so I get nice treesitter 3 | -- highlighting, including for embedded languages (e.g. awk/jq) 4 | -- (see queries/bash/injections.scm) 5 | local dirname = vim.fn.expand("%:h") 6 | local parent_dir = vim.fs.basename(dirname) 7 | if parent_dir == "tmp" then 8 | vim.bo.filetype = "bash" 9 | end 10 | -------------------------------------------------------------------------------- /.config/nvim/after/plugin/helpers.lua: -------------------------------------------------------------------------------- 1 | -- dumps the contents of one or more variables to the console 2 | -- selene: allow(unscoped_variables,unused_variable) 3 | P = function(...) 4 | local args = {} 5 | for _, arg in ipairs({ ... }) do 6 | table.insert(args, vim.inspect(arg)) 7 | end 8 | print(unpack(args)) 9 | return ... 10 | end 11 | -------------------------------------------------------------------------------- /.config/nvim/after/plugin/highlight.lua: -------------------------------------------------------------------------------- 1 | -- see queries/bash/injections.scm for where this is set 2 | vim.api.nvim_set_hl(0, "@evry_flag", { italic = true, fg = "lightgrey" }) 3 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/cloak.lua: -------------------------------------------------------------------------------- 1 | -- 'https://github.com/laytan/cloak.nvim?tab=readme-ov-file#configuration' 2 | return { 3 | "laytan/cloak.nvim", 4 | event = "BufRead", 5 | keys = { { "C", "CloakToggle", "toggle cloak" } }, 6 | opts = { 7 | patterns = { 8 | { 9 | -- Match any file starting with '.env'. 10 | -- This can be a table to match multiple file patterns. 11 | file_pattern = ".env*", 12 | -- Match an equals sign and any character after it. 13 | -- This can also be a table of patterns to cloak, 14 | -- example: cloak_pattern = { ':.+', '-.+' } for yaml files. 15 | cloak_pattern = "=.+", 16 | }, 17 | }, 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/codeium.lua: -------------------------------------------------------------------------------- 1 | local function toggle() 2 | require("user.patch_codeium").toggle_codeium_enabled() 3 | end 4 | 5 | local mh = require("user.mapping_helpers") 6 | mh.map_key("", toggle, "toggle codeium", { "i", "n" }) 7 | 8 | return { 9 | "Exafunction/codeium.nvim", 10 | commit = "937667b2cadc7905e6b9ba18ecf84694cf227567", 11 | event = "InsertEnter", 12 | cmd = { "Codeium", "CodeiumToggle" }, 13 | cond = not vim.g.on_android, 14 | config = function() 15 | require("codeium").setup() 16 | require("user.patch_codeium").patch_codeium() 17 | 18 | vim.api.nvim_create_user_command("CodeiumToggle", toggle, { desc = "Toggle Codeium" }) 19 | end, 20 | } 21 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/mini.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "echasnovski/mini.nvim", 3 | version = false, 4 | event = "VeryLazy", 5 | config = function() 6 | require("mini.ai").setup() 7 | require("mini.surround").setup() 8 | end, 9 | } 10 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/spectre.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvim-pack/nvim-spectre", 3 | keys = { 4 | { 5 | "S", 6 | function() 7 | require("spectre").open() 8 | end, 9 | desc = "spectre", 10 | }, 11 | }, 12 | cmd = "Spectre", 13 | opts = {}, 14 | } 15 | -------------------------------------------------------------------------------- /.config/nvim/lua/user/init.lua: -------------------------------------------------------------------------------- 1 | require("user.settings") 2 | require("user.key_mappings") 3 | require("user.autocmds") 4 | require("user.remsync") 5 | -------------------------------------------------------------------------------- /.config/nvim/lua/user/snippets.lua: -------------------------------------------------------------------------------- 1 | local ls = require("luasnip") 2 | 3 | -- shorthands 4 | local snippet = ls.s 5 | local f = ls.function_node 6 | 7 | ls.add_snippets("all", { 8 | -- date -> Tue 16 Nov 2021 09:43:49 AM EST 9 | snippet({ trig = "date" }, { 10 | f(function() 11 | return string.format(string.gsub(vim.bo.commentstring, "%%s", " %%s"), os.date()) 12 | end, {}), 13 | }), 14 | }) 15 | -------------------------------------------------------------------------------- /.config/nvim/lua/user/terminal.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | function M.set_background() 4 | local ok, mod = pcall(require, "terminal_colorscheme") 5 | if not ok then 6 | vim.o.background = "dark" 7 | else 8 | -- vim.o to set global option 9 | vim.o.background = mod.dark_mode() and "dark" or "light" 10 | end 11 | end 12 | 13 | return M 14 | -------------------------------------------------------------------------------- /.config/nvim/queries/bash/highlights.scm: -------------------------------------------------------------------------------- 1 | ; extends 2 | 3 | ; https://github.com/purarue/evry 4 | ; evry has syntax like: 5 | ; evry 1 day -do_some_job 6 | ; 7 | ; this identifies the -tag as @evry_flag, so it 8 | ; can be highlighted 9 | (command 10 | name: (command_name 11 | (word) @cmd_name) 12 | (#eq? @cmd_name "evry") 13 | argument: (word) @evry_flag 14 | (#match? @evry_flag "^-")) @evry 15 | 16 | ; can then use a command like this to highlight it specifically: 17 | ; vim.api.nvim_set_hl(0, "@evry_flag", {italic = true, fg = "lightgrey"}) 18 | -------------------------------------------------------------------------------- /.config/nvim/queries/markdown/injections.scm: -------------------------------------------------------------------------------- 1 | ; extends 2 | 3 | ; https://github.com/purarue/pmark 4 | (fenced_code_block 5 | (code_fence_content) @injection.content 6 | (#match? @injection.content "^...PMARK") 7 | ; skip the first line, is a PMARK marker 8 | (#offset! @injection.content 1 0 0 0) 9 | (#set! injection.language "bash")) 10 | -------------------------------------------------------------------------------- /.config/nvim/queries/query/injections.scm: -------------------------------------------------------------------------------- 1 | ; extends 2 | 3 | ; highlight regex strings in treesitter query files 4 | (predicate 5 | name: (identifier) @query_cond 6 | (#any-of? @query_cond "match" "any-match" "vim-match" "any-match" 7 | "any-vim-match" "lua-match" "any-lua-match") 8 | parameters: (parameters 9 | (string 10 | (string_content) @injection.content)) 11 | (#set! injection.language "regex")) 12 | -------------------------------------------------------------------------------- /.config/nvim/queries/rifleconfig/injections.scm: -------------------------------------------------------------------------------- 1 | ; extends 2 | 3 | ; highlight any commands using the bash tree-sitter parser 4 | (command_list 5 | (command) @injection.content 6 | (#set! injection.include-children) 7 | (#set! injection.language "bash")) 8 | -------------------------------------------------------------------------------- /.config/nvim/selene.toml: -------------------------------------------------------------------------------- 1 | std = "lua51+vim" 2 | 3 | [lints] 4 | mixed_table = "allow" 5 | -------------------------------------------------------------------------------- /.config/nvim/snippets/cfg.snippets: -------------------------------------------------------------------------------- 1 | snippet python_defaults 2 | [metadata] 3 | name = $1 4 | version = 5 | description = 6 | license = 7 | license_file = LICENSE 8 | long_description = file: README.md 9 | long_description_content_type = text/markdown 10 | author = purarue 11 | url = https://github.com/purarue/$1 12 | 13 | [options] 14 | packages = find: 15 | include_package_data = True 16 | install_requires = 17 | 18 | python_requires = >=3.8 19 | 20 | [options.packages.find] 21 | exclude = 22 | tests* 23 | include = 24 | $1 25 | 26 | [options.package_data] 27 | $1 = py.typed 28 | 29 | [options.entry_points] 30 | console_scripts = 31 | 32 | [options.extras_require] 33 | testing = 34 | mypy 35 | flake8 36 | -------------------------------------------------------------------------------- /.config/nvim/snippets/python.snippets: -------------------------------------------------------------------------------- 1 | snippet click_path 2 | from pathlib import Path 3 | import click 4 | 5 | @click.command() 6 | @click.argument("$2", type=click.Path(exists=True, path_type=Path), required=True) 7 | def main($2: Path) -> None: 8 | """ 9 | """ 10 | click.echo($2) 11 | $0 12 | 13 | if __name__ == "__main__": 14 | main(prog_name="$1") 15 | 16 | snippet click 17 | from pathlib import Path 18 | import click 19 | 20 | @click.command() 21 | def main() -> None: 22 | """ 23 | """ 24 | 25 | if __name__ == "__main__": 26 | main(prog_name="$1") 27 | 28 | snippet typ 29 | from typing import $1 30 | -------------------------------------------------------------------------------- /.config/nvim/snippets/sh.snippets: -------------------------------------------------------------------------------- 1 | snippet bash_this_dir 2 | THIS_DIR="$(realpath "$(dirname "\${BASH_SOURCE[0]}")")" 3 | cd "\${THIS_DIR}" || exit $? 4 | 5 | # https://github.com/purarue/bgproc 6 | snippet bgproc_job 7 | #!/usr/bin/env bash 8 | 9 | wait-for-internet -q --timeout "\${WFI_TIMEOUT:-10}" || exit 0 10 | 11 | evry $1 -$2 && { 12 | printlog '$2:' 13 | $0 14 | } 15 | -------------------------------------------------------------------------------- /.config/nvim/stylua.toml: -------------------------------------------------------------------------------- 1 | column_width = 140 2 | indent_type = "Spaces" 3 | indent_width = 4 4 | collapse_simple_statement = "Never" 5 | -------------------------------------------------------------------------------- /.config/nvim/vim.toml: -------------------------------------------------------------------------------- 1 | [vim] 2 | any = true 3 | -------------------------------------------------------------------------------- /.config/plus1_blacklist.txt: -------------------------------------------------------------------------------- 1 | .3g2 2 | .3gp 3 | .7z 4 | .aac 5 | .ac3 6 | .aiff 7 | .alac 8 | .ape 9 | .apk 10 | .arj 11 | .avi 12 | .bak 13 | .bat 14 | .bin 15 | .bmp 16 | .cab 17 | .com 18 | .cpl 19 | .cur 20 | .ddl 21 | .deb 22 | .dmg 23 | .dmp 24 | .doc 25 | .docx 26 | .drv 27 | .exe 28 | .f4p 29 | .f4v 30 | .flac 31 | .flv 32 | .gif 33 | .gifv 34 | .gz 35 | .icns 36 | .ico 37 | .iso 38 | .jar 39 | .jpeg 40 | .jpg 41 | .key 42 | .m2v 43 | .m4a 44 | .m4p 45 | .m4v 46 | .md 47 | .mka 48 | .mkv 49 | .mp2 50 | .mp3 51 | .mp4 52 | .mpe 53 | .mpeg 54 | .mpg 55 | .mpv 56 | .odp 57 | .ogg 58 | .ogv 59 | .opus 60 | .pkg 61 | .png 62 | .pps 63 | .ppt 64 | .pptx 65 | .psd 66 | .pyc 67 | .qt 68 | .rar 69 | .rpm 70 | .svg 71 | .sys 72 | .tar 73 | .tif 74 | .tiff 75 | .tmp 76 | .toast 77 | .vcd 78 | .wav 79 | .webm 80 | .wma 81 | .wmv 82 | .z 83 | .zip 84 | -------------------------------------------------------------------------------- /.config/pura_lua/pura_utils.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | ---reads the entire file to a string 4 | ---@param filename string 5 | ---@param readmode? readmode 6 | ---@return string? 7 | function M.read_to_string(filename, readmode) 8 | local f = io.open(filename, "r") 9 | if f then 10 | local content = f:read(readmode or "*a") 11 | f:close() 12 | return content 13 | end 14 | return nil 15 | end 16 | 17 | --- removes spaces from start and end of a string 18 | --- trim6 from https://lua-users.org/wiki/StringTrim 19 | ---@param s string 20 | ---@return string 21 | function M.trim(s) 22 | return s:match("^()%s*$") and "" or s:match("^%s*(.*%S)") 23 | end 24 | 25 | return M 26 | -------------------------------------------------------------------------------- /.config/pura_lua/terminal_colorscheme.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local terminal_theme_file = os.getenv("HOME") .. "/.cache/terminal-theme" 4 | 5 | ---@return string? 6 | function M.terminal_colorscheme() 7 | return os.getenv("TERMINAL_THEME") or require("pura_utils").read_to_string(terminal_theme_file, "*l") 8 | end 9 | 10 | ---@return boolean 11 | function M.dark_mode() 12 | local colorscheme = M.terminal_colorscheme() 13 | return colorscheme == nil or colorscheme:lower() == "dark" 14 | end 15 | 16 | ---@return boolean 17 | function M.light_mode() 18 | return not M.dark_mode() 19 | end 20 | 21 | return M 22 | -------------------------------------------------------------------------------- /.config/pythonrc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import atexit 4 | import os 5 | import readline 6 | 7 | history = os.path.join( 8 | os.environ.get("XDG_CACHE_HOME", os.path.join(os.environ["HOME"], ".cache")), 9 | "python_history", 10 | ) 11 | try: 12 | readline.read_history_file(history) 13 | # default history len is -1 (infinite), which may grow unruly 14 | readline.set_history_length(1000) 15 | # https://bugs.python.org/issue20886#msg265568 16 | except FileNotFoundError: 17 | pass 18 | 19 | atexit.register(readline.write_history_file, history) 20 | -------------------------------------------------------------------------------- /.config/ranger/.gitignore: -------------------------------------------------------------------------------- 1 | preview.rc 2 | hidden_filter.rc 3 | -------------------------------------------------------------------------------- /.config/ranger/Makefile: -------------------------------------------------------------------------------- 1 | BOOKMARKS_FILE:=~/.local/share/ranger/bookmarks 2 | 3 | all: hidden_filter.rc preview.rc $(BOOKMARKS_FILE) 4 | $(BOOKMARKS_FILE): ./dir-aliases ~/.config/directories 5 | ./dir-aliases 6 | preview.rc: ./generate_image_preview 7 | ./generate_image_preview 8 | hidden_filter.rc: ./hidden_template.rc 9 | ./generate_filter 10 | clean: 11 | rm -f ./hidden_filter.rc ./preview.rc $(BOOKMARKS_FILE) 12 | -------------------------------------------------------------------------------- /.config/ranger/generate_filter: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ -z "$oname" ]]; then 4 | printf "oname not set\n" >&2 5 | exit 1 6 | fi 7 | 8 | THIS_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" 9 | cd "${THIS_DIR}" || exit $? 10 | 11 | set -x 12 | 13 | exec jinjanate ./hidden_template.rc >hidden_filter.rc 14 | -------------------------------------------------------------------------------- /.config/ranger/generate_image_preview: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | TARGET="${XDG_CONFIG_HOME}/ranger/preview.rc" 3 | case "${ON_OS:-$(on_machine)}" in 4 | android*) 5 | # dont think there's any way to do this right now 6 | echo 'set preview_images false' >"${TARGET}" 7 | ;; 8 | linux_arch*) 9 | printf 'set preview_images %s\n' "${RANGER_GENERATE_IMAGE_PREVIEW:-true}" >"${TARGET}" 10 | if [[ "$TERM" == xterm-kitty ]]; then 11 | # use kitty to preview images 12 | echo 'set preview_images_method kitty' >>"${TARGET}" 13 | elif [[ "$TERM" == foot ]]; then 14 | echo 'set preview_images_method sixel' >>"${TARGET}" 15 | else 16 | # use ueberzug to preview images 17 | echo 'set preview_images_method ueberzug' >>"${TARGET}" 18 | fi 19 | ;; 20 | *) 21 | # fallback to w3m? 22 | echo -e 'set preview_images true\nset preview_images_method w3m' >"${TARGET}" 23 | ;; 24 | esac 25 | -------------------------------------------------------------------------------- /.config/ranger/hidden_template.rc: -------------------------------------------------------------------------------- 1 | ###SETTINGS### 2 | set hidden_filter ^\.|\.(?:pyc|vrb|pyo|class|lof|swp|aux|nav|out|snm|toc|bcf|run\.xml|synctex\.gz|blg|bbl|egg-info)$|^lost\+found$|^__(py)?cache__$|^tags(?:\.lock|\.temp)?$|^_build$|^build$|^dist$|^node_modules$|^target|{{ oname }}$ 3 | -------------------------------------------------------------------------------- /.config/ranger/make: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # non-directory specific make script 3 | exec make -C "${HOME}/.config/ranger" -f "${HOME}/.config/ranger/Makefile" 4 | -------------------------------------------------------------------------------- /.config/rifleman/image.conf: -------------------------------------------------------------------------------- 1 | # vim: ft=rifleconfig 2 | # 3 | # This is a configuration file for "rifleman" 4 | # https://github.com/purarue/rifleman 5 | # 6 | # This matches any png, jpeg and gif files, and optimizes them in-place 7 | # This uses a couple of my wrapper scripts, but under the hood 8 | # its using: 9 | # 10 | # for gifs: https://github.com/kohler/gifsicle 11 | # for pngs: http://optipng.sourceforge.net/ 12 | # for jpegs: http://jpegclub.org/jpegtran/ 13 | 14 | # https://purarue.xyz/d/optigif 15 | # for gifs 16 | mime image/gif, has optigif = OPTIGIF_OVERWRITE=1 optigif "$1" 17 | 18 | # https://purarue.xyz/d/optijpg 19 | # for jpegs 20 | mime image/jpeg, has jpegtran = optijpg "$1" 21 | 22 | # for pngs 23 | mime image/png, has optipng = optipng -o5 "$@" 24 | -------------------------------------------------------------------------------- /.config/rofi/config.rasi: -------------------------------------------------------------------------------- 1 | configuration { 2 | modi: "window,run"; 3 | location: 2; 4 | } 5 | 6 | // @theme "dracula" 7 | -------------------------------------------------------------------------------- /.config/scramble_history/files.yaml: -------------------------------------------------------------------------------- 1 | cstimer: 2 | - ~/data/cubing/cstimer/*.json 3 | twistytimer: 4 | - ~/data/cubing/manual.csv 5 | - ~/data/cubing/phone_twistytimer/*.txt 6 | - ~/data/cubing/cubers_io/*.txt 7 | -------------------------------------------------------------------------------- /.config/screenlayout/auto.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # automatically fixes my screen layout, depending on whether or not HDMI is plugged in 3 | if xrandr | grep -q 'HDMI-A-0 connected'; then 4 | "${HOME}/.config/screenlayout/desk_dual_monitor.sh" 5 | else 6 | "${HOME}/.config/screenlayout/single_laptop_screen.sh" 7 | fi 8 | -------------------------------------------------------------------------------- /.config/screenlayout/desk_dual_monitor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # For when I have monitor plugged in on the right of my laptop screen 3 | xrandr --output eDP --primary --mode 1920x1080 --pos 0x0 --rotate normal --output HDMI-A-0 --mode 3840x2160 --pos 1920x0 --rotate normal --output DisplayPort-0 --off --output DisplayPort-1 --off 4 | -------------------------------------------------------------------------------- /.config/screenlayout/single_laptop_screen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # For when Im just using my laptop screen 3 | xrandr --output eDP --primary --mode 1920x1080 --pos 0x0 --rotate normal --output HDMI-A-0 --off --output DisplayPort-0 --off --output DisplayPort-1 --off 4 | -------------------------------------------------------------------------------- /.config/skhd/skhdrc: -------------------------------------------------------------------------------- 1 | # Mac keyboard hotkey daemon 2 | # See https://github.com/koekeishiya/skhd/blob/master/examples/skhdrc for more examples 3 | # Use shkd to bind applications to cmd + alt 4 | # This shouldn't interfere with window manager commands (https://github.com/ianyh/Amethyst) 5 | # since those are prefixed with option + shift or ctrl + option + shift 6 | 7 | cmd + alt - return : kitty -d=~ -1 8 | cmd + alt - f : /Applications/Firefox\ Developer\ Edition.app/Contents/MacOS/firefox 9 | -------------------------------------------------------------------------------- /.config/thefuck/settings.py: -------------------------------------------------------------------------------- 1 | # The Fuck settings file 2 | # 3 | # The rules are defined as in the example below: 4 | # 5 | # rules = ['cd_parent', 'git_push', 'python_command', 'sudo'] 6 | # 7 | # The default values are as follows. Uncomment and change to fit your needs. 8 | # See https://github.com/nvbn/thefuck#settings for more information. 9 | # 10 | 11 | # rules = [] 12 | # exclude_rules = [] 13 | # wait_command = 3 14 | # require_confirmation = True 15 | # no_colors = False 16 | # debug = False 17 | # priority = {} 18 | # history_limit = None 19 | # alter_history = True 20 | # wait_slow_command = 15 21 | # slow_commands = ['lein', 'react-native', 'gradle', './gradlew', 'vagrant'] 22 | # repeat = False 23 | # instant_mode = False 24 | # num_close_matches = 3 25 | # env = {'LC_ALL': 'C', 'LANG': 'C', 'GIT_TRACE': '1'} 26 | -------------------------------------------------------------------------------- /.config/user-dirs.dirs: -------------------------------------------------------------------------------- 1 | # This file is written by xdg-user-dirs-update 2 | # If you want to change or add directories, just edit the line you're 3 | # interested in. All local changes will be retained on the next run. 4 | # Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped 5 | # homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an 6 | # absolute path. No other format is supported. 7 | # 8 | XDG_DESKTOP_DIR="$HOME/" 9 | XDG_DOWNLOAD_DIR="$HOME/Downloads" 10 | XDG_TEMPLATES_DIR="$HOME/.local/share/Templates" 11 | XDG_PUBLICSHARE_DIR="$HOME/.local/share/Public" 12 | XDG_DOCUMENTS_DIR="$HOME/Documents" 13 | XDG_MUSIC_DIR="$HOME/Music" 14 | XDG_PICTURES_DIR="$HOME/Pictures" 15 | XDG_VIDEOS_DIR="$HOME/Movies" 16 | -------------------------------------------------------------------------------- /.config/user-dirs.locale: -------------------------------------------------------------------------------- 1 | en_US -------------------------------------------------------------------------------- /.config/wezterm/clipboard.lua: -------------------------------------------------------------------------------- 1 | local wt = require("wezterm") 2 | 3 | -- https://github.com/wez/wezterm/discussions/3469 4 | 5 | local M = {} 6 | M.autoQuotePastedUrls = function(window, pane) 7 | local pasteCmd = "clippaste" 8 | local success, clipb, stderr = wt.run_child_process({ pasteCmd }) 9 | if not success then 10 | local msg = "clippaste failed: " .. stderr 11 | wt.log_info(msg) 12 | window:toast_notification(msg, nil, 4000) 13 | return 14 | end 15 | if clipb:find("^https?://") then 16 | clipb = "'" .. clipb .. "'" 17 | end 18 | pane:paste(clipb) 19 | end 20 | 21 | return M 22 | -------------------------------------------------------------------------------- /.config/yadm/dotfiles_ignore_words.txt: -------------------------------------------------------------------------------- 1 | doubleclick 2 | -------------------------------------------------------------------------------- /.config/yadm/hooks/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Reverts README.md copy -- what is done by pre-commit 3 | # Delete the README.md since the original at ~/.config/yadm/README.md still exists 4 | 5 | cd || exit $? 6 | [[ -f ~/README.md ]] && rm ~/README.md 7 | -------------------------------------------------------------------------------- /.config/yadm/hooks/post-merge: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Moves the README.md downloaded from github back to ~/.config/yadm/README.md 3 | # so that changes made through the web interacted stay updated locally 4 | 5 | cd || exit $? 6 | [[ -f ~/README.md ]] && mv ~/README.md ~/.config/yadm/README.md 7 | -------------------------------------------------------------------------------- /.config/yadm/hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd || exit $? 4 | 5 | # make sure there is no errors with my profile, 6 | # because this causes x11 issues if it can't be sourced 7 | sh ~/.profile || { 8 | echo 'Error in sourcing ~/.profile' >&2 9 | exit 1 10 | } 11 | 12 | # check for spelling errors in my dotfiles 13 | case "$ON_OS" in 14 | linux_*) 15 | spell-dotfiles || exit $? 16 | ;; 17 | *) ;; 18 | esac 19 | 20 | # Copy README for git repo to $HOME so that the github repo README will be updated 21 | # post-commit moves the README.md back so as to not pollute $HOME 22 | cp ~/.config/yadm/README.md ~/README.md 23 | yadm add -f ~/README.md 24 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/arch_packages_wayland.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | # os 4 | gammastep 5 | hyprland 6 | hyprlock 7 | swaybg 8 | pipewire 9 | pipewire-pulse 10 | polkit-kde-agent 11 | qt5-wayland 12 | qt6-wayland 13 | rofi-lbonn-wayland-git 14 | wev 15 | wireplumber 16 | wl-clipboard 17 | xdg-desktop-portal-hyprland 18 | xorg-xwayland 19 | 20 | auto-cpufreq # for battery life 21 | otf-font-awesome # for waybar 22 | 23 | # for clicking without my trackpad 24 | wlrctl 25 | wl-kbptr 26 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/arch_packages_x11.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | # os 4 | 5 | arandr 6 | autorandr 7 | autotiling-git 8 | exfat-utils 9 | i3-wm 10 | i3blocks 11 | i3lock 12 | network-manager-applet 13 | picom 14 | pipewire-alsa 15 | redshift 16 | udiskie 17 | udisks2 18 | ueberzug 19 | unclutter 20 | xorg-server 21 | xorg-xev 22 | xorg-xinput 23 | xorg-xmodmap 24 | xorg-xwininfo 25 | xorg-xinit 26 | 27 | # utilities 28 | 29 | screenkey-git 30 | scrot 31 | w3m 32 | wezterm 33 | xclip 34 | xcolor 35 | xdotool 36 | xorg-xdpyinfo 37 | xorg-xwininfo 38 | xterm 39 | xvkbd 40 | 41 | # applications 42 | 43 | gparted 44 | mupdf-gl 45 | snes9x-gtk 46 | thunar 47 | 48 | # fonts 49 | xorg-font-util 50 | xorg-fonts-encodings 51 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/bash_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | purarue/mpv-sockets 4 | purarue/mpvf 5 | purarue/bgproc 6 | purarue/plaintext-playlist 7 | purarue/pmark 8 | purarue/frinkconv 9 | paulirish/git-open 10 | dylanaraps/neofetch 11 | kadwanev/retry 12 | kdheepak/panvimdoc 13 | reinefjord/wayshot 14 | eschulte/lisp-format 15 | rupa/z 16 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/cargo_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | cargo-license # list licenses 4 | cargo-update # to update these packages 5 | evry # my task scheduler 6 | procs # ps replacement 7 | diskonaut # disk visualizer 8 | kondo # removes node_module/build directories 9 | so # stackoverflow 10 | readenv # renv, for executing a command with a modified environment 11 | wait-for-internet 12 | hexyl # hexdump 13 | monolith # saves webpages as a single HTML file 14 | taplo-cli # TOML library, for formatting 15 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/computer_node_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | elm-format 4 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/computer_python.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=requirements 2 | 3 | # things I would only want to install on a computer 4 | pandas 5 | matplotlib 6 | numpy 7 | scipy 8 | orjson 9 | lxml[html_clean] 10 | jsonc-parser 11 | openmeteo-requests 12 | requests-cache 13 | retry-requests 14 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/dart_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | linkcheck 4 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/gh_extension_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | gennaro-tedesco/gh-i 4 | gennaro-tedesco/gh-s 5 | dlvhdr/gh-dash 6 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/linux_python3_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | beets 4 | beets-filetote 5 | cython 6 | imgur-uploader 7 | iwlib 8 | pyacoustid 9 | pyautogui 10 | pylast 11 | pynvim 12 | python-language-server 13 | python-xlib 14 | thefuck 15 | twine 16 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/mix_archive_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | phx_new 4 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/node_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | # language support 4 | @elm-tooling/elm-language-server 5 | @prettier/plugin-php 6 | @fsouza/prettierd 7 | @astrojs/language-server 8 | @prisma/language-server 9 | @tailwindcss/language-server 10 | bash-language-server 11 | coffeescript 12 | cssmodules-language-server 13 | eslint 14 | fixjson 15 | html-minifier 16 | js-beautify 17 | jsonlint 18 | node-cljfmt 19 | npm 20 | prettier 21 | prettier-plugin-prisma 22 | prettier-plugin-toml 23 | pyright 24 | stylelint 25 | typescript 26 | typescript-language-server 27 | uglifycss 28 | vscode-langservers-extracted 29 | yaml-language-server 30 | 31 | # web tools/packages 32 | serve 33 | vercel 34 | 35 | # other tools 36 | @jamen/lorem 37 | git-stats 38 | mapscii 39 | moby 40 | readability-cli 41 | sqleton 42 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/ocaml_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | dune 4 | merlin 5 | ocaml-lsp-server 6 | odoc 7 | ocamlformat 8 | utop 9 | dune-release 10 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/pipx_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=requirements 2 | 3 | ansi2html 4 | cookiecutter 5 | csvkit 6 | cube-scramble-cli 7 | currencyconverter 8 | diceware 9 | eyeD3 10 | greasyfork-archive 11 | pypyp 12 | setup-cfg-fmt 13 | speedtest-cli 14 | supervisor 15 | termdown 16 | termgraph 17 | time-in 18 | urlscan 19 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/python3_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=requirements 2 | 3 | Pygments 4 | black 5 | codespell 6 | exifread 7 | feedgen 8 | flake8 9 | geopy 10 | giturlparse 11 | idna 12 | ipdb 13 | ipython 14 | jinjanator 15 | mlength 16 | phonenumbers 17 | pip 18 | pipenv 19 | pipx 20 | platformdirs 21 | pyYAML 22 | pyflyby 23 | pyperclip 24 | pysrt 25 | python-frontmatter 26 | reorder_editable 27 | rich 28 | rifleman 29 | rsa 30 | selenium 31 | setuptools 32 | srt 33 | toml 34 | trash-cli 35 | watchfiles 36 | yt-dlp 37 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/ruby_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | # lsp/linting 4 | rubocop 5 | -------------------------------------------------------------------------------- /.config/yadm/package_lists/wsl_packages.txt: -------------------------------------------------------------------------------- 1 | # vim: ft=conf 2 | 3 | python3-pip 4 | tree 5 | npm 6 | yarn 7 | libicu-dev 8 | libmagic-dev 9 | silversearcher-ag 10 | ripgrep 11 | jq 12 | datamash 13 | entr 14 | ffmpeg 15 | fzf 16 | figlet 17 | lynx 18 | wget 19 | unar 20 | software-properties-common 21 | todotxt-cli 22 | gcc 23 | -------------------------------------------------------------------------------- /.config/zsh/.gitignore: -------------------------------------------------------------------------------- 1 | personal_aliases 2 | tokens 3 | directory_aliases 4 | secrets 5 | -------------------------------------------------------------------------------- /.config/zsh/cache_aliases.zsh: -------------------------------------------------------------------------------- 1 | # periodically cache my aliases so I can reconstruct the meaning of commands using them 2 | # should be the last thing run when starting zsh 3 | # meant to be used as part of HPI https://github.com/purarue/HPI 4 | 5 | hash evry && evry 1 week -zsh_alias_cache && { 6 | ALIAS_CACHE_BACKUP_DIR="$(python3 -m my.utils.backup_to 'zsh_aliases')" || exit $? 7 | ALIAS_CACHE_TARGET="${ALIAS_CACHE_BACKUP_DIR}/$(date +'%s')-$(uname)" 8 | alias | sort >"${ALIAS_CACHE_TARGET}" 9 | unset ALIAS_CACHE_BACKUP_DIR ALIAS_CACHE_TARGET 10 | } 11 | -------------------------------------------------------------------------------- /.config/zsh/cd.zsh: -------------------------------------------------------------------------------- 1 | # bindings to change my directory in the shell 2 | # 3 | # Alt+left arrow/Alt+H to move up a dir 4 | up-dir() { 5 | cd '..' 6 | zle reset-prompt 7 | } 8 | zle -N up-dir 9 | bindkey '^[[1;3D' up-dir 10 | bindkey '^[h' up-dir 11 | 12 | # Alt+right arrow/Alt+L to launch fzf cd (move into dir) 13 | bindkey '^[[1;3C' fzf-cd-widget 14 | bindkey '^[l' fzf-cd-widget 15 | 16 | CD() { 17 | local chosen 18 | cd ~ 19 | chosen="$(fd -L --type d | fzf --no-multi --height=10 --reverse --preview="tree -C {}")" 20 | [[ -z "$chosen" ]] && return 1 21 | cd "$chosen" || return $? 22 | } 23 | -------------------------------------------------------------------------------- /.config/zsh/completions/_binary_completion: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # complete any command that takes another command as its arguments 3 | 4 | function _binary_completion() { 5 | _alternative 'commands: :_path_commands' 6 | } 7 | -------------------------------------------------------------------------------- /.config/zsh/completions/_services: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | #compdef services 3 | 4 | function _services() { 5 | _arguments '1: :(start stop)' 6 | } 7 | -------------------------------------------------------------------------------- /.config/zsh/completions/_trackpad: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | #compdef trackpad 3 | 4 | function _trackpad() { 5 | _arguments '1: :(enable disable)' 6 | } 7 | -------------------------------------------------------------------------------- /.config/zsh/completions/_transparent: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | #compdef transparent 3 | 4 | function _transparent() { 5 | _arguments \ 6 | '1: :(enable disable)' \ 7 | '2: :(target)' 8 | } 9 | -------------------------------------------------------------------------------- /.config/zsh/completions/_volume: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | #compdef volume 3 | 4 | function _volume() { 5 | _arguments '1: :(up down mute micmute)' 6 | } 7 | -------------------------------------------------------------------------------- /.config/zsh/functions/add-to-path: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | # adds the passed directory or the current directory to your $PATH 3 | 4 | add-to-path() { 5 | local toadd 6 | toadd="${1:-$(pwd)}" 7 | if [[ ! -d "$toadd" ]]; then 8 | echo "Not a directory: $toadd" >&2 9 | return 1 10 | fi 11 | # check if already in path 12 | if [[ ":$PATH:" == *":$toadd:"* ]]; then 13 | echo "$toadd already in path" >&2 14 | return 1 15 | fi 16 | export PATH="$toadd:$PATH" 17 | } 18 | -------------------------------------------------------------------------------- /.config/zsh/functions/cdp: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # cd back to the top of the git repo you're in 3 | 4 | cdp() { 5 | local TEMP_PWD="$PWD" 6 | while [[ ! -d ./.git ]]; do 7 | cd .. 8 | # if we weren't in a git repo, and we hit root 9 | if [[ $PWD == / ]]; then 10 | echo "Could not find a git repo in the current tree..." >&2 11 | cd "$TEMP_PWD" 12 | break 13 | fi 14 | done 15 | OLDPWD="$TEMP_PWD" 16 | } 17 | -------------------------------------------------------------------------------- /.config/zsh/functions/cdtmp: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # cd to a new tmp directory 3 | 4 | cdtmp() { 5 | local cdto 6 | local basetemp="${TMPDIR:-/tmp}" 7 | local cdtmpbase="${basetemp}/cdtmp" 8 | mkdir -p "$cdtmpbase" 9 | cdto="$(mktemp -p "$cdtmpbase" -d XXXXXXXXXX)" 10 | cd "$cdto" 11 | } 12 | -------------------------------------------------------------------------------- /.config/zsh/functions/duck: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # searches duckduckgo on the command line using lynx 3 | # duck "TERMS TO SEARCH FOR" 4 | 5 | function duck() { 6 | lynx "duckduckgo.com/lite?kd=-1&kp=-1&q=$*" 7 | } 8 | -------------------------------------------------------------------------------- /.config/zsh/functions/fkill: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # fkill - kill process 3 | # use fzf to match against a process and kill it 4 | 5 | fkill() { 6 | local pid 7 | pid="$(fpick)" || return $? 8 | kill -${1-15} "$pid" 9 | } 10 | -------------------------------------------------------------------------------- /.config/zsh/functions/flocate: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # fuzzy search for files on the entire system 3 | # and cd to the enclosing directory 4 | 5 | function flocate() { 6 | case "$ON_OS" in 7 | mac*) 8 | echo "Use 'mdfind' instead" >&2 9 | return 1 10 | ;; 11 | esac 12 | local FZFFOUNDFILENAME="$(locate / | fzf +m --preview='${HOME}/.config/fzf_preview {}')" 13 | # go to directory if its a directory, else go to enclosing directory 14 | if [[ -d "$FZFFOUNDFILENAME" ]]; then 15 | cd "$FZFFOUNDFILENAME" 16 | else 17 | cd "$(dirname "$FZFFOUNDFILENAME")" 18 | fi 19 | } 20 | -------------------------------------------------------------------------------- /.config/zsh/functions/fpick: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # fpick - pick a process 3 | # use fzf to match against a process, print its PID 4 | 5 | fpick() { 6 | local pid procs 7 | procs="$(ps -ef)" 8 | pid="$(sed 1d <<<"${procs}" | fzf -m --tac | awk '{print $2}')" 9 | [[ -z "$pid" ]] && return 1 10 | printf "%s\n" "$pid" 11 | } 12 | -------------------------------------------------------------------------------- /.config/zsh/functions/fwait: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # fwait 3 | # use fzf to match against a process and wait for it to finish 4 | # typically used like: 5 | # fwait && echo 'do something else' 6 | 7 | fwait() { 8 | local pid procs 9 | procs="$(ps -ef)" 10 | pid="$(sed 1d <<<"${procs}" | fzf +m --tac -q "$*" | awk '{print $2}')" 11 | [[ -z "$pid" ]] && return 1 12 | ps -opid "${pid}" || return 1 # make sure its still running. might have exited in the time between user selection and now 13 | watch -g ps -opid "${pid}" 14 | } 15 | -------------------------------------------------------------------------------- /.config/zsh/functions/mkcd: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # Create a new directory and enter it 3 | # Source: https://unix.stackexchange.com/a/9124 4 | 5 | function mkcd() { 6 | case "$1" in 7 | */.. | */../) cd -- "$1" ;; # that doesn't make any sense unless the directory already exists 8 | /*/../*) (cd "${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd -- "$1" ;; 9 | /*) mkdir -p "$1" && cd "$1" ;; 10 | */../*) (cd "./${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd "./$1" ;; 11 | ../*) (cd .. && mkdir -p "${1#.}") && cd "$1" ;; 12 | *) mkdir -p "./$1" && cd "./$1" ;; 13 | esac 14 | } 15 | -------------------------------------------------------------------------------- /.config/zsh/functions/ranger: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # wraps ranger to cd to rangers' directory when exiting 3 | # Modified from: 4 | # https://github.com/ranger/ranger/wiki/Integration-with-other-programs#changing-directories 5 | 6 | ranger() { 7 | _call_ranger() { 8 | if [[ -n "$PIPENV_ACTIVE" ]]; then 9 | /usr/bin/ranger "$@" || return $? 10 | else 11 | command ranger "$@" || return $? 12 | fi 13 | 14 | } 15 | 16 | local IFS tempfile 17 | local -a ranger_args=() 18 | IFS=$'\t\n' 19 | tempfile="$(mktemp -t ranger.XXXXXX)" 20 | ranger_args+=(--cmd="map S chain shell echo %d > "$tempfile"; quitall!") 21 | ranger_args+=("$@") 22 | 23 | _call_ranger "${ranger_args[@]}" 24 | [[ -f "$tempfile" ]] && cd -- "$(cat "$tempfile")" 25 | command rm -f "$tempfile" 26 | unfunction _call_ranger 27 | } 28 | -------------------------------------------------------------------------------- /.config/zsh/functions/tm: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # tm - create new tmux session, or switch to existing one 3 | # `tm` to run tmpick 4 | # `tm irc` will attach to the irc session (if it exists), else it will create it. 5 | 6 | tm() { 7 | [[ -n "$TMUX" ]] && change="switch-client" || change="attach-session" 8 | # if name specified, create/attach 9 | if [[ -n $1 ]]; then 10 | tmux $change -t "$1" 2>/dev/null || (tmux new-session -d -s "$1" && tmux $change -t "$1") 11 | return 12 | fi 13 | tmpick 14 | } 15 | -------------------------------------------------------------------------------- /.config/zsh/functions/tmpick: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # pick a tmux session if active, else attach/create a new one 3 | 4 | tmpick() { 5 | if [[ -n "$TMUX" ]]; then 6 | # if in tmux, pick a window 7 | tmux choose-window 8 | else 9 | # else 10 | if tmux list-sessions >/dev/null 2>&1; then 11 | # if tmux is active somewhere, attach 12 | tmux attach 13 | else 14 | tmux 15 | fi 16 | fi 17 | } 18 | -------------------------------------------------------------------------------- /.config/zsh/functions/update: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # Update typically used packages 3 | 4 | function update() { 5 | wait-for-internet --text "(waiting for internet)" 6 | echo "Updating system (pacman/brew/termux) packages..." 7 | case "$ON_OS" in 8 | mac*) 9 | brew update && brew upgrade 10 | brew upgrade --cask 11 | ;; 12 | linux_arch*) 13 | paru -Syu 14 | housekeeping-info 15 | havecmd flatpak && flatpak update 16 | ;; 17 | android*) 18 | pkg update 19 | ;; 20 | windows*) 21 | sudo apt update && sudo apt upgrade 22 | ;; 23 | esac 24 | yadm bootstrap 25 | } 26 | -------------------------------------------------------------------------------- /.config/zsh/functions/which-cat: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | #runs which, and prints the contents of the function/script 3 | 4 | function which-cat() { 5 | local COMMAND_OUTPUT USER_INPUT 6 | USER_INPUT="${1:?Must provide a command to lookup}" 7 | if COMMAND_OUTPUT="$(which "${USER_INPUT}")"; then 8 | # if the file is readable 9 | if [[ -r "${COMMAND_OUTPUT}" ]]; then 10 | if iconv --from-code="utf-8" --to-code="utf-8" "${COMMAND_OUTPUT}" >/dev/null 2>&1; then 11 | command cat "${COMMAND_OUTPUT}" 12 | else 13 | file "${COMMAND_OUTPUT}" 14 | fi 15 | else 16 | # error finding command, or its an alias/function 17 | printf '%s\n' "${COMMAND_OUTPUT}" 18 | fi 19 | else 20 | printf '%s\n' "${COMMAND_OUTPUT}" >&2 21 | fi 22 | } 23 | -------------------------------------------------------------------------------- /.config/zsh/hpi.zsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/zsh 2 | # on some machines (WSL/termux), 3 | # I can't sync to the ~/.config directory easily 4 | # so this is a workaround, which syncs to somewhere 5 | # else syncthing has access to and periodically 6 | # rsyncs to the ~/.config directory 7 | # this is called from android.zsh/windows.zsh files 8 | 9 | sync_hpi_config() { 10 | local hpi_synced_dir 11 | echo 'Syncing HPI config...' 12 | for base in "$WHOME" "$HOME/storage/shared"; do 13 | hpi_synced_dir="${base}/hpi_config" 14 | [[ -d "$hpi_synced_dir" ]] || continue 15 | rsync -Pavh "$hpi_synced_dir/my" ~/.config/my/ 16 | chmod -x ~/.config/my/my/config/*.py 17 | return 0 18 | done 19 | printf 'Could not find synced HPI config\n' 20 | } 21 | -------------------------------------------------------------------------------- /.config/zsh/source_aliases.zsh: -------------------------------------------------------------------------------- 1 | ALIAS_DIR="${ZDOTDIR}/aliases" 2 | source "${ALIAS_DIR}/aliases" # General aliases 3 | source "${ALIAS_DIR}/git_aliases" # Git aliases (from oh-my-zsh) 4 | source "${ALIAS_DIR}/project_aliases" # Aliases for my own projects 5 | source "${ALIAS_DIR}/dev_aliases" # language tooling/programming aliases 6 | # Personal Aliases (e.g. ssh to servers) 7 | source_if_exists "${HPIDATA}/personal_aliases" 8 | # Tokens for interacting with APIs etc 9 | source_if_exists "${HPIDATA}/tokens" 10 | -------------------------------------------------------------------------------- /.config/zsh/ssh.zsh: -------------------------------------------------------------------------------- 1 | # add both my SSH keys to an agent 2 | # this is so that I can use multiple Github accounts 3 | SHARED_AUTH_SOCK="${TMPDIR:-/tmp}/zsh_shared_socket" 4 | if [[ ! -S "$SHARED_AUTH_SOCK" ]]; then 5 | eval "$(ssh-agent)" 6 | # link socket to a shared location 7 | ln -sf "$SSH_AUTH_SOCK" "$SHARED_AUTH_SOCK" 8 | ssh-add -l >/dev/null || { 9 | for ssh_key in "${HOME}/.ssh/id_rsa" "${HOME}/.ssh/id_ed25519"; do 10 | if [[ -e "$ssh_key" ]]; then 11 | ssh-add "$ssh_key" 12 | else 13 | printf "Key doesn't exist: %s\n" "$ssh_key" 14 | fi 15 | done 16 | } 17 | fi 18 | export SSH_AUTH_SOCK="$SHARED_AUTH_SOCK" 19 | -------------------------------------------------------------------------------- /.config/zsh/windows.zsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | # run bgproc jobs once every 2 hours 3 | # https://github.com/purarue/bgproc 4 | evry 1 hour -run_windows_jobs && bgproc_on_machine -on 5 | 6 | # sync HPI config from syncthing directory to WSL .config/my directory 7 | evry 10 minutes -sync_hpi_config && sync_hpi_config 8 | 9 | # update mod time on a file so I can figure out when I last 10 | # used my windows machine, to make sure I update it periodically 11 | touch "${HOME}/data/windows_terminal_opened" 12 | 13 | # In WSL, cache the path to the windows home directory, 14 | # something like /mnt/c/Users/Name 15 | WHOME_FILE="${HOME}/.cache/whome" 16 | [[ -d "${HOME}/.cache" ]] || mkdir -p "${HOME}/.cache" 17 | [[ -f "${WHOME_FILE}" ]] || wslpath "$(wslvar USERPROFILE)" >"${WHOME_FILE}" 18 | WHOME="$(cat "${WHOME_FILE}")" 19 | export WHOME 20 | -------------------------------------------------------------------------------- /.local/scripts/cross-platform/editor: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec ttt nvim "$@" 3 | -------------------------------------------------------------------------------- /.local/scripts/cross-platform/lock-screen: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Lock the screen 3 | # the daemon process creates the pixelated image every minute in the background 4 | # so that i3lock doesn't have to wait for the image to be generated when run 5 | 6 | case "$ON_OS" in 7 | mac*) 8 | pmset displaysleepnow 9 | exit 0 10 | ;; 11 | linux*) 12 | if [ -n "$WAYLAND_DISPLAY" ]; then 13 | hyprlock 14 | elif [ "$1" = "-b" ]; then # daemon 15 | while true; do 16 | scrot --silent --overwrite "${HOME}/.cache/desktop.png" 17 | magick -scale 2% -scale 5000% "${HOME}/.cache/desktop.png" "${HOME}/.cache/pixel.png" 18 | sleep 120 19 | done 20 | else 21 | i3lock -ni "${HOME}/.cache/pixel.png" 22 | fi 23 | ;; 24 | *) 25 | echo "Dont know how to lock screen..." >&2 26 | ;; 27 | 28 | esac 29 | -------------------------------------------------------------------------------- /.local/scripts/cross-platform/playping: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Sends a notification-like ping 3 | 4 | case "$ON_OS" in 5 | linux*) 6 | exec paplay /usr/share/sounds/freedesktop/stereo/message.oga 7 | ;; 8 | mac*) 9 | exec afplay /System/Library/Sounds/Ping.aiff 10 | ;; 11 | windows*) 12 | exec powershell.exe -c '(New-Object Media.SoundPlayer "C:\Windows\Media\ding.wav").PlaySync();' 13 | ;; 14 | android_termux*) 15 | exec termux-vibrate 16 | ;; 17 | *) ;; 18 | esac 19 | -------------------------------------------------------------------------------- /.local/scripts/cross-platform/print-or-notify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # if on a terminal, just print what the user passed 3 | # as arguments or from STDIN. otherwise, use the notify script 4 | # here to send a notification 5 | 6 | TEXT="${*:-$(cat)}" 7 | 8 | if attached-to-terminal; then 9 | echo "$TEXT" 10 | else 11 | notify "${TEXT}" 12 | fi 13 | -------------------------------------------------------------------------------- /.local/scripts/generic/albumify-singles: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # assumes you're in the directory with the files you want to run 3 | # converts a bunch of singles to a bunch of albums with the individual 4 | # singles. This is useful to maintain album art for singles 5 | 6 | while read -r line; do 7 | name=$(remove-extension "$line") 8 | if [[ -f "$name" ]]; then 9 | echo "Error: ${name} already exists" >&2 10 | continue 11 | fi 12 | mkdir "$name" 13 | cp "$line" "$name" 14 | done < <(list-music) 15 | -------------------------------------------------------------------------------- /.local/scripts/generic/ansicolors: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | for attr in 0 1 4 5 7; do 3 | echo "------------------------------------------------" 4 | printf "ESC[%s;Foreground;Background - \n" $attr 5 | for fore in 30 31 32 33 34 35 36 37; do 6 | for back in 40 41 42 43 44 45 46 47; do 7 | printf '\033[%s;%s;%sm %02s;%02s\033[0m' \ 8 | $attr $fore $back $fore $back 9 | done 10 | printf '\n' 11 | done 12 | done 13 | -------------------------------------------------------------------------------- /.local/scripts/generic/audio2mp3: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # AUTHOR: gotbletu (@gmail|twitter|youtube|github|lbry) 3 | 4 | helpmsg() { 5 | printf "%s\n" "desc: convert to mp3 audio" 6 | printf "%s\n" "depend: ffmpeg lame" 7 | printf "\n" 8 | printf "%s\n" "usage: ${0##*/} [file]" 9 | printf "\n" 10 | printf "%s\n" " $ ${0##*/} file.m4a" 11 | printf "%s\n" " $ ${0##*/} file1.m4a file2.m4a file3.m4a" 12 | printf "%s\n" " $ ${0##*/} *.m4a" 13 | } 14 | if [ $# -lt 1 ]; then 15 | helpmsg 16 | exit 1 17 | elif [ "$1" = -h ] || [ "$1" = --help ]; then 18 | helpmsg 19 | exit 0 20 | else 21 | myArray=("$@") 22 | for arg in "${myArray[@]}"; do 23 | ffmpeg -i "$arg" -codec:a libmp3lame -qscale:a 2 "${arg%.*}.mp3" 24 | done 25 | fi 26 | -------------------------------------------------------------------------------- /.local/scripts/generic/auto-subtitle-install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # uses the auto-subtitle fork which removes a couple bugs 3 | # https://github.com/Irvingouj/auto-subtitle 4 | # 5 | # for whatever reason that doesn't install ffmpeg-python, 6 | # so this injects that into that venv 7 | # 8 | # uses 3.11.9 since that is the last supported version by 9 | # openai-whisper 10 | set -ex 11 | if [[ -z "$PYENV_ROOT" ]]; then 12 | echo "PYENV_ROOT not set" >&2 13 | exit 1 14 | fi 15 | PYTHON_VER="3.11.9" 16 | PYTHON_311="$PYENV_ROOT/versions/$PYTHON_VER/bin/python" 17 | if [[ ! -f "$PYTHON_311" ]]; then 18 | echo "python $PYTHON_VER not found, installing..." >&2 19 | pyenv install "$PYTHON_VER" || exit $? 20 | fi 21 | pipx install --verbose git+https://github.com/Irvingouj/auto-subtitle --python "$PYTHON_311" 22 | pipx inject auto-subtitle ffmpeg-python 23 | -------------------------------------------------------------------------------- /.local/scripts/generic/basher-upgrade-all: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | while read -r pkg; do 4 | echo "Updating ${pkg}..." 1>&2 5 | basher upgrade "${pkg}" || exit $? 6 | done < <(basher outdated | spkglist) 7 | -------------------------------------------------------------------------------- /.local/scripts/generic/bashx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | SCRIPT="${1?:No script provided}" 3 | shift || true 4 | declare SCRIPT_PATH="$SCRIPT" 5 | if [[ ! -f "$SCRIPT_PATH" ]]; then 6 | SCRIPT_PATH="$(which "$SCRIPT_PATH")" 7 | fi 8 | exec bash -x "$SCRIPT_PATH" "$@" 9 | -------------------------------------------------------------------------------- /.local/scripts/generic/beet-search: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o pipefail 4 | set -e 5 | 6 | search_with_key() { 7 | local key="${1?:must provide key}" 8 | shift 9 | beet ls "${key}:$*" --path 10 | } 11 | 12 | search() { 13 | search_with_key 'albumartist_sort' "$@" || return $? 14 | search_with_key 'artist_sort' "$@" || return $? 15 | search_with_key 'album' "$@" || return $? 16 | search_with_key 'title' "$@" || return $? 17 | search_with_key 'composer_sort' "$@" || return $? 18 | } 19 | 20 | main() { 21 | if [[ -z "$*" ]]; then 22 | echo "Usage: beet-fzf " >&2 23 | return 1 24 | fi 25 | search "$@" | unique | fzf --preview 'beet info {}' --preview-window=right:50% 26 | } 27 | 28 | main "$@" || exit $? 29 | -------------------------------------------------------------------------------- /.local/scripts/generic/bookmark-open: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # allow me to open a URL from https://github.com/purarue/bookmark.txt 3 | 4 | ENTRY_CHOICE="$(bookmark -p list | head -n -2 | picker -p "Open which bookmark? > ")" 5 | URL="$(echo "${ENTRY_CHOICE}" | urlextract | head -n 1)" 6 | [ -z "${URL}" ] && exit 1 7 | openurl "${URL}" 8 | -------------------------------------------------------------------------------- /.local/scripts/generic/center-text: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Accepts a string as the first argument 3 | # Centers the text vertically on the screen 4 | 5 | MESSAGE="${1:?Specify the message to print as the first argument}" 6 | 7 | clear 8 | LINES="$(($(tput lines) / 2))" 9 | # center text vertically 10 | for _ in $(seq "${LINES}"); do 11 | echo 12 | done 13 | # center text horizontally 14 | COLUMNS="$(tput cols)" 15 | printf "%*s\n" $(((${#1} + COLUMNS) / 2)) "${MESSAGE}" 16 | # move prompt to bottom of screen 17 | for _ in $(seq $((LINES - 1))); do 18 | echo 19 | done 20 | -------------------------------------------------------------------------------- /.local/scripts/generic/click-repeat: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import time 4 | 5 | import pyautogui 6 | import click 7 | 8 | 9 | @click.command() 10 | @click.argument("SLEEP_TIME", type=int, default=1) 11 | def main(sleep_time: int) -> None: 12 | """ 13 | clicks the mouse (cross-platform) every few seconds 14 | """ 15 | click.echo( 16 | f"Clicking the mouse every {sleep_time} second{'s' if sleep_time != 1 else ''}..." 17 | ) 18 | while True: 19 | pyautogui.click() 20 | time.sleep(sleep_time) 21 | 22 | 23 | if __name__ == "__main__": 24 | main() 25 | -------------------------------------------------------------------------------- /.local/scripts/generic/clp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # accepts input from STDIN, sends text back to STDOUT 3 | # copies what it received to the clipboard 4 | # used in vim: 5 | # https://purarue.xyz/x/programming/languages/shell_tools/vim/magic_wands/ 6 | STDIN="$(cat)" 7 | printf '%s\n' "${STDIN}" 8 | printf '%s' "${STDIN}" | clipcopy 9 | if [[ "$(echo "${STDIN}" | wc -l)" == 1 ]]; then 10 | exec notify "${APP:-'clp'}" "$(printf 'Copied to clipboard: %s' "${STDIN}")" 11 | else 12 | exec notify "${APP:-'clp'}" "$(printf 'Copied %d lines to clipboard' "$(echo "${STDIN}" | wc -l)")" 13 | fi 14 | -------------------------------------------------------------------------------- /.local/scripts/generic/cstimer: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Run cstimer on my local machine 3 | 4 | set -e 5 | set -o pipefail 6 | 7 | main() { 8 | local clone_loc cache_dir 9 | # if cstimer server is already running, then open in browser 10 | if curl --silent http://localhost:4633 >/dev/null; then 11 | rm "$(evry location -open-cstimer)" 12 | backup-cubing 13 | else 14 | # otherwise run the server 15 | cache_dir="${XDG_CACHE_DIR:-${HOME}/.cache}" 16 | clone_loc="${cache_dir}/cstimer" 17 | [[ -e "$clone_loc" ]] || git clone 'https://github.com/purarue/cstimer' "$clone_loc" 18 | cd "$clone_loc" || exit 1 19 | make server 20 | fi 21 | } 22 | 23 | main || exit $? 24 | -------------------------------------------------------------------------------- /.local/scripts/generic/current-week: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import datetime 4 | 5 | print(int(datetime.date.today().strftime("%U"))) 6 | -------------------------------------------------------------------------------- /.local/scripts/generic/datenow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # prompt current date in lots of formats 3 | # and copy that to your command line 4 | 5 | print_dates() { 6 | date "+%m/%d/%y # us date" 7 | date "+%d/%m/%y # standard date" 8 | date "+%Y/%m/%d # YYYY/MM/DD (blog)" 9 | date "+%F # YYYY-MM-DD" 10 | date "+%F %T # YYYY-MM-DD HH:MM:SS" 11 | date "+%c # full date" 12 | date "+%A, %B %e, %Y, %l:%M:%S%p # now" 13 | date "+%s # epoch" 14 | } 15 | 16 | PICKED="$(print_dates | picker -p "Pick Date > ")" || exit $? 17 | DATESTR="$(cut -d "#" -f1 <<<"${PICKED}" | xargs echo)" 18 | printf '%s\n' "${DATESTR}" 19 | printf '%s' "${DATESTR}" | clipcopy 20 | notify "datenow" "Copied '${DATESTR}' to clipboard" 21 | -------------------------------------------------------------------------------- /.local/scripts/generic/decode64: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """Usage: 4 | decode64 SUBSTR HASH 5 | decode64 --help 6 | 7 | Will repetitvely base64 decode HASH till SUBSTR is in decoded string 8 | If SUBSTR is a number, will decode HASH that many times 9 | """ 10 | 11 | import base64 12 | import docopt 13 | 14 | assert __doc__ is not None 15 | args = docopt.docopt(__doc__) 16 | hash = args["HASH"] 17 | 18 | try: 19 | for _ in range(int(args["SUBSTR"])): 20 | hash = base64.b64decode(hash) 21 | except ValueError: 22 | while args["SUBSTR"].lower() not in str(hash.lower()): 23 | hash = base64.b64decode(hash) 24 | 25 | print(str(hash, "utf-8")) 26 | -------------------------------------------------------------------------------- /.local/scripts/generic/describe-evry-json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o pipefail 4 | 5 | main() { 6 | jq -r '.[] | select((.type == "tag_name") or .type == "till_next_pretty") | .body' | paste -d " " - - | sed -e 's/ / - /' || return $? 7 | } 8 | 9 | main || exit $? 10 | -------------------------------------------------------------------------------- /.local/scripts/generic/dict: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # AUTHOR: gotbletu (@gmail|twitter|youtube|github|lbry) 3 | 4 | helpmsg() { 5 | printf "%s\n" "desc: online dictionary lookup" 6 | printf "\n" 7 | printf "%s\n" "usage: ${0##*/} [word]" 8 | printf "\n" 9 | printf "%s\n" " $ ${0##*/} telomere" 10 | } 11 | if [ $# -lt 1 ]; then 12 | helpmsg 13 | exit 1 14 | elif [ "$1" = -h ] || [ "$1" = --help ]; then 15 | helpmsg 16 | exit 0 17 | fi 18 | exec curl -s dict://dict.org/d:"$1" | less 19 | -------------------------------------------------------------------------------- /.local/scripts/generic/discord-currently-listening-presence: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | wait-for-internet 3 | # https://github.com/purarue/currently_listening 4 | with-secrets currently_listening_py discord-presence --server-url wss://purarue.xyz/currently_listening/ws --image-url https://purarue.xyz/currently_listening/currently-listening-image "$@" 5 | sleep 30m 6 | -------------------------------------------------------------------------------- /.local/scripts/generic/docx-md: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | # convert a docx to markdown and open it in nvim 4 | TARGET="$(remove-extension "${1:?Provide the docx to convert as the first argument}").md" 5 | pandoc -s "$1" -t markdown -o "${TARGET}" 6 | exec nvim "${TARGET}" 7 | -------------------------------------------------------------------------------- /.local/scripts/generic/dragon-sink: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # brings up a prompt to drag files into. 3 | # If no flags are provided, copies any files 4 | # dragged into the prompt into the current directory. 5 | # if the --mv flag is provided, moves files instead 6 | declare cmd drg files 7 | [[ "$1" = "--mv" ]] && cmd="mv" || cmd="cp" 8 | drg="$(command -v dragon-drop)" || drg="$(command -v dragon)" || { 9 | echo "couldn't find the dragon-drop or dragon command" 10 | exit 1 11 | } 12 | files="$("$drg" --target --and-exit)" 13 | [[ -z "$files" ]] && exit 1 14 | while IFS= read -r f; do 15 | path="${f#file://}" 16 | $cmd -v "${path}" "$(pwd)/$(basename "${path}")" 17 | done <<<"$files" 18 | -------------------------------------------------------------------------------- /.local/scripts/generic/emoji: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | launch 'sh -c "kitty +kitten unicode_input text | clp"' 3 | -------------------------------------------------------------------------------- /.local/scripts/generic/exifalbumrename: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Renames a song to use its EXIF attributes 3 | # I use this when downloading stuff using 4 | # https://github.com/iheanyi/bandcamp-dl 5 | # since that slugifies names 6 | 7 | if [[ -z "$1" ]]; then 8 | echo "Must provide paths to rename" >&2 9 | exit 1 10 | fi 11 | 12 | # cd so moving files is easier 13 | # this is best run in the same directory as what you're modifying 14 | cd "$(realpath "$(dirname "$1")")" || exit 15 | 16 | for path in "$@"; do 17 | ppath="$(basename "${path}")" || continue 18 | trackno="$(exifattr "${ppath}" 'Track')" || continue 19 | trackname="$(exifattr "${ppath}" 'Title')" || continue 20 | ext="$(get-extension "${ppath}")" || continue 21 | newpath="$(printf '%d - %s.%s' "${trackno}" "${trackname}" "${ext}")" 22 | mv -v "${ppath}" "${newpath}" 23 | done 24 | -------------------------------------------------------------------------------- /.local/scripts/generic/exifinfo: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | FILE="${1?Must provide a file as the first argument to dump info about}" 4 | if [ ! -e "${FILE}" ]; then 5 | printf "%s does not exist\n" "${FILE}" 6 | exit 1 7 | fi 8 | if [ -d "${FILE}" ]; then 9 | printf "Path must be a file, %s is a directory\n" "${FILE}" 10 | exit 1 11 | fi 12 | 13 | # Use exiftool to get data, but don't use 14 | # its mime type - doesn't match anything 15 | # I can figure out. 16 | { 17 | exiftool "${FILE}" | grep -v "^MIME Type" 18 | printf "MIME Type : %s" "$(file-mime "${FILE}")" 19 | } | sort 20 | 21 | if [ -n "$2" ]; then 22 | shift 23 | echo "Warning: ignoring additional arguments: $*" >&2 24 | fi 25 | -------------------------------------------------------------------------------- /.local/scripts/generic/ffmpeg-then-notify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ffmpeg "$@" >>/tmp/mpv-ffmpeg.log 2>&1 || { 3 | notify -u critical "ffmpeg failed, check log" 4 | exit 1 5 | } 6 | notify "done encoding" 7 | -------------------------------------------------------------------------------- /.local/scripts/generic/figlet-one-line: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | runs figlet and renders the text so that it can be 5 | embedded into code as a single string with newlines 6 | 7 | copies that to my clipboard 8 | """ 9 | 10 | 11 | import subprocess 12 | 13 | import click 14 | from pura.clipboard import clipcopy 15 | 16 | 17 | @click.command(help=__doc__) 18 | @click.argument("TEXT") 19 | def main(text: str) -> None: 20 | resp = subprocess.check_output(["figlet", text]).decode("utf-8") 21 | rendered = repr(resp) 22 | clipcopy(rendered) 23 | click.echo(f"copied to clipboard:\n\n{resp}") 24 | 25 | 26 | if __name__ == "__main__": 27 | main() 28 | -------------------------------------------------------------------------------- /.local/scripts/generic/file-modified-ago: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # prints how long a file was modified ago in human readable text 3 | 4 | # disable debug mode, if enabled 5 | [[ -n "$EVRY_DEBUG" ]] && unset EVRY_DEBUG 6 | [[ -n "$EVRY_JSON" ]] && unset EVRY_JSON 7 | 8 | FILE="${1?Error: no file given}" 9 | shift 10 | 11 | if [[ ! -r "$FILE" ]]; then 12 | echo "Error: cannot read file: $FILE" >&2 13 | exit 1 14 | fi 15 | 16 | FILE_MODIFIED_AT="$(stat -c %Y "$FILE")" || exit 1 17 | CURRENT_TIME="$(date +%s)" || exit 1 18 | 19 | MODIFIED_AGO="$((CURRENT_TIME - FILE_MODIFIED_AT))" 20 | MODIFIED_PRETTY="$(EVRY_JSON=1 evry duration "$MODIFIED_AGO"s | jq '[.[] | {key: .type, value: .body}] | from_entries | .duration_pretty' -r)" 21 | echo "$MODIFIED_PRETTY" 22 | -------------------------------------------------------------------------------- /.local/scripts/generic/generate-subs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # uses auto-subtitle (a local openai whisper subtitle generator wrapper) script 3 | # installed in a pipx venv: 4 | # https://purarue.xyz/d/auto-subtitle-install?redirect 5 | 6 | if [[ ! -f "$1" ]]; then 7 | echo "Usage: $0 " 8 | exit 1 9 | fi 10 | 11 | process_file() { 12 | file="$1" 13 | full_path="$(realpath "$file")" 14 | srt_path="${full_path%.*}.srt" 15 | if [[ ! -f "$srt_path" ]]; then 16 | echo "Generating subtitles for $full_path" >&2 17 | auto_subtitle --srt_only true "$full_path" --model medium.en || { 18 | echo "Failed to generate subtitles for $file" >&2 19 | rm -f "$srt_path" 20 | } 21 | fi 22 | } 23 | 24 | for file in "$@"; do 25 | process_file "$file" 26 | done 27 | -------------------------------------------------------------------------------- /.local/scripts/generic/genpass: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | # generates a password and puts it on your clipboard 7 | # uses https://github.com/purarue/genpasswd 8 | # or 'pip install diceware' 9 | generate() { 10 | if [[ -n "$USE_DICEWARE" ]]; then 11 | if [[ -n "$1" ]]; then 12 | diceware "$@" 13 | else 14 | diceware -d '_' -n 5 "$@" 15 | fi 16 | else 17 | genpasswd "$@" || return $? 18 | fi 19 | } 20 | 21 | pw="$(generate "$@")" || exit $? 22 | echo "$pw" 23 | echo "$pw" | clipcopy 24 | echo 'Copied password to clipboard' 25 | notify 'Copied password to clipboard' 26 | -------------------------------------------------------------------------------- /.local/scripts/generic/ghstars: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | if ! has-git-remote; then 3 | echo 'no git remote' >&2 4 | exit 1 5 | fi 6 | declare url 7 | url="$(git open --print | cut -d'/' -f4-5)" 8 | if [[ -z "$url" ]]; then 9 | echo 'no url' >&2 10 | exit 1 11 | fi 12 | if resp="$(gh api --paginate "repos/${url}/stargazers")"; then 13 | jq '.[].login' -r <<<"$resp" 14 | else 15 | printf 'Could not fetch repos/%s/stargazers\n' "$url" 16 | exit 1 17 | fi 18 | -------------------------------------------------------------------------------- /.local/scripts/generic/gifpreview: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # accepts a gif as the first argument, 3 | # converts and prints the path to the 4 | # middle frame of the gif 5 | 6 | path="${1:?"No file given to convert to a gif"}" 7 | # validate input 8 | case "$path" in 9 | *.gif) ;; 10 | 11 | *) 12 | echo "Must provide a .gif file as the argument" 1>&2 13 | exit 1 14 | ;; 15 | esac 16 | [ -e /tmp/gifpreview ] && rm -rf /tmp/gifpreview 17 | mkdir /tmp/gifpreview 18 | # convert gif to images 19 | magick -coalesce "$path" /tmp/gifpreview/preview.png || exit 1 20 | # get the middle image 21 | find /tmp/gifpreview >/tmp/gifpreview/images.log 22 | middleline="$(($(wc -l &1 11 | exit 1 12 | fi 13 | verify_giturlparse || { 14 | echo "Couldn't import giturlparse, 'pip install giturlparse'" >&2 15 | exit 1 16 | } 17 | if https_url="$(printf '%s' "${remote_url}" | /usr/bin/env python3 -c "import sys, giturlparse; print(giturlparse.parse(sys.stdin.read().strip()).urls['https'])" 2>/dev/null)"; then 18 | echo "${https_url}" 19 | exit 0 20 | else 21 | printf "Could not parse %s into a HTTP URL properly.\n" "${remote_url}" 2>&1 22 | exit 1 23 | fi 24 | else 25 | echo "Not currently in a git repo" 2>&1 26 | exit 1 27 | fi 28 | -------------------------------------------------------------------------------- /.local/scripts/generic/gron-to-csv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # convert gron output to csv 3 | # replace the = with a comma, remove the trailing semicolon 4 | # 5 | # need to re-add those if you want to convert back to json 6 | 7 | input="${1:?Please provide input file}" 8 | gron --monochrome "$input" | sed -e 's/;$//' -e 's/ = /,/' 9 | -------------------------------------------------------------------------------- /.local/scripts/generic/heart: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import click 4 | 5 | HEARTS = [ 6 | "❤️", 7 | "🧡", 8 | "💛", 9 | "💚", 10 | "💙", 11 | "💜", 12 | "🤍", 13 | "🤎", 14 | "💖", 15 | ] 16 | 17 | 18 | @click.command() 19 | @click.option("-a", "--all", "_all", is_flag=True, help="Print all hearts") 20 | def main(_all: bool) -> None: 21 | chosen: str 22 | if _all: 23 | chosen = "".join(HEARTS) 24 | else: 25 | 26 | import random 27 | 28 | chosen = random.choice(HEARTS) 29 | click.echo(chosen) 30 | 31 | 32 | if __name__ == "__main__": 33 | main() 34 | -------------------------------------------------------------------------------- /.local/scripts/generic/in-path: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # check each directory in $PATH for script name 4 | # if found, print full path to script and exit 5 | 6 | declare script_name="${1?missing script name}" 7 | declare target 8 | for dir in ${PATH//:/ }; do 9 | target="${dir}/${script_name}" 10 | if [[ -f "${target}" ]]; then 11 | echo "${target}" 12 | if [[ ! -x "${target}" ]]; then 13 | echo "Warning: ${target} is not executable" >&2 14 | fi 15 | fi 16 | done 17 | -------------------------------------------------------------------------------- /.local/scripts/generic/jqc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # pipe data into this, pass any jq filters as arguments 3 | 4 | set -o pipefail 5 | set -e 6 | 7 | jsonc-to-json | jq "$@" 8 | -------------------------------------------------------------------------------- /.local/scripts/generic/jsonc-to-json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import json 4 | import fileinput 5 | import contextlib 6 | 7 | from jsonc_parser.parser import JsoncParser 8 | 9 | 10 | def main() -> None: 11 | lines = list(fileinput.input()) 12 | data = JsoncParser.parse_str("\n".join(lines)) 13 | print(json.dumps(data, indent=4)) 14 | 15 | 16 | if __name__ == "__main__": 17 | with contextlib.suppress(KeyboardInterrupt): 18 | main() 19 | -------------------------------------------------------------------------------- /.local/scripts/generic/jumplist: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # generates a jumplist of directories, so I can cd to one 3 | # https://purarue.xyz/d/cd.zsh?dark 4 | # 5 | # using 6 | # https://purarue.xyz/d/tttlist?dark 7 | # and the commits modules to scan my local repos 8 | # https://github.com/karlicoss/HPI/blob/master/my/coding/commits.py 9 | 10 | set -e 11 | set -o pipefail 12 | 13 | # update tttlist cache once a day 14 | tttlist_cached() { 15 | evry 1d -tttlist && tttlist >~/.cache/tttlist 16 | cat ~/.cache/tttlist 17 | } 18 | 19 | { 20 | tttlist_cached 21 | hpi query my.coding.commits.repos -s | jq -r 22 | } | grep -v '^/tmp' | unique || exit $? 23 | -------------------------------------------------------------------------------- /.local/scripts/generic/list-git-dirs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR="$1" 4 | shift 5 | if [[ -z "$DIR" ]]; then 6 | echo "Usage: list-git-dirs " >&2 7 | exit 1 8 | fi 9 | 10 | exec fd --base-directory "${DIR}" -LIH --type d '^.git$' "$@" --absolute-path -x echo '{//}' 11 | -------------------------------------------------------------------------------- /.local/scripts/generic/list-my-git-repos: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | RELATIVE=0 6 | # accept -r to print relative to home directory 7 | [[ "$1" == "-r" ]] && RELATIVE=1 8 | 9 | parallel -j+0 'list-git-dirs {}' <~/.cache/repo_bases.txt | { 10 | if ((RELATIVE)); then 11 | sed -e "s@^$HOME/@~/@" 12 | else 13 | cat 14 | fi 15 | } 16 | -------------------------------------------------------------------------------- /.local/scripts/generic/mal_sources_toggle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -u 4 | 5 | declare SCRIPT="${HPIDATA}/reminder-sink/mal_sources" 6 | 7 | [[ -e "$SCRIPT" ]] || { 8 | printf 'Could not find script at %s\n' "$SCRIPT" 1>&2 9 | exit 1 10 | } 11 | 12 | if [[ -x "$SCRIPT" ]]; then 13 | echo 'Script is executable, making it non-executable' 14 | chmod -x "$SCRIPT" 15 | else 16 | echo 'Script is not executable, making it executable' 17 | chmod +x "$SCRIPT" 18 | fi 19 | -------------------------------------------------------------------------------- /.local/scripts/generic/manual_on_os: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | case "$(uname -s)" in 4 | Linux*) 5 | if command -v termux-setup-storage >/dev/null 2>&1; then 6 | ON_OS='android' 7 | else 8 | # check if we're in WSL 9 | case "$(uname -r)" in 10 | *Microsoft*) 11 | ON_OS='windows' 12 | ;; 13 | *) 14 | ON_OS='linux' 15 | ;; 16 | esac 17 | fi 18 | ;; 19 | Darwin*) 20 | ON_OS='mac' 21 | ;; 22 | *) 23 | printf "Unknown Operating System...\n" >&2 24 | ;; 25 | esac 26 | 27 | echo "$ON_OS" 28 | -------------------------------------------------------------------------------- /.local/scripts/generic/mpv-ffmpeg-extract: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | TMPDIR="${TMPDIR:-/tmp}/mpv-logs" 4 | LOGFILE="$(newest "$TMPDIR")" || exit 1 5 | LINE="$(grep '\[encode\] ffmpeg' "$LOGFILE" | tail -n 1)" 6 | if [[ -z "$LINE" ]]; then 7 | echo "No ffmpeg command found in $LOGFILE" >&2 8 | exit 1 9 | fi 10 | 11 | # remove everything before [encode] 12 | echo "ffmpeg ${LINE#*\[encode\] ffmpeg }" 13 | -------------------------------------------------------------------------------- /.local/scripts/generic/mpv-pause-all: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # pauses or unpauses all mpv instances 3 | # pass 'false' to unpause, 'true' to pause (default) 4 | 5 | case "$1" in 6 | "true" | "false" | '') ;; 7 | *) 8 | echo "Usage: $0 [true|false]" >&2 9 | exit 1 10 | ;; 11 | esac 12 | CMD="${1:-true}" 13 | 14 | for socket in $(mpv-active-sockets); do 15 | printf '{ "command": ["set_property", "pause", %s] }\n' "$CMD" | socat - "$socket" 16 | done 17 | -------------------------------------------------------------------------------- /.local/scripts/generic/mpv_signal_daemon: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # sends a signal to the mpv_history_daemon to check 3 | # if new sockets have been added or any mpv instances 4 | # have quit 5 | # 6 | # https://github.com/purarue/mpv-history-daemon 7 | 8 | pkill -f 'python3 -m mpv_history_daemon daemon' -RTMIN || true 9 | 10 | # if you launch like 'mpv-history-daemon daemon' then 11 | # you can use this instead 12 | # pkill -f 'mpv_history_daemon daemon' -RTMIN || true 13 | -------------------------------------------------------------------------------- /.local/scripts/generic/mv-classify-videos-by-rotation: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | for vid in "$@"; do 4 | rotation="$(exifattr "$vid" Rotation)" || exit $? 5 | mkdir -p "$rotation" 6 | mv -vn "$vid" "$rotation" 7 | done 8 | -------------------------------------------------------------------------------- /.local/scripts/generic/norg-to-markdown: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # converts neorg file to markdown 3 | # https://github.com/nvim-neorg/neorg 4 | 5 | FILENAME="${1?Error: No filename given}" 6 | FULL_PATH="$(realpath "$FILENAME")" 7 | TARGET="$(replace-extension "$FULL_PATH" md)" 8 | 9 | GIT_DIR="$XDG_CACHE_HOME/norg-pandoc" 10 | 11 | if [[ ! -d "$GIT_DIR" ]]; then 12 | git clone https://github.com/boltlessengineer/norg-pandoc "$GIT_DIR" || exit 1 13 | fi 14 | 15 | cd "$GIT_DIR" || exit 1 16 | exec pandoc --from ./init.lua --to gfm "$FULL_PATH" -o "$TARGET" 17 | -------------------------------------------------------------------------------- /.local/scripts/generic/optigif: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # optimize gif 3 | OLD_GIF="${1:?provide gif to optimize as first argument}" 4 | NEW_GIF="$(remove-extension "${OLD_GIF}")-opt.gif" 5 | TMP_GIF='/tmp/optimized.gif' 6 | rm -rf "${TMP_GIF}" 7 | gifsicle --colors 256 -O3 "${OLD_GIF}" -o "${TMP_GIF}" && cp -v "${TMP_GIF}" "${NEW_GIF}" || exit $? 8 | # overwrite if specified 9 | [ -n "${OPTIGIF_OVERWRITE}" ] && du -h "${OLD_GIF}" "${NEW_GIF}" && mv -v "${NEW_GIF}" "${OLD_GIF}" 10 | -------------------------------------------------------------------------------- /.local/scripts/generic/optijpg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | FILE="${1:?provide jpeg to optimize as first argument}" 3 | exec jpegtran -copy none -optimize -outfile "${FILE}" "${FILE}" 4 | -------------------------------------------------------------------------------- /.local/scripts/generic/org-to-md: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | readonly INPUT="${1:?Provide the .org file to convert from as the first argument}" 4 | readonly OUTPUT="${2:?Provide the output.md path as the second argument}" 5 | 6 | pandoc -t markdown "${INPUT}" >"${OUTPUT}" 7 | # doesn't convert quotes properly 8 | sed -i -e "s|\\\'|\'|g" "$2" 9 | -------------------------------------------------------------------------------- /.local/scripts/generic/photo-doc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # this copies some picture I just took on my phone from my Camera roll 3 | # to ~/shared/Shared 4 | 5 | STORAGE="${HOME}/storage/" 6 | IMAGE_DIR="${STORAGE}/dcim/Camera/" 7 | 8 | FILE="$(newest -ignore-hidden "${IMAGE_DIR}")" 9 | if [[ -z "$FILE" ]]; then 10 | echo "No new photos" 11 | exit 1 12 | fi 13 | 14 | printf '%s\nModified: %s ago\nMove? [Y|n] ' "$FILE" "$(file-modified-ago "$FILE")" 15 | 16 | read -r answer 17 | [[ "$answer" == [Nn]* ]] && exit 1 18 | to_folder="${HOME}/shared/Shared/photo-doc" 19 | mkdir -p "$to_folder" 20 | mv -vn "$FILE" "$to_folder" 21 | 22 | photos-unsync-recent 1 23 | -------------------------------------------------------------------------------- /.local/scripts/generic/photos-unsync-recent: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # sometimes after syncing a recent 3 | # photo with rsync, I want to delete 4 | # it instead. photos remain on my phone 5 | # for 28 days, so I delete photos from 6 | # the synced folder that are less than 7 | # 3 days old. 8 | 9 | from="$(backup_to phone_pictures)/Camera" || exit 1 10 | 11 | days='-3' 12 | [[ -n "$1" ]] && days="-$1" 13 | 14 | list-photos() { 15 | find "$from" -type f -mtime "$days" "$@" 16 | } 17 | 18 | list-photos >&2 19 | printf "delete %d synced files from the last %.1f days? (y/N) " "$(list-photos | wc -l)" "$(cut -c2- <<<"$days")" 20 | 21 | read -r answer 22 | [[ "$answer" == [yY]* ]] || exit 0 23 | 24 | echo "deleting..." >&2 25 | list-photos -print -delete >&2 26 | -------------------------------------------------------------------------------- /.local/scripts/generic/plainplay-m3u: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # https://github.com/purarue/plaintext-playlist 3 | # Create a m3u file for each file in my playlist 4 | 5 | set -u 6 | set -o pipefail 7 | 8 | TARGET_DIR="${1:?Provide a directory to put the m3u files into}" 9 | 10 | while read -r -d $'\0' playlist; do 11 | target="${TARGET_DIR}/$(replace-extension "$(basename "${playlist}")" m3u)" 12 | printf 'Creating %s\n' "${target}" >&2 13 | plainplay --abs m3u "${playlist}" >"${target}" 14 | done < <(find "${PLAINTEXT_PLAYLIST_PLAYLISTS}" -type f -name "*.txt" -print0) 15 | -------------------------------------------------------------------------------- /.local/scripts/generic/print-json: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # format and print colored json output 3 | JSON_FILE="${1:?No JSON file provided}" 4 | jq <"${JSON_FILE}" | highlight --out-format=ansi -S json || exit 1 5 | -------------------------------------------------------------------------------- /.local/scripts/generic/qr: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # converts a string to a qr code and displays it full screen 3 | # if no URL is passed as the first argument, reads from STDIN 4 | 5 | INPUT="${1:-$(cat)}" # if no URL was passed, read from STDIN 6 | TEMP="$(mktemp -p /tmp -d 'qr-XXXX')/img.png" # temporary dir 7 | 8 | qrencode "${INPUT}" -o "${TEMP}" || exit $? 9 | exec openurl "${TEMP}" 10 | -------------------------------------------------------------------------------- /.local/scripts/generic/remove-leading-spaces: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | Given some text that has leading spaces on each line, 5 | remove the leading spaces but keep everything aligned 6 | """ 7 | 8 | import sys 9 | import contextlib 10 | 11 | 12 | def leading_spaces(line: str) -> int: 13 | i = 0 14 | for char in line: 15 | if char.isspace(): 16 | i += 1 17 | else: 18 | break 19 | return i 20 | 21 | 22 | def main() -> None: 23 | lines = sys.stdin.readlines() 24 | if not lines: 25 | return 26 | min_spaces = min(leading_spaces(line) for line in lines if line.strip()) 27 | for line in lines: 28 | print(line[min_spaces:], end="") 29 | 30 | 31 | if __name__ == "__main__": 32 | with contextlib.suppress(KeyboardInterrupt): 33 | main() 34 | -------------------------------------------------------------------------------- /.local/scripts/generic/repos-dirty: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | # prints the absolute path of all git repos in the given directory that have uncommitted changes/untracked files 3 | 4 | in_dir="${1:-$REPOS}" 5 | if [[ -z "$in_dir" ]]; then 6 | echo "Usage: repos-dirty " 7 | exit 1 8 | fi 9 | list-git-dirs "$in_dir" | parallel -k -j+0 'cd {} && has-git-remote && git-has-untracked-or-changes && pwd' 10 | -------------------------------------------------------------------------------- /.local/scripts/generic/repos-pull-all: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | set -u 4 | 5 | cd "$REPOS" || return 1 6 | list-git-dirs "$REPOS" | parallel --line-buffered -j "$(nproc)" "cd {} && has-git-remote && { git pull; pwd }" 7 | -------------------------------------------------------------------------------- /.local/scripts/generic/rg-nvim: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # fzf all file contents recursively with rg, open the line 3 | # the user selects in my editor 4 | 5 | set -e 6 | set -o pipefail 7 | 8 | rg_lines() { 9 | PICKED_LINE="$(rg --no-heading --with-filename --line-number --color ansi "$*" | fzf --ansi)" || exit $? 10 | [[ -z "${PICKED_LINE}" ]] && return 1 11 | printf '%s\n' "${PICKED_LINE}" | cut -d':' -f'1-2' 12 | } 13 | 14 | declare -a RG_PARTS 15 | # split into filename and line number 16 | readarray -d ':' -t RG_PARTS < <(rg_lines "$@") 17 | [[ -z "${RG_PARTS[*]}" ]] && exit 1 18 | # arithmetic substitution removes extra newline from number 19 | exec editor "+$((RG_PARTS[1]))" "${RG_PARTS[0]}" 20 | -------------------------------------------------------------------------------- /.local/scripts/generic/rifleman-extract: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # fd | rifleman-extract 'black' # since we format python with black 3 | # prints all the python files that are in the directory (including 4 | # ones that have a shebang line) 5 | 6 | if [[ -z "$1" ]]; then 7 | echo "Usage: $(basename 0) " 8 | exit 1 9 | fi 10 | 11 | jq_str="$(printf 'to_entries[] | select(.key | startswith("%s")) | .value | .[]' "$1")" 12 | rifleman - -j | jq -r "$jq_str" 13 | -------------------------------------------------------------------------------- /.local/scripts/generic/server_clipboard_notify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o pipefail 4 | 5 | usage() { 6 | printf "Pass 'copy' or 'paste' as the first argument\n" >&2 7 | } 8 | 9 | main() { 10 | local tfile 11 | tfile="$(mktemp)" 12 | # shellcheck disable=SC2064 13 | trap "rm -vf '$tfile'" EXIT 14 | 15 | arg="$1" 16 | if [[ -z "$arg" ]]; then 17 | usage 18 | return 1 19 | fi 20 | case "$arg" in 21 | copy | paste) 22 | case "$arg" in 23 | copy) 24 | notify "Copying to server clipboard..." 25 | ;; 26 | paste) 27 | notify "Pasting from server clipboard..." 28 | ;; 29 | esac 30 | server_clipboard "$@" 2>"$tfile" 31 | resp="$(cat "$tfile")" 32 | [[ -n "$resp" ]] && notify "$resp" 33 | ;; 34 | *) 35 | echo "Unknown command: $arg" 36 | usage 37 | return 1 38 | ;; 39 | esac 40 | } 41 | 42 | main "$@" || exit $? 43 | -------------------------------------------------------------------------------- /.local/scripts/generic/show-pickle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | Reads a pickled (python) object from a file 5 | Accepts the file as the first argument 6 | """ 7 | 8 | import os 9 | import sys 10 | import pickle 11 | import pprint 12 | 13 | if len(sys.argv) < 2: 14 | print( 15 | "Error: Must provide a file to read a pickle from as the first argument.", 16 | file=sys.stderr, 17 | ) 18 | sys.exit(1) 19 | 20 | filepath = os.path.abspath(sys.argv[1]) 21 | with open(filepath, "rb") as picklef: 22 | data = pickle.load(picklef) 23 | 24 | pprint.pprint(data) 25 | -------------------------------------------------------------------------------- /.local/scripts/generic/sign-canvas: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | URL='https://github.com/szimek/signature_pad' 4 | CACHE_DIR="$HOME/.cache/signature_pad" 5 | 6 | [[ -d ~/.cache ]] || mkdir ~/.cache 7 | 8 | if [[ ! -d "$CACHE_DIR" ]]; then 9 | git clone "$URL" "$CACHE_DIR" || exit $? 10 | fi 11 | 12 | cd "$CACHE_DIR/docs" || { 13 | echo "Failed to cd to docs folder" 14 | exit 1 15 | } 16 | setsid -f sh -c 'sleep 1 && openurl localhost:5059' 17 | exec serve -p 5059 18 | -------------------------------------------------------------------------------- /.local/scripts/generic/spell-dotfiles: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | list-config-no-hist | 6 | grep -vE 'alacritty|system-config|lynx' | 7 | exists | tr '\n' '\0' | 8 | xargs -0 codespell-conf -I ~/.config/yadm/dotfiles_ignore_words.txt "$@" 9 | -------------------------------------------------------------------------------- /.local/scripts/generic/star: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # star or unstar a github repository 3 | # requires you to have githubs cli tool 'gh' setup 4 | 5 | set -e 6 | set -o pipefail 7 | 8 | # expects input like username/repo, or the full https URL 9 | repo="${1:?Provide repository or link to star/unstar}" 10 | method="${2:-PUT}" # provide 'DELETE' as second argument to unstar 11 | # get last two items from link 12 | full_name="$repo" 13 | # if this is an HTTPS, remove that so username/repo remains 14 | if [[ "$full_name" =~ https://github\.com ]]; then 15 | full_name="$(cut -d/ -f4- <<<"$repo")" 16 | fi 17 | set -x 18 | exec gh api --silent -X "${method}" "user/starred/${full_name}" 19 | -------------------------------------------------------------------------------- /.local/scripts/generic/status-code: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | exec curl -s -o /dev/null -w "%{http_code}\n" "${1:?Missing URL}" 3 | -------------------------------------------------------------------------------- /.local/scripts/generic/sub-rename: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # rename a subtitle file to match the video file so that 3 | # it automatically gets loaded by mpv/video player 4 | 5 | declare video subs 6 | 7 | video="$(gum file -c 'File >')" || exit $? 8 | subs="$(gum file -c 'Subs >')" || exit $? 9 | 10 | # rename the subtitle file to match the video file 11 | cp -v "$subs" "$(remove-extension "$video").srt" 12 | -------------------------------------------------------------------------------- /.local/scripts/generic/terminal-set-theme: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | if [[ "$TERM" = "xterm-kitty" ]]; then 3 | kitten themes --reload-in=all --config-file-name="${HOME}/.config/kitty/theme.conf" "${1:?Must provide theme as kwarg}" || exit $? 4 | fi 5 | printf '#!/usr/bin/env bash\nexport TERMINAL_THEME=%s\n' "$1" >~/.cache/terminal-theme.sh 6 | echo "$1" >~/.cache/terminal-theme 7 | -------------------------------------------------------------------------------- /.local/scripts/generic/timer-till: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # starts a timer which ends at a particular point in the future 3 | # e.g. timer-till 'today at 10pm' 4 | # I often use this with https://purarue.xyz/d/playping-loop?redirect, 5 | # as a sort of alarm/reminder to do something, like: 6 | # timer-till 'today at 4pm' && playping-loop 7 | 8 | declare at now 9 | now="$(epoch)" 10 | at="$(dateq parse -Fepoch "today at $*")" || return $? 11 | [[ -z "$at" ]] && exit 1 12 | 13 | if [[ "$at" -le "$now" ]]; then 14 | echo "Time must be in the future, parsed $(dateq parse -Ftime "$at"), now is $(dateq parse -Ftime "$now")" >&2 15 | exit 1 16 | fi 17 | 18 | exec timer -f "$((at - now))s" 19 | -------------------------------------------------------------------------------- /.local/scripts/generic/tmux-kill-detached: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | tmux list-sessions | grep -E -v '\(attached\)$' | while IFS=$'\n' read -r line; do 3 | echo "Killing ${line}" 4 | tmux kill-session -t "${line%%:*}" 5 | done 6 | -------------------------------------------------------------------------------- /.local/scripts/generic/to-github: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # initializes a github repository 3 | # assumes this is a git repository and has a commit 4 | # 5 | # This uses hub instead of gh since it handles the 6 | # 'current directory' initialization nicely 7 | 8 | in-gitdir || { 9 | echo "Not currently in a git repository" >&2 10 | exit 1 11 | } 12 | hub create "$@" 13 | exec git push --set-upstream origin master 14 | -------------------------------------------------------------------------------- /.local/scripts/generic/to-gitlab: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # initializes a gitlab repository 3 | # assumes this is a git repository and has a commit 4 | in-gitdir || { 5 | echo "Not currently in a git repository" >&2 6 | exit 1 7 | } 8 | git remote add origin "git@gitlab.com:purarue/$(basename "$(pwd)").git" 9 | exec git push --set-upstream origin master 10 | -------------------------------------------------------------------------------- /.local/scripts/generic/to-json-objects: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import json 5 | import contextlib 6 | 7 | import click 8 | 9 | 10 | @click.command() 11 | @click.option( 12 | "-k", "--key", help="key to embed into each object", type=str, required=True 13 | ) 14 | def main(key: str) -> None: 15 | """ 16 | pipe some lines into this, creates JSON objects with --key. use like: 17 | 18 | seq 10 | to-json-objects -k "number" | jq '. + {"data": "something"}' 19 | 20 | to create a stream of JSON objects 21 | """ 22 | for line in map(str.rstrip, sys.stdin): 23 | sys.stdout.write(json.dumps({key: line})) 24 | sys.stdout.write("\n") 25 | 26 | sys.stdout.flush() 27 | 28 | 29 | if __name__ == "__main__": 30 | with contextlib.suppress(KeyboardInterrupt): 31 | main() 32 | -------------------------------------------------------------------------------- /.local/scripts/generic/todos: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | maybe_boxes() { 5 | if havecmd boxes; then 6 | boxes -pv1h1 -dshell 7 | else 8 | cat 9 | fi 10 | } 11 | 12 | chomp <"$XDG_DOCUMENTS_DIR/.todo_names.txt" | while read -r name; do 13 | maybe_boxes <<<"${name/_/ }" 14 | "$name" list 15 | done 16 | -------------------------------------------------------------------------------- /.local/scripts/generic/treesitter-not-ensured: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | set -o pipefail 4 | # prints any treesitter parsers that are not in ensure_installed in my config, in-case I want to add them to my configuration 5 | comm -23 <(fd -I '.so' ~/.local/share/nvim/lazy/nvim-treesitter/parser/ -x echo '{/.}' | sort) <(awk '/^.*ensure_installed/,/\}/' <~/.config/nvim/lua/plugins/treesitter.lua | sed -e '1d' -e '$d' | tr -d '", ' | sort) | grep -vx rifleconfig 6 | -------------------------------------------------------------------------------- /.local/scripts/generic/ttt: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # vendorized from https://github.com/purarue/ttt, 3 | # so that I'm not missing it when Im installing stuff on 4 | # my computer 5 | tttlog "$@" 6 | exec "$@" 7 | -------------------------------------------------------------------------------- /.local/scripts/generic/tttlist: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This prints directories that appear a lot in my ttt history, 3 | # used in https://purarue.xyz/d/cd.zsh?dark to cd to one 4 | # Requires: 5 | # my ttt HPI module (https://github.com/purarue/HPI) 6 | # https://github.com/purarue/exists 7 | # https://github.com/purarue/chomp 8 | 9 | set -e 10 | set -o pipefail 11 | 12 | hpi query my.ttt.history -s | jq -r '.directory' | grep -vx ~ | sort | uniq -c | chomp | sort -nr | cut -d' ' -f2- | exists 13 | -------------------------------------------------------------------------------- /.local/scripts/generic/unstarred-nvim-plugins: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # to list my currently unstarred nvim plugins 3 | # to star all of these: 4 | # unstarred-nvim-plugins | cut -d'/' -f4- | grep -v purarue | parallel -j1 -k 'star {}' 5 | # uses the 'star' script in this directory which uses 'gh' internally 6 | 7 | lazy-plugins() { 8 | list-git-dirs "${HOME}/.local/share/nvim/lazy" -d 2 | parallel -j+0 'cd {}; giturl' | sed -e 's/.git$//' | sort 9 | } 10 | 11 | already-starred() { 12 | mystars -3 | jq -r '.items | .[].arg' | sort 13 | } 14 | 15 | comm -23 <(lazy-plugins) <(already-starred) 16 | -------------------------------------------------------------------------------- /.local/scripts/generic/update-my-stars: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | wait-for-internet --timeout 1 || { 4 | echo 'No internet connection, skipping update of my github stars...' >&2 5 | exit 0 6 | } 7 | 8 | update_stars() { 9 | mystars "$@" -c=never | tee -a "${TMPDIR:-/tmp}"/mystars_update.log 2>&1 10 | } 11 | 12 | case "$1" in 13 | -f) 14 | rm "$(evry location -update_my_stars)" 15 | ;; 16 | *) ;; 17 | esac 18 | 19 | evry 6 hours -update_my_stars && { 20 | echo 'Updating my github stars...' >&2 21 | update_stars -u 22 | } 23 | 24 | evry 1 month -re_update_my_stars && { 25 | echo 'Reindexing my github stars...' >&2 26 | update_stars -r 27 | } 28 | -------------------------------------------------------------------------------- /.local/scripts/generic/urlhandler: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # receives text from STDIN, extracts unique URLs 3 | # prompts me to pick one and opens it 4 | 5 | # --urlextract is used in tmux, urlscan is the default 6 | # (used for things like opening URLs in neomutt) 7 | if [ "$1" = '--urlextract' ]; then 8 | urls="$(extracturls)" || exit $? 9 | else 10 | urls="$(urlscan -n)" 11 | fi 12 | 13 | if [ -z "${urls}" ]; then 14 | notify "No URLs found" 15 | exit 1 16 | fi 17 | 18 | chosen_url="$urls" 19 | [ "$(echo "$urls" | wc -l)" = "1" ] || chosen_url="$(echo "${urls}" | picker -p 'Pick a URL to open > ')" 20 | if [ -n "${chosen_url}" ]; then 21 | echo "${chosen_url}" | clipcopy 22 | openurl "${chosen_url}" 23 | fi 24 | -------------------------------------------------------------------------------- /.local/scripts/generic/urlview: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | if CONTENTS="$(clippaste)"; then 3 | # make sure this looks like text, and there wasn't an image on my clipboard 4 | if iconv --from-code="utf-8" --to-code="utf-8" <(printf '%s' "$CONTENTS") >/dev/null 2>&1; then 5 | openurl "$CONTENTS" || { 6 | notify -u critical "Couldn't open url: $CONTENTS" 7 | } 8 | else 9 | notify -u critical "Clipboard contents don't look like text, ignoring..." 10 | fi 11 | else 12 | notify -u critical "Couldn't get clipboard contents" 13 | fi 14 | -------------------------------------------------------------------------------- /.local/scripts/generic/vitamin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # add my vitamins to my food tracker 3 | # https://github.com/purarue/ttally 4 | 5 | set -eu 6 | set -o pipefail 7 | 8 | tf="$(mktemp)" 9 | trap 'rm -f "$tf"' EXIT 10 | 11 | add_to_food() { 12 | local SOURCE_FILE="$HPIDATA/vitamin.json" || return $? 13 | if [[ ! -e "$SOURCE_FILE" ]]; then 14 | printf 'Source file %s does not exist\n' "$SOURCE_FILE" >&2 15 | return 1 16 | fi 17 | jq --arg TIMESTAMP "$(epoch)" '[.[] + {"when": $TIMESTAMP | tonumber}]' <"$HPIDATA/vitamin.json" | 18 | tee "$tf" | jq '.[] | .food' -r | surround "'" | prefix 'added ' || return $? 19 | python3 -m ttally from-json food -f "${tf}" || return $? 20 | } 21 | 22 | add_to_food || exit $? 23 | -------------------------------------------------------------------------------- /.local/scripts/generic/water-should-drink: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | set -o pipefail 4 | 5 | compute-target() { 6 | # should drink 14.8 ML per pound of weight -- prints how much water I should drink each day 7 | CURRENT_WEIGHT="$(hpi query ttally.__main__.weight --order-key when --limit 1 --reverse -s | jq .pounds)" 8 | MULTIPLIER=1.25 # arbitrary, to account for water in food; just a higher target for myself 9 | perl -E "say int($MULTIPLIER * 14.8 * ${CURRENT_WEIGHT})" 10 | } 11 | 12 | CACHE_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/water-should-drink" 13 | 14 | evry 1d -compute-water-should-drink && compute-target >"$CACHE_FILE" 15 | cat "$CACHE_FILE" 16 | -------------------------------------------------------------------------------- /.local/scripts/generic/wca-comps: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # a cached version of wca-upcoming-competitions to make sure 3 | # I only hit worldcubeassosiation once a week 4 | 5 | CACHE_FILE="$HOME/.cache/wca-comps" 6 | # make sure script works (no imports fail) 7 | evry 1 week -wcacomps && wait-for-internet --quiet --timeout 5 && wca-upcoming-competitions >"${CACHE_FILE}" 8 | 9 | # if we dont have internet and the cachefile exists, just print the old result 10 | if [[ -e "$CACHE_FILE" ]]; then 11 | cat <"${CACHE_FILE}" 12 | else 13 | echo 'wca-comps: No internet, and no cached result' >&2 14 | exit 1 15 | fi 16 | -------------------------------------------------------------------------------- /.local/scripts/generic/wca-upcoming-competitions: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # fetches all the upcoming wca competitions 3 | current_date="$(date +%Y-%m-%d)" 4 | pagination_size='' 5 | page=1 6 | while true; do 7 | data="$(curl -sL "https://www.worldcubeassociation.org/api/v0/competition_index?include_cancelled=false&sort=start_date%2Cend_date%2Cname&ongoing_and_future=$current_date&page=$page")" 8 | count=$(echo "$data" | jq 'length') 9 | jq '.[]' <<<"$data" 10 | if [[ -z "$pagination_size" ]]; then 11 | pagination_size="$count" 12 | else 13 | # if we hit something without the default pagination size, then were done 14 | if [[ "$count" != "$pagination_size" ]]; then 15 | break 16 | fi 17 | fi 18 | ((page++)) 19 | done 20 | -------------------------------------------------------------------------------- /.local/scripts/generic/windows-ppas: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | sudo add-apt-repository ppa:neovim-ppa/unstable 3 | sudo apt update 4 | sudo apt install neovim 5 | -------------------------------------------------------------------------------- /.local/scripts/generic/with-secrets: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | 3 | source ~/.profile 2>/dev/null 4 | source ~/.config/zsh/.zshrc 2>/dev/null 5 | 6 | if [[ -z "$1" ]]; then 7 | echo "Usage: "$(basename "$0")" " >&2 8 | else 9 | exec "$@" 10 | fi 11 | -------------------------------------------------------------------------------- /.local/scripts/generic/youtube-thumbnail: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # preview a youtube thumbnail fullscreen 3 | YOUTUBE_URL="${1:?Provide Youtube URL as the first argument}" 4 | IMAGE_URL="$(curl -s "${YOUTUBE_URL}" | pup 'link[itemprop="thumbnailUrl"] attr{href}' | head -n 1)" || { 5 | printf "Couldn't download %s\n" "${YOUTUBE_URL}" 6 | exit 1 7 | } 8 | 9 | # https://purarue.xyz/d/urlpicpreview?dark 10 | exec urlpicpreview "${IMAGE_URL}" 11 | -------------------------------------------------------------------------------- /.local/scripts/generic/youtube-user-id: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Gets the youtube ID for a user from a link 3 | # Could be a link to their channel or a video 4 | # Searches the tags for a channelId value 5 | 6 | yt-dlp --print channel_url --playlist-items 1 "${1:?Pass the URL as the first argument}" | awk -F/ '{print $NF}' 7 | -------------------------------------------------------------------------------- /.local/scripts/generic/youtube-user-rss-feed: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # users the youtube-user-id script to get the channel ID, and print the corresponding youtube RSS feed and name 3 | # this is the RSS format expected by newsraft 4 | data="$(yt-dlp --print channel_url --print channel --playlist-items 1 "${1?Provide a youtube url}")" 5 | channel_id="$(awk -F'/' 'NR == 1 {print $NF}' <<<"$data")" 6 | name="$(tail -n1 <<<"$data")" 7 | [[ -z "$channel_id" ]] && exit 8 | printf 'https://www.youtube.com/feeds/videos.xml?channel_id=%s "%s"\n' "${channel_id}" "${name}" 9 | -------------------------------------------------------------------------------- /.local/scripts/linux/afk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | pkill udiskie 3 | figlet afk 4 | lock-screen 5 | if gum confirm "re-enable disk automounting?"; then 6 | i3-msg exec 'udiskie -t' >/dev/null 7 | fi 8 | -------------------------------------------------------------------------------- /.local/scripts/linux/battery: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | printf '%s %d%%\n' "$(cat /sys/class/power_supply/*/status)" "$(cat /sys/class/power_supply/*/capacity)" 3 | -------------------------------------------------------------------------------- /.local/scripts/linux/brightness: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # call like: 3 | # brightness up 5 4 | # brightness down 10 5 | 6 | CMD="${1:?No argument provided (up/down)}" 7 | STEP="${2:-5}" # default to 5% 8 | 9 | case "${CMD}" in 10 | up) 11 | brightnessctl set "${STEP}%+" 12 | ;; 13 | down) 14 | brightnessctl set "${STEP}%-" 15 | ;; 16 | esac 17 | -------------------------------------------------------------------------------- /.local/scripts/linux/colorize_number: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # if a number is 0, leaves it as is 3 | # colors a number to make it more noticeable 4 | # used in my i3blocks scripts 5 | # https://github.com/vivien/i3blocks 6 | 7 | NUM="${1:-$(chomp | tr -d "\n")}" 8 | 9 | if [ "${NUM}" = '0' ]; then 10 | printf '0\n' 11 | else 12 | printf "%s\n" "${NUM}" 13 | fi 14 | -------------------------------------------------------------------------------- /.local/scripts/linux/cstimer-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # https://github.com/purarue/cstimer-save-server 3 | 4 | main() { 5 | save_to="$(backup_to "cubing/cstimer")" || return $? 6 | secret="$(cat "${HPIDATA}/cstimer_secret.txt")" || return $? 7 | export CSTIMER_SECRET="$secret" 8 | exec cstimer-save-server -save-to "$save_to" -timestamped 9 | } 10 | 11 | main || exit $? 12 | -------------------------------------------------------------------------------- /.local/scripts/linux/flashlight: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # i.e. I fullscreen the nsxiv (image viewer) instance 3 | # to turn my laptop into a flashlight 4 | 5 | # switch to a newly created 'flashlight' workspace 6 | i3-msg workspace flashlight >/dev/null 2>&1 7 | 8 | # set brightness to 100 9 | light -S 100 10 | 11 | # create a 1x1 white pixel image 12 | FILE=/tmp/flashlight.png 13 | magick -size 1x1 xc:white "${FILE}" 14 | 15 | # and display it 16 | exec nsxiv "${FILE}" 17 | -------------------------------------------------------------------------------- /.local/scripts/linux/flatpak-run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # launches a flatpak application by letting me pick one with rofi 3 | 4 | set -o pipefail 5 | 6 | main() { 7 | local chosen 8 | # https://purarue.xyz/d/picker?dark 9 | chosen="$(flatpak list --columns=application | picker)" 10 | [[ -z "$chosen" ]] && return 1 11 | setsid -f flatpak run "${chosen}" >/dev/null 2>&1 12 | } 13 | 14 | main || exit $? 15 | -------------------------------------------------------------------------------- /.local/scripts/linux/focused-screen-resolution: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # uses focused-screen-index to get the currently 3 | # focused monitor, and prints the resolution 4 | # using xrandr 5 | 6 | declare screen_index 7 | screen_index="$(focused-screen-index)" || exit $? 8 | xrandr | grep -w connected | sed -e "$((screen_index + 1))q;d" | grep -oP "(\d+x\d+)" 9 | -------------------------------------------------------------------------------- /.local/scripts/linux/gammastep-loc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o pipefail 4 | 5 | main() { 6 | declare loc 7 | declare -a args=() 8 | # https://github.com/purarue/HPI-personal/blob/master/scripts/last-gps-location 9 | loc="$(last-gps-location -d ":" --fuzz 2.0 --precision 0)" 10 | if [[ -n "$loc" ]]; then 11 | args+=(-l "$loc") 12 | fi 13 | exec gammastep -t 6500:4000 "${args[@]}" "$@" 14 | } 15 | 16 | main "$@" || exit $? 17 | -------------------------------------------------------------------------------- /.local/scripts/linux/gpg_autoclick: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # automatically click the 'save in password manager' and 'ok' buttons for the gpg dialog 3 | # see ~/.local/share/gpg_autoclick 4 | 5 | from pathlib import Path 6 | import pyautogui 7 | 8 | datadir = Path("~/.local/share/gpg_autoclick").expanduser() 9 | 10 | 11 | def locate_and_click(p: Path) -> None: 12 | assert p.exists(), f"{p} doesn't exist!" 13 | locations = list(pyautogui.locateAllOnScreen(str(p))) 14 | assert len(locations) > 0, f"Couldn't find {p}" 15 | pyautogui.click(locations[0]) 16 | 17 | 18 | def main() -> None: 19 | locate_and_click(datadir / "tick_box.png") 20 | locate_and_click(datadir / "ok.png") 21 | 22 | 23 | if __name__ == "__main__": 24 | main() 25 | -------------------------------------------------------------------------------- /.local/scripts/linux/housekeeping-info: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | housekeeping 7 | housekeeping 8 | EVRY_JSON=1 housekeeping | describe-evry-json 9 | -------------------------------------------------------------------------------- /.local/scripts/linux/housekeeping-offline: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | if wait-for-internet --timeout 5 --text 'Running housekeeping...'; then 7 | housekeeping-info 8 | else 9 | echo 'Offline, exiting...' >&2 10 | exit 1 11 | fi 12 | -------------------------------------------------------------------------------- /.local/scripts/linux/hy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This is the script that I run when I start my arch system 3 | # 4 | # This is called from the terminal right after I login 5 | # I do not have a login greeter, I launch directly 6 | # into the arch cmdline 7 | 8 | source ~/.profile 9 | exec Hyprland 10 | -------------------------------------------------------------------------------- /.local/scripts/linux/i3-is-floating-window: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # exit code 0 if the window is floating, 1 if its tiling 3 | # accepts a window ID as the first argument, else 4 | # uses the currently focused window 5 | # requires xprop 6 | 7 | if [[ -z "$1" ]]; then 8 | WINDOW_ID="$(xprop -root _NET_ACTIVE_WINDOW | awk '{print $NF}')" 9 | else 10 | WINDOW_ID="$1" 11 | fi 12 | 13 | xprop -id "${WINDOW_ID}" | grep -q "I3_FLOATING_WINDOW" || exit $? 14 | -------------------------------------------------------------------------------- /.local/scripts/linux/i3-resize: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # From: https://github.com/LukeSmithxyz/voidrice/blob/archi3/.local/bin/i3cmds/i3resize 3 | 4 | [ -z "$1" ] && echo "No direction provided" && exit 1 5 | distanceStr="15 px or 5 ppt" 6 | 7 | moveChoice() { 8 | i3-msg resize "$1" "$2" "${distanceStr}" | grep '"success":true' || 9 | i3-msg resize "$3" "$4" "${distanceStr}" 10 | } 11 | 12 | case "$1" in 13 | up) 14 | moveChoice grow up shrink down 15 | ;; 16 | down) 17 | moveChoice shrink up grow down 18 | ;; 19 | left) 20 | moveChoice shrink right grow left 21 | ;; 22 | right) 23 | moveChoice grow right shrink left 24 | ;; 25 | esac 26 | -------------------------------------------------------------------------------- /.local/scripts/linux/i3-sticky: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # i3-sticky [enable|disable] 3 | # if no argument is provided, toggles sticky 4 | 5 | enable_sticky() { 6 | i3-msg "floating enable; sticky enable" 7 | } 8 | 9 | disable_sticky() { 10 | i3-msg "floating disable; sticky disable" 11 | } 12 | 13 | case "$1" in 14 | enable) 15 | enable_sticky 16 | ;; 17 | disable) 18 | disable_sticky 19 | ;; 20 | *) 21 | if i3-is-floating-window; then 22 | disable_sticky 23 | else 24 | enable_sticky 25 | fi 26 | ;; 27 | esac 28 | -------------------------------------------------------------------------------- /.local/scripts/linux/i3blocks-parse-signals: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -o pipefail 3 | awk '/^\[|signal/,//' ~/.config/i3blocks/config | sed -e 's_\[_\["_; s_\]_"\]_;' | tq | jq 'to_entries | .[] | select(.value.signal) | "\(.key) \(.value.signal)"' -r 4 | -------------------------------------------------------------------------------- /.local/scripts/linux/i3blocks-refresh-all: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # grep the i3blocks config file for signals 3 | # which can be refreshed, and refresh them 4 | 5 | set -x 6 | 7 | # remove some cache files which impact block functionality 8 | rm -f "${HOME}/.cache/mailsync_warn" 9 | rm -f "$(evry location -guestbook_comments)" 10 | 11 | grep '^signal' "${HOME}/.config/i3blocks/config" | cut -d'=' -f2 | while read -r signal; do 12 | pkill -RTMIN+"${signal}" i3blocks & 13 | done 14 | 15 | wait 16 | 17 | [[ -z "$QUIET" ]] && { 18 | attached-to-terminal || notify 'Refreshed all blocks' 19 | } 20 | -------------------------------------------------------------------------------- /.local/scripts/linux/i3blocks-refresh-mpv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | i3blocks-refresh-mk mpv-paused & 3 | i3blocks-refresh-mk mpv-song & 4 | wait 5 | -------------------------------------------------------------------------------- /.local/scripts/linux/i3blocks-watch-mpv-daemon-logs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | touch /tmp/mpv-history-daemon.log 7 | 8 | # read the logfile which https://github.com/purarue/mpv-history-daemon 9 | # writes to, filtering to lines which specify song has ended/started 10 | # 11 | # when that happens, refresh my i3blocks 12 | 13 | tail -n 1 -f /tmp/mpv-history-daemon.log | 14 | grep --line-buffered -e 'eof|' -e 'playlist-pos|[[:digit:]]' | 15 | while read -r; do i3blocks-refresh-mpv; done 16 | -------------------------------------------------------------------------------- /.local/scripts/linux/image-working-dir: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # just a script that moves an image to 3 | # my downloads folder so I can work on it 4 | # 5 | # this is bound in ranger (my file manager) 6 | 7 | to_dir="$XDG_DOWNLOAD_DIR/images" 8 | mkdir -p "$to_dir" 9 | 10 | exec cp -p "$1" "$to_dir" 11 | -------------------------------------------------------------------------------- /.local/scripts/linux/launch-waybar: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CONFIG_FILES="$HOME/.config/waybar/config.jsonc $HOME/.config/waybar/style.css" 4 | 5 | trap "killall waybar" EXIT 6 | 7 | sleep 1 8 | while true; do 9 | waybar & 10 | inotifywait -e create,modify $CONFIG_FILES 11 | killall waybar 12 | done 13 | -------------------------------------------------------------------------------- /.local/scripts/linux/main-screen-resolution: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # gets the first screen from xrandr and prints 3 | # the resolution. I use this sometimes instead 4 | # of the focused-screen-resolution because it 5 | # gets very complicated determine pixel location 6 | # based on monitor output. xwininfo/xdotool return 7 | # pixel info by adding pixel widths of previous screens, 8 | # so scripts like i3-picture-in-picture just use 9 | # the main monitor instead of trying to figure out 10 | # where to place windows 11 | 12 | xrandr | grep -w connected | head -n 1 | grep -oP "(\d+x\d+)" 13 | -------------------------------------------------------------------------------- /.local/scripts/linux/mpv-last-screenshot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # copy the latest mpv screenshot to clipboard 3 | 4 | path="$(mpv-currently-playing | tail -n 1)" || exit $? 5 | dir="$(dirname "$path")" || exit $? 6 | if [[ ! -d "$dir" ]]; then 7 | printf 'error: %s is not a directory\n' "$dir" >&2 8 | exit 1 9 | fi 10 | exec newest "$dir" 11 | -------------------------------------------------------------------------------- /.local/scripts/linux/notify-mpv-song-description: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if desc="$(mpv-song-description-py)"; then 4 | notify-send "$desc" 5 | else 6 | notify-send 'nothing playing''' 7 | fi 8 | -------------------------------------------------------------------------------- /.local/scripts/linux/randomize-wallpaper: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | if [[ -n "${WAYLAND_DISPLAY:-}" ]]; then 3 | random_wallpaper="$(find "$FILES_DIR/wallpapers" -type f | shuf -n 1)" 4 | oldid="$(pgrep swaybg)" 5 | setsid -f swaybg -i "$random_wallpaper" -m fill 6 | kill "$oldid" 7 | else 8 | # Randomize the wallpaper using feh 9 | exec feh --randomize --bg-fill --no-fehbg "${FILES_DIR}/wallpapers" 10 | fi 11 | -------------------------------------------------------------------------------- /.local/scripts/linux/redshift-loc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o pipefail 4 | 5 | main() { 6 | declare loc 7 | declare -a args=() 8 | # https://github.com/purarue/HPI-personal/blob/master/scripts/last-gps-location 9 | loc="$(last-gps-location -d ":" --fuzz 2.0)" 10 | if [[ -n "$loc" ]]; then 11 | args+=(-l "$loc") 12 | fi 13 | exec redshift -t 6500:4000 "${args[@]}" "$@" 14 | } 15 | 16 | main "$@" || exit $? 17 | -------------------------------------------------------------------------------- /.local/scripts/linux/refresh-block: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | BLOCK="${1?Block name required}" 3 | 4 | if pgrep -x i3blocks >/dev/null; then 5 | i3blocks-refresh-mk "$BLOCK" 6 | elif pgrep -x waybar >/dev/null; then 7 | waybar-refresh-block "$BLOCK" 8 | fi 9 | -------------------------------------------------------------------------------- /.local/scripts/linux/sonic-pi-run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # wrapper script to handle sonic-pi on arch with pulseaudio 3 | # see https://purarue.xyz/x/devlog/sonic_pi/ 4 | # for an explanation 5 | 6 | jackd -R -d alsa -d hw:1 & 7 | qjackctl & 8 | sleep 5 9 | sonic-pi # block 10 | 11 | # shellcheck disable=SC2046 12 | kill -15 $(jobs -p) 13 | -------------------------------------------------------------------------------- /.local/scripts/linux/sw: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This is the script that I run when I start my arch system 3 | # 4 | # This is called from the terminal right after I login 5 | # I do not have a login greeter, I launch directly 6 | # into the arch cmdline 7 | 8 | # shellcheck source=/dev/null 9 | source ~/.profile 10 | exec sway 11 | -------------------------------------------------------------------------------- /.local/scripts/linux/sway-display-off: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | swayidle \ 3 | timeout 1 'swaymsg "output * dpms off"' \ 4 | resume 'swaymsg "output * dpms on"' & 5 | swaylock -c000000 6 | kill %% 7 | -------------------------------------------------------------------------------- /.local/scripts/linux/sway-resize: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # From: https://github.com/LukeSmithxyz/voidrice/blob/archi3/.local/bin/i3cmds/i3resize 3 | 4 | [ -z "$1" ] && echo "No direction provided" && exit 1 5 | distanceStr="15 px or 5 ppt" 6 | 7 | moveChoice() { 8 | swaymsg resize "$1" "$2" "${distanceStr}" | grep '"success":true' || 9 | swaymsg resize "$3" "$4" "${distanceStr}" 10 | } 11 | 12 | case "$1" in 13 | up) 14 | moveChoice grow up shrink down 15 | ;; 16 | down) 17 | moveChoice shrink up grow down 18 | ;; 19 | left) 20 | moveChoice shrink right grow left 21 | ;; 22 | right) 23 | moveChoice grow right shrink left 24 | ;; 25 | esac 26 | -------------------------------------------------------------------------------- /.local/scripts/linux/termcolors: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | for i in {0..255}; do 3 | # shellcheck disable=SC2059 4 | printf "\x1b[38;5;${i}mcolour${i}\n" 5 | done 6 | -------------------------------------------------------------------------------- /.local/scripts/linux/tiktok-update-rss-feeds: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | contents="$(cat "$HOME/.config/newsraft/feeds")" 4 | usernames="$(cat "$XDG_DOCUMENTS_DIR/tiktok.txt")" 5 | 6 | while read -r line; do 7 | if grep -q "rss/${line}.xml " <<<"$contents"; then 8 | echo "Skipping @$line, already present" >&2 9 | else 10 | echo "Adding @$line" >&2 11 | file="${HOME}/.cache/tiktok-local-rss/rss/${line}.xml" 12 | if [[ ! -f "$file" ]]; then 13 | echo "While adding $line, $file not found" >&2 14 | continue 15 | fi 16 | printf 'file://%s "%s"\n' "$file" "$line" >>"$HOME/.config/newsraft/feeds" 17 | fi 18 | done <<<"$usernames" 19 | -------------------------------------------------------------------------------- /.local/scripts/linux/timedatectl-timezone: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | main() { 7 | local tz 8 | tz="$(timedatectl | grep 'Time zone' | cut -d':' -f2- | awk '{print $1}')" 9 | [[ -z "$tz" ]] && { 10 | echo 'Failed to get timezone from timedatectl' >&2 11 | return 1 12 | } 13 | printf '%s\n' "$tz" 14 | } 15 | 16 | main || exit $? 17 | -------------------------------------------------------------------------------- /.local/scripts/linux/timezone-has-changed: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o pipefail 4 | 5 | main() { 6 | local geotz curtz 7 | flock ~/.local/tz-lock with-secrets hpi doctor -S my.time.tz.via_location 2>/dev/null 8 | geotz="$(current-timezone)" || return $? 9 | curtz="$(timedatectl-timezone)" || return $? 10 | if [[ "${geotz}" != "${curtz}" ]]; then 11 | printf 'Set timezone %s and current timezone %s do not match!\n' "${curtz}" "${geotz}" >&2 12 | return 0 13 | else 14 | printf 'System and Geolocated timezones match: %s\n' "${curtz}" >&2 15 | fi 16 | return 1 17 | } 18 | 19 | main || exit $? 20 | -------------------------------------------------------------------------------- /.local/scripts/linux/transparent: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # enable/disable transparency for the currently moused over application 3 | # Usage: 4 | # transparent [target] 5 | # optionally, specify target to change the moues into a target -- the next click will target that application 6 | # target exists because some applications can't be 'moused over' (e.g. mpv) 7 | 8 | if [ "$1" = "enable" ]; then 9 | if [ "$2" = "target" ]; then 10 | picom-trans -s 85 11 | else 12 | picom-trans -c 85 13 | fi 14 | elif [ "$1" = "disable" ]; then 15 | if [ "$2" = "target" ]; then 16 | picom-trans -s 100 17 | else 18 | picom-trans -c 100 19 | fi 20 | else 21 | printf "You must specify either enable or disable\n" 1>&2 22 | fi 23 | -------------------------------------------------------------------------------- /.local/scripts/linux/update-rss: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # updates my rss feed, if I don't already have it open 3 | # If newsraft is not open, this reloads all items and 4 | # saves how many items are unread to ~/.cache/rss-unread 5 | # If it fails, does not write 6 | 7 | readonly CACHE_FILE="${XDG_CACHE_HOME:-${HOME}/.cache}/rss-unread" 8 | 9 | if pgrep -x newsraft >/dev/null; then 10 | echo "Newsraft is active, skipping update..." >&2 11 | exit 1 12 | else 13 | newsraft -e reload-all >/dev/null 14 | unread="$(newsraft -e print-unread-items-count)" || exit $? 15 | if [[ -z "$unread" ]]; then 16 | echo '0' >"${CACHE_FILE}" 17 | else 18 | # delete a space followed by anything 19 | echo "${unread%% *}" >"${CACHE_FILE}" 20 | fi 21 | fi 22 | -------------------------------------------------------------------------------- /.local/scripts/linux/volume: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # volume [volume_step] 3 | 4 | CMD="${1:?No command provided. Provide one of: up|down|mute|micmute}" 5 | VOLUME_STEP="${2:-5}" 6 | 7 | case "${CMD}" in 8 | up) 9 | pactl set-sink-volume @DEFAULT_SINK@ +"$VOLUME_STEP"% 10 | ;; 11 | down) 12 | pactl set-sink-volume @DEFAULT_SINK@ -"$VOLUME_STEP"% 13 | ;; 14 | mute) 15 | pactl set-sink-mute @DEFAULT_SINK@ toggle 16 | ;; 17 | micmute) 18 | pactl set-source-mute @DEFAULT_SOURCE@ toggle 19 | ;; 20 | *) 21 | echo "Unknown command: ${CMD}" 1>&2 22 | exit 1 23 | ;; 24 | esac 25 | -------------------------------------------------------------------------------- /.local/scripts/linux/waybar-refresh-all: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | waybar-signals | cut -d'=' -f2 | while read -r signal; do 4 | pkill "-RTMIN+${signal}" waybar & 5 | done 6 | wait 7 | [[ "$1" == "no-notify" ]] || notify "Refreshed all blocks" 8 | -------------------------------------------------------------------------------- /.local/scripts/linux/waybar-refresh-block: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | chosen="${1?Usage: $0 }" 3 | signal="$(waybar-signals | grep -m1 "$chosen")" 4 | if [[ -z "$signal" ]]; then 5 | echo "Could not find signal for query: $chosen" >&2 6 | printf "Known signals:\n%s\n" "$(waybar-signals)" >&2 7 | exit 1 8 | fi 9 | 10 | # split by '=' into name and value 11 | readarray -d= -t parts < <(printf '%s' "$signal") 12 | name="${parts[0]}" 13 | signal="${parts[1]}" 14 | 15 | pkill -RTMIN+"$signal" waybar 16 | printf "Refreshed %s (%d)\n" "$name" "$signal" >&2 17 | -------------------------------------------------------------------------------- /.local/scripts/linux/waybar-signals: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | from jsonc_parser.parser import JsoncParser 5 | 6 | 7 | def main() -> None: 8 | config_dir = os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")) 9 | config_file = os.path.join(config_dir, "waybar/config.jsonc") 10 | data = JsoncParser.parse_file(config_file) 11 | for k, v in data.items(): 12 | if not isinstance(v, dict): 13 | continue 14 | if "signal" in v: 15 | print(f"{k}={v['signal']}") 16 | 17 | 18 | if __name__ == "__main__": 19 | main() 20 | -------------------------------------------------------------------------------- /.local/scripts/linux/webcam-pic: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # open mpv to save a picture (using webcam) in ~/Pictures/pics 3 | 4 | declare pics 5 | pics="${XDG_PICTURES_DIR:?Pictures environment variable not set}/pics" 6 | [[ ! -d "${pics}" ]] && mkdir -p "${pics}" 7 | cd "${pics}" || exit 1 8 | # open mpv so I can take a picture 9 | mpv /dev/video0 10 | exec launch ranger "${pics}" 11 | -------------------------------------------------------------------------------- /.local/scripts/linux/xmodmap-reset: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ux 4 | 5 | exec setxkbmap -layout us 6 | -------------------------------------------------------------------------------- /.local/scripts/notes_rendered/cache-srt-to-text: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | INPUT="${1:?Give .srt file as input}" 4 | TARGET="${2:?Give .txt file as target}" 5 | 6 | # if SRT file modification time is newer than target file, then we need to re-convert 7 | CONVERT=0 8 | if [[ ! -e "$TARGET" ]]; then 9 | CONVERT=1 10 | elif (($(stat -c %Y "$INPUT") > $(stat -c %Y "$TARGET"))); then 11 | CONVERT=1 12 | fi 13 | 14 | if ((CONVERT)); then 15 | echo "Converting $INPUT to $TARGET" >&2 16 | srt-to-text "$1" | uniq >"$TARGET" 17 | fi 18 | -------------------------------------------------------------------------------- /.local/scripts/reminder-sink/flipflop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # https://purarue.xyz/d/flipflop.py?redirect 3 | 4 | set -o pipefail 5 | 6 | # shellcheck disable=SC1091 7 | source "$HPIDATA/tokens" 8 | 9 | EXIT=0 10 | OUTPUT="$(flipflop.py status --filter-on -o json | jq 'keys[]' -r | tr '_' ' ')" || { 11 | notify "flipflop failed to run" 12 | exit 1 13 | } 14 | 15 | if [[ -n "$OUTPUT" ]]; then 16 | echo "${OUTPUT/_/ }" 17 | EXIT=3 18 | fi 19 | exit "$EXIT" 20 | -------------------------------------------------------------------------------- /.local/scripts/reminder-sink/guestbook: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # if there are comments to approve, warn me 3 | 4 | CACHE_FILE="$HOME/.cache/guestbook-comments" 5 | [[ ! -f $CACHE_FILE ]] && exit 0 6 | 7 | EXIT=0 8 | if COMMENT_COUNT="$(is-integer "$(cat "$CACHE_FILE")")"; then 9 | ((COMMENT_COUNT > 0)) && EXIT=2 10 | fi 11 | 12 | exit "$EXIT" 13 | -------------------------------------------------------------------------------- /.local/scripts/reminder-sink/last-export-dates: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # uses the cache file generated by last-export-dates.job: 3 | # https://github.com/purarue/HPI-personal/blob/master/jobs/linux/last_export_dates.job 4 | 5 | CACHE_FILE="${HPIDATA}/last-export-dates.txt" 6 | 7 | # i.e. skip running this on my phone if the cache 8 | # file doesn't exist, only need to be warned about 9 | # this when I'm able to do something about it 10 | [[ ! -f "${CACHE_FILE}" ]] && exit 0 11 | 12 | DATA="$(cat "${CACHE_FILE}")" 13 | if [[ -n "$DATA" ]]; then 14 | echo "$DATA" 15 | exit 3 16 | else 17 | exit 0 18 | fi 19 | -------------------------------------------------------------------------------- /.local/scripts/reminder-sink/listen_to_album: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # if I haven't listened to a new album in the past week, notify me 3 | 4 | set -o pipefail 5 | 6 | EXIT=0 7 | LISTENCOUNT="$(hpi query -r 2w my.nextalbums.history | jq 'length')" || { 8 | notify "listen_to_album: hpi query failed" 9 | exit 1 10 | } 11 | 12 | [[ "${LISTENCOUNT}" == '0' ]] && EXIT=2 13 | exit "$EXIT" 14 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/all/cached_repo_bases.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | evry 1 week -cached-repo-bases && { 4 | printlog 'cached-repo-bases:caching locations of my git repos' 5 | python3 -c 'import my.config; print("\n".join(map(str, my.config.commits.roots)))' >"${XDG_CACHE_HOME?:No cache dir set}/repo_bases.txt" 6 | } 7 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/all/offline_listens_cache.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | evry 4 weeks -update-offline-listens-cache && { 4 | printlog "offline_listens:updating cache..." 5 | python3 -m offline_listens update-cache 6 | dust --no-colors ~/.cache/offline-listens.json 7 | } 8 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/all/promnesia_index.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # https://github.com/karlicoss/promnesia 3 | # run the promnesia indexer 4 | 5 | case "$ON_OS" in 6 | windows* | android*) 7 | exit 0 8 | ;; 9 | esac 10 | 11 | havecmd promneisa || exit 0 12 | 13 | evry 1 day -promnesia_index && { 14 | # source environment variables that may be needed (e.g. ipinfo token) 15 | printlog "promnesia_index:running index..." 16 | with-secrets remove-broken-sms-files 17 | with-secrets promnesia index --overwrite >>/tmp/promnesia_index.log 2>&1 || send-error "promnesia index failed..." 18 | } 19 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/all/pull_dotfiles.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # pull dotfiles repo in $REPOS so commits are accurate in 3 | # https://github.com/karlicoss/HPI/blob/master/my/coding/commits.py 4 | 5 | wait-for-internet -q --timeout "${WFI_TIMEOUT:-10}" || exit 0 6 | 7 | evry 1 day -pull-dotfiles && { 8 | TARGET="$REPOS/dotfiles" 9 | [[ -e "${TARGET}" ]] && cd "${TARGET}" && git pull 10 | } 11 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/all/sync_datafiles.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # sync from local datadir ~/.local/share/window_watcher/ 3 | # to ~/data 4 | # otherwise this is constantly writing to ~/data/ and 5 | # syncthing syncs the file *all the time* 6 | 7 | evry 1 hour -sync-window-watcher && { 8 | FROM="${HOME}/.local/share/window_watcher" 9 | [[ -e "${FROM}" ]] || exit 0 10 | run_window_watcher tasks || send-error 'couldnt sync window_watcher files' 11 | } 12 | 13 | evry 1 hour -sync-ttt && { 14 | FROM="${HOME}/.local/share/ttt" 15 | [[ -e "${FROM}" ]] || exit 0 16 | rsync -Pavh "$FROM/" "$(backup_to ttt)" 17 | } 18 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/all/ttally_cache.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | evry 15 minutes -update-ttally-cache && { 4 | printlog "ttally:updating ttally cache..." 5 | if ttally update-cache; then 6 | : 7 | else 8 | (($? != 2)) && send-error "error updating ttally cache" 9 | fi 10 | } 11 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/android/backup_images.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | STORAGE="${HOME}/storage/" 4 | 5 | IMAGE_DIRS=( 6 | "${STORAGE}/dcim/Camera/" 7 | "${STORAGE}/pictures/Screenshots/" 8 | ) 9 | 10 | evry 5 minutes -backup_images && { 11 | BACKUP_TO="$(backup_to phone_pictures)" 12 | for idir in "${IMAGE_DIRS[@]}"; do 13 | [[ -d "${idir}" ]] || continue 14 | rsync -Pavh --exclude=".*" "${idir}" "${BACKUP_TO}/$(basename "${idir}")" && 15 | find "${idir}" -type f -mtime +180 -print -delete 16 | done 17 | } 18 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/android/create_playlists.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | evry 1 day -create_playlists && { 4 | printlog 'creating playlists...' 5 | cd "$PLAINTEXT_PLAYLIST_MUSIC_DIR" && find . "$PLAINTEXT_PLAYLIST_MUSIC_DIR" -maxdepth 1 -type f -name '*.m3u8' -print -delete 6 | cd "$PLAINTEXT_PLAYLIST_MUSIC_DIR" && fd . -I "$PLAINTEXT_PLAYLIST_PLAYLISTS" -d 1 | parallel -j "$(($(nproc) * 4))" -t 'plainplay m3u {/.} > {/.}.m3u8' 7 | 8 | m3u-shuf "${PLAINTEXT_PLAYLIST_MUSIC_DIR}/car.m3u8" -o "${PLAINTEXT_PLAYLIST_MUSIC_DIR}/car.m3u8" 9 | } 10 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/android/delete_trash.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | evry 1 week -android-empty-trash && { 4 | printlog 'empty-trash:removing trash files manually on android' 5 | rm -rvf ~/.local/share/Trash 6 | } 7 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/linux/build_exobrain.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | wait-for-internet -q --timeout "${WFI_TIMEOUT:-10}" || exit 0 4 | 5 | evry 6 hours -exobrain && { 6 | printlog 'exobrain:building exobrain w/ search index...' 7 | cd "$REPOS/exobrain" || return $? 8 | # if Im currently changing stuff, dont build/push 9 | git-has-untracked-or-changes && { 10 | printlog 'exobrain:uncommitted changes, not building' 11 | exit 0 12 | } 13 | git pull 14 | make link_personal_notes 15 | make built_and_stork 16 | ./scripts/sync_with_retry 17 | } 18 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/linux/copy_images.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # sync photos from my data directory to my XDG_PICTURES_DIR 3 | # on my phone, this is synced from the underlying dcim/Camera folder: 4 | # https://purarue.xyz/d/backup_images.job?dark 5 | 6 | evry 5 minutes -copy_images && { 7 | rsync -Pavh --exclude=".*" "${HPIDATA}/phone_pictures" "${XDG_PICTURES_DIR}" && 8 | find "${HPIDATA}/phone_pictures" -type f -mtime +180 -print -delete 9 | } 10 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/linux/generate_notes_journal_vlogs.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # update generated journal/notes HTML pages so I can reference on my phone 3 | 4 | evry 10 minutes -update-journal-vlog-html-transcripts && render-notes 5 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/linux/linkmusic.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # sync music in playlists to my phone 3 | # https://github.com/purarue/plaintext-playlist 4 | # https://purarue.xyz/d/linkmusic?dark 5 | 6 | evry 30 minutes -linkmusic && linkmusic ~/.local/share/musicsync/ --delete 7 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/linux/mystars.job: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # update https://github.com/purarue/oh-my-stars 3 | 4 | # this script internally has the evry call 5 | # it is like this so I can decouple it running 6 | # on my phone 7 | # https://purarue.xyz/d/update-my-stars?dark 8 | update-my-stars 9 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/linux/tiktok.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | wait-for-internet -q --timeout "${WFI_TIMEOUT:-10}" || exit 0 4 | 5 | evry 6 hours -tiktok-update-rss && { 6 | printlog 'tiktok-update-rss:downloading new videos...' 7 | tiktok-local-rss download 8 | tiktok-local-rss rss 9 | tiktok-update-rss-feeds 10 | } 11 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/linux/update_rss.job: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # update rss feeds on my computer 3 | # purarue.xyz/d/update-rss 4 | 5 | wait-for-internet -q --timeout "${WFI_TIMEOUT:-10}" || exit 0 6 | 7 | evry 1 hour -update-rss && { 8 | if update-rss; then 9 | printlog "updaterss:updated RSS feeds:$(cat ~/.cache/rss-unread)" 10 | else 11 | printlog "updaterss:failed to update RSS feeds" 12 | fi 13 | } 14 | -------------------------------------------------------------------------------- /.local/scripts/supervisor_jobs/linux/warn_mailsync.job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | evry 10 minutes -warn_mailsync && { 4 | # dont warn if obs is open 5 | pgrep -x obs >/dev/null && exit 0 6 | wait-for-internet --quiet --timeout "${WFI_TIMEOUT:-5}" || exit 0 7 | # if mailsync hasn't been run in 30 minutes, set a cache file 8 | # that files' existence is checked for in my status bar, which then displays an error 9 | MAILSYNC_WARN_FILE="${HOME}/.cache/mailsync_warn" 10 | if file-modified-within "${XDG_CONFIG_HOME:-$HOME/.config}/mutt/.mailsynclastrun" '30 minutes'; then 11 | rm -f "${MAILSYNC_WARN_FILE}" 12 | else 13 | touch "${MAILSYNC_WARN_FILE}" 14 | fi 15 | refresh-block mail 16 | } 17 | -------------------------------------------------------------------------------- /.local/scripts/todo-actions/Makefile: -------------------------------------------------------------------------------- 1 | sync: 2 | # find all items in this dir which are executable, and sync them to ~/.local/share/todo-actions 3 | find . -maxdepth 1 -type f -executable -exec cp -auv {} ~/.local/share/todo-actions \; 4 | touch: 5 | find . -maxdepth 1 -type f -executable -exec touch {} \; 6 | -------------------------------------------------------------------------------- /.local/scripts/todo-actions/full: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if [[ -z "$TODO_DIR" ]]; then 6 | echo "TODO_DIR is not set" >&2 7 | exit 1 8 | fi 9 | 10 | export TODO_DIR="$TODO_DIR" 11 | # https://github.com/purarue/full_todotxt 12 | full_todotxt -ps || exit $? 13 | -------------------------------------------------------------------------------- /.local/scripts/todo-actions/interactive: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if attached-to-terminal; then 6 | "$TODO_FULL_SH" fzf 7 | else 8 | "$TODO_FULL_SH" rofi 9 | fi 10 | -------------------------------------------------------------------------------- /.local/share/gpg_autoclick/ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purarue/dotfiles/77843d62e8357579d7e8c8e3cd0033cfce803ff6/.local/share/gpg_autoclick/ok.png -------------------------------------------------------------------------------- /.local/share/gpg_autoclick/tick_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purarue/dotfiles/77843d62e8357579d7e8c8e3cd0033cfce803ff6/.local/share/gpg_autoclick/tick_box.png -------------------------------------------------------------------------------- /.local/share/ipython/profile_calculator/startup/00-load-modules.py: -------------------------------------------------------------------------------- 1 | # load modules for doing math 2 | from math import * # noqa: F401,F403 3 | -------------------------------------------------------------------------------- /.local/share/ipython/profile_default/startup/00-pyflyby.ipy: -------------------------------------------------------------------------------- 1 | # loads https://github.com/deshaw/pyflyby which 2 | # auto-imports modules as they are used 3 | # %load_ext pyflyby 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/abookc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec abook -C "$XDG_CONFIG_HOME/abook/abookrc" -f "$XDG_DOCUMENTS_DIR/addressbook" "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/alacritty-tmux: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec alacritty -e tmux 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/alarm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec paplay /usr/share/sounds/freedesktop/stereo/alarm-clock-elapsed.oga 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/albums: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec openurl "https://purarue.xyz/s/albums" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/beet-export-all: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec beet export "" "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/beet-fix-renamed-files: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec beet update -F=path "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/boxes-nvim: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec boxes -dada-box -pv1h2 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/boxes-python: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # create a comment box as a python comment, text piped from STDIN 3 | exec boxes -dshell -pv1h2 "$@" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/boxes-vim: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | boxes-python | tr '#' '"' 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/calcursed: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | exec calcurse --datadir "$CALCURSE_DIR" --confdir "$XDG_CONFIG_HOME/calcurse" "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/camera: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # open mpv to save a picture (using webcam) in ~/Pictures/pics 3 | 4 | declare pics 5 | pics="${XDG_PICTURES_DIR:?XDG_PICTURES_DIR environment variable not set}/pics" 6 | [[ ! -d "$pics" ]] && mkdir -p "$pics" 7 | cd "$pics" || exit 1 8 | # open mpv so I can take a picture 9 | mpv /dev/video0 10 | exec launch ranger "$pics" 11 | -------------------------------------------------------------------------------- /.local/share/shortcuts/cheat: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | command -v tttlog >/dev/null 2>&1 && tttlog "$(basename "$0") $*" 3 | exec curl -s "https://cheat.sh/$*" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/cl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | clipcopy 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/cl-quickfix: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # pastes text from the clipboard and creates a quickfist list 3 | # this is typically called from kitty -- which saves the 4 | # output of the previous command, then calls this in a new window 5 | # https://github.com/purarue/dotfiles/blob/cdae322fa6b735d5ca12dd3248354b5eeaaab0be/.config/kitty/kitty.conf#L1581-L1588 6 | set -e 7 | exec nvim -q <(clippaste) +copen 8 | -------------------------------------------------------------------------------- /.local/share/shortcuts/clipedit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # edit your clipboard in vim 3 | launch "clippaste | vipe | clipcopy" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/clipreset: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # reset the clipboard formatting 3 | notify "resetting clipboard..." 4 | clippaste | clipcopy 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/clp-args: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # clp, but accepts input as arguments 3 | echo "$*" | clp 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/clr: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # I need to spell this out with 'attached-to-terminal' even though print-or-notify does that exact thing because: 3 | # - if I pipe, then the pipe causes print-or-notify to always send a notification because stdin is not a tty or something 4 | # - if I send it like the notify below, if the data returned by ttally recent food is too long in the terminal, it will 5 | # fail since the argument list is too long 6 | args=("$@") 7 | if [[ -z "$1" ]]; then 8 | args+=("--human-readable") 9 | fi 10 | if attached-to-terminal; then 11 | ttally recent food "${args[@]}" 12 | else 13 | notify "$(ttally recent food "${args[@]}")" 14 | fi 15 | -------------------------------------------------------------------------------- /.local/share/shortcuts/clrs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec clr -hr quantity,water "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/codespell-conf: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | declare -a args=() 3 | if [[ -n "$NVIM_SPELLFILE" ]]; then 4 | args+=("--ignore-words=$NVIM_SPELLFILE") 5 | fi 6 | exec codespell --config ~/.config/codespell/codespell.conf "${args[@]}" "$@" 7 | -------------------------------------------------------------------------------- /.local/share/shortcuts/core: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export BASE_URL='https://purarue.xyz/c/' 3 | exec give 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/create-youtube-dl-resolution-str: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # defaults to about 480p 3 | # otherwise, grabs the format from the FORMAT environment variable 4 | # prints the format string for a particular resolution 5 | FORMAT="${FORMAT:-550}" 6 | exec printf 'bestvideo[height<=%d]+bestaudio/best[height<=%d]' "$FORMAT" "$FORMAT" 7 | -------------------------------------------------------------------------------- /.local/share/shortcuts/curdir: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec basename "$(realpath "$(pwd)")" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/current-city: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ipinfo | grep -m1 city | cut -d':' -f2- | chomp 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/cycle: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # moves the first argument to the end of the list 3 | exec awk "$@" '{ for (i = 2; i <= NF; i++) printf $i "\t" ; print $1 }' 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/dark-theme: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec terminal-set-theme Dark 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/discogs-search: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # https://www.discogs.com/search?q=sampha&type=all 3 | # searches discogs for an album 4 | SEARCH_STR=$(input-dialog "Search for an album > " | chomp | tr " " "+") 5 | [ -z "$SEARCH_STR" ] && exit 1 6 | command -v tttlog >/dev/null 2>&1 && tttlog "$(basename "$0") $SEARCH_STR" 7 | exec openurl "https://www.discogs.com/search/?q=${SEARCH_STR}&type=all" 8 | -------------------------------------------------------------------------------- /.local/share/shortcuts/discord-browser: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec openurl 'https://discord.com/login' 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/dotfiles: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # open the dotfiles git repository 3 | yadm open --print | openurl 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/draglastpic: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | dragon-drop -x "$(lastpic)" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/drive-mount: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # start the ldm (light device mounter) daemon, to mount devices 3 | echo "use lsblk -f to view disk IDs" 4 | exec sudo ldm -u "$(whoami)" 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/ec: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd ~ || exit $? 3 | # fuzzy match list-config names, open one to edit (Edit Config) 4 | fzfcache list-config-no-hist | sed "s#^$HOME/##g" | fzf-edit 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/edit-clipboard: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # edit your clipboard in vim 3 | launch "clippaste | vipe | clipcopy" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/exo-web: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec openurl "https://purarue.xyz/x/notes/?search" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/extracturls: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # receives text from STDIN, extracts unique URLs 3 | # pypi.org/project/urlextract 4 | urls="$(urlextract | sort -u)" 5 | if [ -z "${urls}" ]; then 6 | notify "No URLs found in text" 7 | exit 1 8 | fi 9 | printf "%s\n" "${urls}" 10 | -------------------------------------------------------------------------------- /.local/share/shortcuts/fdf: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec fd --type=file "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/feed-open: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec openurl 'https://purarue.xyz/feed/' 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/file-mime: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # get mime type for one or more files 3 | # this is the same as what rifle (ranger) does 4 | exec file --mime-type -Lb "$@" 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/flake8c: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # flake8 with my default config -- https://purarue.xyz/d/.config/flake8?dark 3 | exec flake8 --config ~/.config/flake8 "$@" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/fzf-edit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | FILE="$(fzfp +m -q "$*")" 3 | if [[ -n "$FILE" ]]; then 4 | editor "$FILE" 5 | else 6 | echo "No file selected" >&2 7 | exit 1 8 | fi 9 | -------------------------------------------------------------------------------- /.local/share/shortcuts/fzfp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec fzf --preview="${HOME}/.config/fzf_preview {}" "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/genpass-phrase: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | USE_DICEWARE=1 exec genpass "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/gi: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # get gitignores for different languages 3 | if [ ! "$(echo "$@" | tr -d "\n\r")" = "" ] && [ ! "$1" = "list" ]; then 4 | printf "*.pdf\n" 5 | fi 6 | curl -sL "https://gitignore.io/api/$*" 7 | printf "\n" 8 | -------------------------------------------------------------------------------- /.local/share/shortcuts/git-color: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec git -c color.ui=always "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/google-chrome-wifi-captive: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec google-chrome-stable 'http://clients3.google.com/generate_204' 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/google-search: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | TEXT="$(cat)" 3 | if [[ -z "$TEXT" ]]; then 4 | TEXT="$(clippaste)" 5 | fi 6 | exec openurl "https://www.google.com/search?q=${TEXT// /+}" 7 | -------------------------------------------------------------------------------- /.local/share/shortcuts/grep-dotfiles: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # searches all my configuration for a string 3 | # passes arguments received to grep 4 | list-config-no-hist | xargs grep -Hrin "$@" 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/heart-cl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | heart "$@" | APP=heart clp 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/html-head-all: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec html-head -a css-dark-mode -a css-pre-wrap "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/i3-jinja: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -x 3 | I3_DIR="${HOME}/.config/i3" 4 | cd "${I3_DIR}" || exit $? 5 | exec jinjanate config.j2 -o config -f yaml " | sed 's/--no-startup-id //g' | cut -d" " -f 2-)" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/img-download-drag: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | img-download "$@" || exit $? 3 | dragon-drop -x "$(clippaste)" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/ipinfo: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # get my ip information 3 | curl -s ipinfo.io | gron | grep -v 'json.readme' | gron -u | jq -r 'to_entries[] | "\(.key): \(.value)"' 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/largechar-clipboard: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | CONTENTS="$(clippaste)" 3 | [ -z "${CONTENTS}" ] && exit 1 4 | printf '%s' "${CONTENTS}" | largechar -c 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/lastpic: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | case "$ON_OS" in 3 | linux*) 4 | exec newest "$@" "${SCREENSHOTS:?No SCREENSHOTS environment variable set}" 5 | ;; 6 | mac*) 7 | find "${HOME}/Desktop" -iname 'screen shot*' | tail -n1 || exit $? 8 | ;; 9 | esac 10 | -------------------------------------------------------------------------------- /.local/share/shortcuts/lastpicdrag: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | dragon-drop -x "$(lastpic)" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/lastpicpreview: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec rifle "$(lastpic)" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/lessi: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec less -i "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/light-theme: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec terminal-set-theme Light 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/list-config: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # list all of my configuration files, by matching combining 3 | # yadm list and a couple search commands 4 | cd # home 5 | { 6 | yadm list | sed "s#^#$HOME/#" 7 | echo "$HOME/.config/yadm/README.md" 8 | echo "$HPIDATA/personal_aliases" 9 | fd --type=file -H -E '__pycache__' -E '.mypy_cache' --full-path "${HOME}" "${XDG_CONFIG_HOME}/todo" "${ZDOTDIR}" 10 | } | grep -v "system-config" | exists | sort -u 11 | -------------------------------------------------------------------------------- /.local/share/shortcuts/list-config-no-hist: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | list-config | grep -vE -e "zsh_history|compdump" -e "$SHORTCUTS_DIR" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/list-images: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec fd '.*\.(png|jpeg|jpg|heic)$' "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/list-videos: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec list-movies "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/listens-desc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # https://github.com/purarue/HPI-personal/blob/master/scripts/listens 3 | exec listens --desc "$@" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/longest-video: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec shortest-video -o max "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/lynx: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # override the lynx binary by 3 | # placing the lynx shortcut 4 | # on $PATH first 5 | LYNX_PATH="$(where lynx | grep -m1 -v "$SHORTCUTS_DIR")" || exit $? 6 | exec "$LYNX_PATH" -accept_all_cookies -cfg="${XDG_CONFIG_HOME}/lynx/lynx.cfg" "$@" 7 | -------------------------------------------------------------------------------- /.local/share/shortcuts/lynx-dump: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec lynx -stdin -dump 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/lynx-from-stdin: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec lynx -stdin 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/mal-recent: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec openurl "myanimelist.net/animelist/purplepinapples?status=7&order=5" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/markdown-list: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec prefix '- ' 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/mediasearch: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if SELECTED=$(printf "moviesearch\ntvsearch" | picker -p "Search Media Type > "); then 3 | exec "$SELECTED" 4 | fi 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/moviesearch: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # searches trakt/letterboxd for a movie 3 | SEARCH_STR=$(input-dialog "Search for a movie > " | chomp | tr " " "+") 4 | [ -z "$SEARCH_STR" ] && exit 1 5 | export SEARCH_STR 6 | moviesearch-trakt & 7 | moviesearch-letterboxd & 8 | wait 9 | -------------------------------------------------------------------------------- /.local/share/shortcuts/moviesearch-letterboxd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # searches letterboxd for a movie 3 | [ -z "$SEARCH_STR" ] && SEARCH_STR=$(input-dialog "Search for a movie > " | chomp | tr " " "+") 4 | [ -z "$SEARCH_STR" ] && exit 1 5 | command -v tttlog >/dev/null 2>&1 && tttlog "$(basename "$0") $SEARCH_STR" 6 | exec openurl "https://letterboxd.com/search/films/${SEARCH_STR}" 7 | -------------------------------------------------------------------------------- /.local/share/shortcuts/moviesearch-trakt: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # searches trakt for a movie 3 | [ -z "$SEARCH_STR" ] && SEARCH_STR=$(input-dialog "Search for a movie > " | chomp | tr " " "+") 4 | [ -z "$SEARCH_STR" ] && exit 1 5 | command -v tttlog >/dev/null 2>&1 && tttlog "$(basename "$0") $SEARCH_STR" 6 | exec openurl "https://trakt.tv/search/movies?query=${SEARCH_STR}&utf8=%E2%9C%93" 7 | -------------------------------------------------------------------------------- /.local/share/shortcuts/mpv-corner: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # mpv wrapper to open a video with mpv and put it in the bottom right corner 3 | setsid -f mpv --x11-name=mpv_stream_media "$@" >/dev/null 2>&1 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/mpv-drag-screenshot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | path="$(mpv-last-screenshot)" 3 | [ -n "$path" ] && exec dragon-drop -x "$path" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/mpv-last-screenshot-upload: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec remsync-image "$(mpv-last-screenshot)" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/mpv-logfile: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | MPV_LOGFILE_TMPDIR="${TMPDIR:-/tmp}/mpv-logs" 3 | mkdir -p "$MPV_LOGFILE_TMPDIR" 4 | exec mpv --log-file="$MPV_LOGFILE_TMPDIR/$(date +%s%N).log" "$@" 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/mtotal: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec mlength -o sum -d m "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/mvlastpic: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | FILE="$(lastpic)" || exit 1 3 | exec mv -v "${FILE}" "./$1" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/mypy-single-lines: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec mypy --show-column-numbers --hide-error-codes --hide-error-context --no-color-output --no-error-summary --no-pretty "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/mystarsfzf: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | update-my-stars 3 | # https://github.com/purarue/oh-my-stars 4 | PICKED="$(fzfcache mystars "$@" | fzf --ansi -0)" || exit $? 5 | printf '%s\n' "${PICKED}" 6 | URL="$(echo "${PICKED}" | urlextract)" 7 | # if a URL was extracted, copy it to my clipboard 8 | [[ -n "${URL}" ]] && { 9 | printf '%s' "${URL}" | clipcopy 10 | printf '%s\n' "${URL}" 11 | } 12 | -------------------------------------------------------------------------------- /.local/share/shortcuts/mz: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # use cached https://github.com/purarue/projects repository information 3 | # to quickly open one of my Github repositories 4 | chosen="$(jq -r '.[] | .html_url' <"${REPOS}/projects/cache.json" | fzf -0)" || exit $? 5 | echo "$chosen" | clipcopy 6 | -------------------------------------------------------------------------------- /.local/share/shortcuts/neomuttr: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # neomutt and refresh my menu bar block 3 | neomutt && refresh-block mail 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/pinta: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec flatpak run com.github.PintaProject.Pinta "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/pipehtml: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # given HTML on STDIN, create a tempfile with its contents 3 | tmpf="$(tmpfile html "$1")" 4 | cat >"$tmpf" 5 | exec printf '%s\n' "$tmpf" 6 | -------------------------------------------------------------------------------- /.local/share/shortcuts/play-music: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # play music in the current directory, recursively 3 | list-music | sort -n | mpv --playlist=- --no-audio-display 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/play-shortest-video: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | if file="$(shortest-video)"; then 4 | exec rifle "$file" 5 | fi 6 | exit 1 7 | -------------------------------------------------------------------------------- /.local/share/shortcuts/playping-loop: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # I use this as a pleasant sounding alarm often, e.g. 3 | # timer 15m && playping-loop 4 | watch playping 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/primes: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec primesieve "$@" -p 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/printer-server: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # open the printer interface in the browser 3 | PRINTER_PORT=$(sudo cat /etc/cups/cupsd.conf | grep -i "Listen localhost" | cut -d":" -f2) 4 | printf "localhost:%d" "$PRINTER_PORT" | openurl 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/pygmentize-html-style: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | style="$(pygmentize-styles | fzf)" || exit $? 3 | exec pygmentize -P style="$style" -O noclasses=True -f html "$@" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/pygmentize-styles: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC2063 3 | pygmentize -L styles | grep '* ' | cut -c3- | sed -e 's/:$//' 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/qf: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # usually used like qf <(grep -Hrin ...) or qf <(!!) 3 | # to repeat last command and create a quickfix list 4 | exec nvim -q "$@" +copen 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/qr-clipboard: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | clippaste | qr 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/realbasename: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec basename "$(realpath "$(pwd)")" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/reload-browser: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec xvkbd -window Navigator -text "i\Cr" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/reminder-sink-notify: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | SR="$(reminder-sink run)" 3 | exec notify "${SR:-No reminders}" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/render-notes: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec make -f "$HOME/.local/scripts/notes_rendered/Makefile" "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/repos: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec repos-list -f "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/reshortcuts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -o pipefail 3 | cd || exit $? 4 | [[ -n "${SHORTCUTS_DIR}" ]] && [[ -d "${SHORTCUTS_DIR}" ]] && rm -rf "${SHORTCUTS_DIR}" 5 | echo "Creating/formatting shortcuts..." 6 | DEBUG_OUTPUT="$(shortcuts create --debug && fd . "${SHORTCUTS_DIR}" -X rifleman 2>&1)" || { 7 | echo "$DEBUG_OUTPUT" 8 | } 9 | -------------------------------------------------------------------------------- /.local/share/shortcuts/rgqf: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec rg --no-heading --with-filename --line-number "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/rj: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | if [[ "$1" == "-o" ]]; then 3 | : # skip internet check, just run the loop once 4 | elif wait-for-internet --quiet --timeout 0; then 5 | exec bgproc_on_machine -pn 6 | fi 7 | export WFI_TIMEOUT=0 8 | exec bgproc_on_machine -on 9 | -------------------------------------------------------------------------------- /.local/share/shortcuts/screenshot-upload: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec remsync-image "$(lastpic)" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/screenshots: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec nsxiv -t "${SCREENSHOTS}" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/shortest-video: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | file="$(list-movies -X mlength -o min -d path "$@")" 3 | if [ -n "$file" ]; then 4 | echo "$file" 5 | else 6 | echo "No media found" >&2 7 | exit 1 8 | fi 9 | -------------------------------------------------------------------------------- /.local/share/shortcuts/shuffle-music: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Plays songs from this folder, recursively, randomly 3 | list-music | shuf | mpv --playlist=- --no-audio-display 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/sort-by-line-length: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -o pipefail 3 | awk '{ print length, $0 }' | sort -n | cut -d' ' -f2- 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/spell: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | spell-list "$@" || true 4 | spell-interactive "$@" 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/spell-fd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec fd --type f --exclude package-lock.json --exclude yarn.lock "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/spell-interactive: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec spell-fd "$@" --exec-batch codespell-conf --write-changes --interactive 3 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/spell-list: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec spell-fd "$@" --exec-batch codespell-conf 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/sqlitebrowser-: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # on linux, call the binary directly 3 | havecmd 'sqlitebrowser' && exec sqlitebrowser "$@" 4 | # on mac, this is installed into /Applications/ 5 | exec open -a DB\ Browser\ for\ SQLite "$@" 6 | -------------------------------------------------------------------------------- /.local/share/shortcuts/ssh-keygen-good: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec ssh-keygen -t ed25519 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/stream-audio: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | STREAM_MEDIA_CMD=mpv exec stream-media --no-video "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/stream-corner: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # streams and sets the instance name on the mpv window 3 | # this is used with a for_window hook in i3 to put the 4 | # window in the bottom right 5 | exec stream-media --x11-name=mpv_stream_media "$@" 6 | -------------------------------------------------------------------------------- /.local/share/shortcuts/stream-corner-1080: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export FORMAT=1100 3 | exec stream-corner-at "$@" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/stream-corner-480: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec stream-corner-at "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/stream-corner-720: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export FORMAT=850 3 | exec stream-corner-at "$@" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/stream-corner-at: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # set the FORMAT environment variable to specify maximum height/width 3 | # defaults to about 480p 4 | STREAM_MEDIA_CMD=mpv exec stream-corner --ytdl-format="$(create-youtube-dl-resolution-str)" "$@" 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/stream-from-firefox: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # copies the current URL from firefox, and starts streaming it with stream-at-480 3 | # escape, then yy (yank the URL; using the vimium extension) 4 | xvkbd -window Navigator -text "\Eyy" 5 | sleep 1 # just to make sure its copied 6 | exec stream-corner-480 7 | -------------------------------------------------------------------------------- /.local/share/shortcuts/styluac: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec stylua --config-path "$HOME/.config/nvim/stylua.toml" "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/sync-neomutt: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # wait for internet, sync my mail, then launch neomutt 3 | wait-for-internet && mailsync 4 | i3blocks-refresh-mk mail 5 | neomutt || return $? 6 | i3blocks-refresh-mk mail 7 | -------------------------------------------------------------------------------- /.local/share/shortcuts/syncgui: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec openurl 'localhost:8384' 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/synonym: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | word="${1:?Provide the word to list synonyms as first argument}" 3 | moby "${word}" | grep , | tr , '\n' | chomp 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/text2html: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec pygmentize -f html "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/timer-till-playping: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | timer-till "$*" && playping-loop 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/tmpfile: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ext="${1:-tmp}" 3 | filename="${2:-$(genpasswd -rsym -rnum)}" 4 | echo "$(mktemp -d)/${filename}.${ext}" 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/to-icon: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # convert an image to a 16x16 icon - to favicon size 3 | FILEPATH=${1:?Must provide image to convert} 4 | NEW_FILEPATH="$(remove-extension "${FILEPATH}")-icon.png" 5 | exec magick -resize x16 -gravity center -crop 16x16+0+0 -flatten -colors 256 "${FILEPATH}" "${NEW_FILEPATH}" 6 | -------------------------------------------------------------------------------- /.local/share/shortcuts/todo: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec todo.sh "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/trakt-progress: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec openurl "https://trakt.tv/users/purplepinapples/progress" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/tstamp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec date +'%Y%m%d%H%M%S' 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/tvsearch: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # searches trakt for a tv show 3 | SEARCH_STR=$(input-dialog "Search for a TV show > " | chomp | tr " " "+") 4 | [ -z "$SEARCH_STR" ] && exit 1 5 | command -v tttlog >/dev/null 2>&1 && tttlog "$(basename "$0") $SEARCH_STR" 6 | exec openurl "https://trakt.tv/search/shows?query=${SEARCH_STR}&utf8=%E2%9C%93" 7 | -------------------------------------------------------------------------------- /.local/share/shortcuts/twitch-stream: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # open chatterino and use mpv to stream from twitch 3 | STREAMER="${1:?Pass the twitch user to stream from as the first argument.}" 4 | pgrep -x chatterino >/dev/null || setsid chatterino >/dev/null 2>&1 & 5 | MPVF_PICKER=rofi setsid mpvf "https://www.twitch.tv/${STREAMER}" >/dev/null & 6 | -------------------------------------------------------------------------------- /.local/share/shortcuts/tz: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec time-in tz "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/unicode: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | file="${TMPDIR:-/tmp}/unicode_input" 3 | kitty -- sh -c "kitten unicode_input >\"$file\"" || exit $? 4 | contents="$(cat "$file")" 5 | [[ -z "$contents" ]] && exit 1 6 | clp <<<"$contents" 7 | rm -f "$file" 8 | -------------------------------------------------------------------------------- /.local/share/shortcuts/unlines: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec paste -sd " " 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/up-live: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | TERM=xterm exec up --unsafe-full-throttle 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/update-forks: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec clone-repos ~/.config/clone-repos/update-forks.yaml 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/url-echo-redirect: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # echo the URL that would be redirected to 3 | URL="${1:-"$(cat)"}" 4 | if [[ -z "$URL" ]]; then 5 | echo "No URL provided" >&2 6 | exit 1 7 | fi 8 | exec curl -w "%{url_effective}\n" -ILsS "$URL" -o /dev/null 9 | -------------------------------------------------------------------------------- /.local/share/shortcuts/urldrag: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # dragon a picture from my clipboard https://github.com/mwh/dragon 3 | img-download || exit $? 4 | exec dragon-drop -x "$(clippaste)" 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/urlpicpreview: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # preview a picture from a URL 3 | img-download "$@" || exit $? 4 | rifle "$(clippaste)" 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/usdate: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # print the date in the us format 3 | exec date "+%m/%d/%y" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/vic: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | EXECUTABLE="${1:?No Executable provided}" 3 | LOCATION="$(command -v "${EXECUTABLE}")" || exit $? 4 | cd "$(dirname "${LOCATION}")" || exit $? 5 | exec editor "$(basename "${LOCATION}")" 6 | -------------------------------------------------------------------------------- /.local/share/shortcuts/vix: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec ix -v 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/watchtwitch: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | twitchlive -output-format json | jq -r '.[] | .username' | picker -p "who to watch? " | xargs -r twitch 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/webcam-pic: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # open mpv to save a picture (using webcam) in ~/Pictures/pics 3 | 4 | declare pics 5 | pics="${XDG_PICTURES_DIR:?XDG_PICTURES_DIR environment variable not set}/pics" 6 | [[ ! -d "$pics" ]] && mkdir -p "$pics" 7 | cd "$pics" || exit 1 8 | # open mpv so I can take a picture 9 | mpv /dev/video0 10 | exec launch ranger "$pics" 11 | -------------------------------------------------------------------------------- /.local/share/shortcuts/webcam-test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec /usr/bin/mpv /dev/video0 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/wfi: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # wait for internet connection and ping me 3 | command -v tttlog >/dev/null 2>&1 && tttlog "$(basename "$0")" 4 | wait-for-internet "$@" && { 5 | notify "INTERNET" 6 | playping 7 | } 8 | -------------------------------------------------------------------------------- /.local/share/shortcuts/wfib: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # wfi, and then reload the browser 3 | wfi 4 | exec reload-browser 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/which-cat: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # I have a which-cat zsh function as well, this is a fallback for scripts 3 | # or when I'm in nvim 4 | EXEC="${1:?Must provide executable as first argument}" 5 | if LOC="$(which "$EXEC")" >/dev/null 2>&1; then 6 | cat "$LOC" 7 | else 8 | printf "Could not find %s\n" "$EXEC" >&2 9 | fi 10 | -------------------------------------------------------------------------------- /.local/share/shortcuts/yadm-format: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | # autoformat all my dotfiles 3 | set -o pipefail 4 | cd 5 | yadm list | exists | grep -v 'lazy-lock.json' | rifleman - "$@" 6 | -------------------------------------------------------------------------------- /.local/share/shortcuts/yadm-lint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | # run linters on all my dotfiles 3 | set -o pipefail 4 | cd 5 | yadm list | exists | rifleman - -a lint 6 | -------------------------------------------------------------------------------- /.local/share/shortcuts/yh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd ~/.local/share/yadm/repo.git/ || exit $? 3 | exec gh "$@" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/youtube-dl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec python3 -m yt_dlp -o '%(title)s.%(ext)s' -ci "$@" 3 | -------------------------------------------------------------------------------- /.local/share/shortcuts/youtube-dl-480: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # download at about 480p 3 | exec youtube-dl-at "$@" 4 | -------------------------------------------------------------------------------- /.local/share/shortcuts/youtube-dl-720: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # download at about 720p 3 | export FORMAT=850 4 | exec youtube-dl-at "$@" 5 | -------------------------------------------------------------------------------- /.local/share/shortcuts/youtube-dl-at: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # set the FORMAT environment variable to control resolution 3 | exec youtube-dl -f "$(create-youtube-dl-resolution-str)" "$@" 4 | -------------------------------------------------------------------------------- /.local/system-config/etc/X11/xorg.conf.d/20-amdgpu.conf: -------------------------------------------------------------------------------- 1 | Section "Device" 2 | Identifier "AMD" 3 | Driver "amdgpu" 4 | Option "TearFree" "true" 5 | EndSection 6 | -------------------------------------------------------------------------------- /.local/system-config/etc/X11/xorg.conf.d/30-trackpad-options.conf: -------------------------------------------------------------------------------- 1 | # This applies the option any libinput device also matched by the other 2 | # directives. See the xorg.conf(5) man page for more info on 3 | # matching devices. 4 | # 5 | # Apply Natural Scrolling - Flip the Scroll direction for the trackpad 6 | 7 | Section "InputClass" 8 | Identifier "flip touchpad scrolling" 9 | Driver "libinput" 10 | Option "Natural Scrolling" "true" 11 | Option "Accel Speed" "0.2" 12 | EndSection 13 | -------------------------------------------------------------------------------- /.local/system-config/etc/pacman.d/hooks/mirrorupgrade.hook: -------------------------------------------------------------------------------- 1 | [Trigger] 2 | Operation = Upgrade 3 | Type = Package 4 | Target = pacman-mirrorlist 5 | 6 | [Action] 7 | Description = Updating pacman-mirrorlist with reflector and removing pacnew... 8 | When = PostTransaction 9 | Depends = reflector 10 | Exec = /bin/sh -c "reflector --country 'United States' --download-timeout 30 --latest 200 --age 24 --sort rate --save /etc/pacman.d/mirrorlist; rm -f /etc/pacman.d/mirrorlist.pacnew" 11 | -------------------------------------------------------------------------------- /.local/system-config/etc/systemd/system/lockscreen@.service: -------------------------------------------------------------------------------- 1 | # enable this like 'sudo systemctl enable lockscreen@$(whoami).service --now' 2 | 3 | [Unit] 4 | Description=Lock the screen on sleep 5 | Before=sleep.target 6 | Before=suspend.target 7 | 8 | [Service] 9 | User=%i 10 | Type=simple 11 | Environment=DISPLAY=:0 12 | ExecStartPre=/usr/bin/xset dpms force suspend 13 | ExecStart=%h/.local/scripts/cross-platform/lock-screen 14 | TimeoutSec=infinity 15 | 16 | [Install] 17 | WantedBy=sleep.target 18 | WantedBy=suspend.target 19 | -------------------------------------------------------------------------------- /.termux/colors.properties: -------------------------------------------------------------------------------- 1 | # https://github.com/catppuccin/catppuccin 2 | foreground=#cad3f5 3 | background=#24273a 4 | cursor=#f4dbd6 5 | 6 | color0=#494d64 7 | color1=#ed8796 8 | color2=#a6da95 9 | color3=#eed49f 10 | color4=#8aadf4 11 | color5=#f5bde6 12 | color6=#8bd5ca 13 | color7=#b8c0e0 14 | 15 | color8=#5b6078 16 | color9=#ed8796 17 | color10=#a6da95 18 | color11=#eed49f 19 | color12=#8aadf4 20 | color13=#f5bde6 21 | color14=#8bd5ca 22 | color15=#a5adcb 23 | 24 | color16=#f5a97f 25 | color17=#f4dbd6 26 | -------------------------------------------------------------------------------- /.xinitrc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # source keymap configuration 4 | # move xmodmap somewhere else so it doesn't pollute my home directory 5 | usermodmap="$HOME/.config/X11/Xmodmap" 6 | 7 | if [ -f "$usermodmap" ]; then 8 | xmodmap "$usermodmap" 9 | fi 10 | 11 | # source user profile 12 | # sets a bunch of global-ish environment variables, detects which OS I'm 13 | # on and sets the ON_OS environment variable which I use in lots of my scripts 14 | if [ -f "${HOME}/.profile" ]; then 15 | . "${HOME}/.profile" 16 | fi 17 | 18 | # start some nice programs 19 | 20 | if [ -d /etc/X11/xinit/xinitrc.d ]; then 21 | for f in /etc/X11/xinit/xinitrc.d/?*.sh; do 22 | # shellcheck disable=SC1090 23 | [ -x "$f" ] && . "$f" 24 | done 25 | unset f 26 | fi 27 | 28 | # set key repeat rate 29 | xset r rate 300 25 30 | 31 | exec i3 32 | --------------------------------------------------------------------------------