These are my dotfiles. Please see ./.emacs.d/index.org for my Emacs configuration, this file contains non-Emacs stuff.
org-babel-tangle
to tangle all files.C-u org-babel-tangle
to only tangle current file.- This file uses
«this»
syntax in source code blocks to embed noweb code instead of<<that>>
syntax. This allows me to use noweb inside bash blocks without interfering with its syntax highlighter. See Postamble. - You’ll want to make sure some of the files should tangle with executable permission. For that:
(add-hook 'org-babel-post-tangle-hook 'executable-make-buffer-file-executable-if-script-p)
- Also some configuration files are tangled based on a condition. Here are the convenience condition functions:
(defun when-darwin (file-path) (if (eq system-type 'darwin) file-path "no")) (defun when-linux (file-path) (if (eq system-type 'gnu/linux) file-path "no")) (cl-defun when-on (&key linux darwin) (pcase system-type ('darwin darwin) ('gnu/linux linux) (_ "no")))
- Here is the code that puts them together, this block is executed during the startup of this file. See Postamble (at the end of this file) where this code-block is called for execution.
«executable_hook» «conditions»
You can run arbitrary shell commands inside a code block like this: «sh("which git")»
. This can be useful where an output of a command needs to be statically placed in an exported file.
(let (output status)
(with-temp-buffer
(setq status (call-process-shell-command code nil (current-buffer)))
(setq output (string-trim (buffer-substring-no-properties (point-min) (point-max)))))
(if (or (not (eq status 0))
(eq (length output) 0))
default
output))
…and because I use «sh("which X")»
a lot, I also have this:
(string-trim (shell-command-to-string (format "which '%s'" binary)))
The following is just the babel version of (im-when-on ...)
function defined above. It helps you insert the text to a file based on current operating system.
(im-when-on :darwin darwin :linux linux)
And this is for getting values of elisp variables:
(symbol-value (intern var))
options(repos = c(CRAN = "https://cran.rstudio.com"))
Just activate readline.
(use-modules (ice-9 readline))
(activate-readline)
Install global packages to user-local.
prefix=${HOME}/.npm-packages
Well, nix is mainly a package manager but it also is a programming language.
The following enables nix search
command.
experimental-features = nix-command flakes
# Disable gatekeeper, allows you to install apps from unidentified developers
sudo spctl --master-disable
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>${name}</string>
<key>ProgramArguments</key>
<array>
${args}
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>${HOME}/.nix-profile/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
</dict>
</plist>
(replace-regexp-in-string
"\\${[a-zA-Z]+}"
(lambda (substr)
(pcase substr
("${name}" (format "net.isamert.%s" name))
("${args}" (replace-regexp-in-string
"${HOME}"
(expand-file-name "~")
(string-join (mapcar (lambda (it) (format "<string>%s</string>" it)) args) "\n") t t))
("${HOME}" (expand-file-name "~"))
(_ "???")))
(save-excursion
(org-babel-goto-named-src-block "mac-launchagent-template")
(org-element-property :value (org-element-at-point)))
t t)
Here is a great tool for exporting and importing your application specific bindings in Keyboard Shortcuts settings page. I was hesitant to use this feature because it was not easy to replicate but with this tool it’s quite convenient.
# Installation
curl -L -o ~/.local/bin/mac-kb-exporter.php https://gist.githubusercontent.com/miclf/bf4b0cb6de9ead726197db7ed3d937b5/raw/a135140b52014273d59567f24983ded99e30ac2d/macos_keyboard_shortcuts_exporter_importer.php
chmod +x ~/.local/bin/mac-kb-exporter.php
# Usage
# mac-kb-exporter.php save ~/.config/mac-application-shortcuts.json
# mac-kb-exporter.php load ~/.config/mac-application-shortcuts.json
{
"org.mozilla.firefox": {
"Close Tab": "^W",
"Close Window": "⌘W",
"Find Again": "^G",
"Find in Page...": "^F",
"History": "^H",
"Bookmarks": "^B",
"New Tab": "^T"
},
"com.google.Chrome": {
"Find...": "^F",
"New Tab": "^T",
"Open Location...": "^L"
}
}
I used to use yabai but my main pain point was the virtual desktops. Aerospace fixes it completely and it’s more responsive.
brew install --cask nikitabobko/tap/aerospace
cmd-period = 'focus-monitor right'
cmd-comma = 'focus-monitor left'
cmd-shift-period = 'move-node-to-monitor right'
cmd-shift-comma = 'move-node-to-monitor left'
cmd-f1 = 'layout v_accordion'
cmd-f2 = 'layout h_accordion'
cmd-f3 = 'layout tiles horizontal vertical'
cmd-t = 'layout floating tiling'
cmd-h = 'focus --boundaries-action stop left'
cmd-j = 'focus --boundaries-action stop down'
cmd-k = 'focus --boundaries-action stop up'
cmd-l = 'focus --boundaries-action stop right'
cmd-shift-h = 'move left'
cmd-shift-j = 'move down'
cmd-shift-k = 'move up'
cmd-shift-l = 'move right'
cmd-shift-minus = 'resize smart -50'
cmd-shift-equal = 'resize smart +50'
cmd-1 = 'workspace 1'
cmd-2 = 'workspace 2'
cmd-3 = 'workspace 3'
cmd-4 = 'workspace 4'
cmd-5 = 'workspace 5'
cmd-6 = 'workspace 6'
cmd-7 = 'workspace 7'
cmd-8 = 'workspace 8'
cmd-9 = 'workspace 9'
cmd-0 = 'workspace 0'
cmd-shift-1 = 'move-node-to-workspace 1'
cmd-shift-2 = 'move-node-to-workspace 2'
cmd-shift-3 = 'move-node-to-workspace 3'
cmd-shift-4 = 'move-node-to-workspace 4'
cmd-shift-5 = 'move-node-to-workspace 5'
cmd-shift-6 = 'move-node-to-workspace 6'
cmd-shift-7 = 'move-node-to-workspace 7'
cmd-shift-8 = 'move-node-to-workspace 8'
cmd-shift-9 = 'move-node-to-workspace 9'
cmd-tab = 'workspace-back-and-forth'
cmd-alt-ctrl-f13 = 'layout floating tiling'
cmd-alt-ctrl-f14 = 'fullscreen'
cmd-alt-ctrl-f11 = 'resize smart -50'
cmd-alt-ctrl-f12 = 'resize smart +50'
cmd-alt-ctrl-f19 = 'focus-monitor left'
cmd-alt-ctrl-f20 = 'focus-monitor right'
cmd-alt-ctrl-shift-f19 = 'move-node-to-monitor left'
cmd-alt-ctrl-shift-f20 = 'move-node-to-monitor right'
cmd-alt-ctrl-f15 = 'focus --boundaries all-monitors-outer-frame --boundaries-action stop left'
cmd-alt-ctrl-f16 = 'focus --boundaries all-monitors-outer-frame --boundaries-action stop down'
cmd-alt-ctrl-f17 = 'focus --boundaries all-monitors-outer-frame --boundaries-action stop up'
cmd-alt-ctrl-f18 = 'focus --boundaries all-monitors-outer-frame --boundaries-action stop right'
cmd-alt-ctrl-shift-f15 = 'move left'
cmd-alt-ctrl-shift-f16 = 'move down'
cmd-alt-ctrl-shift-f17 = 'move up'
cmd-alt-ctrl-shift-f18 = 'move right'
cmd-alt-ctrl-f1 = 'workspace 1'
cmd-alt-ctrl-f2 = 'workspace 2'
cmd-alt-ctrl-f3 = 'workspace 3'
cmd-alt-ctrl-f4 = 'workspace 4'
cmd-alt-ctrl-f5 = 'workspace 5'
cmd-alt-ctrl-f6 = 'workspace 6'
cmd-alt-ctrl-f7 = 'workspace 7'
cmd-alt-ctrl-f8 = 'workspace 8'
cmd-alt-ctrl-f9 = 'workspace 9'
cmd-alt-ctrl-f10 = 'workspace 0'
cmd-alt-ctrl-shift-f1 = 'move-node-to-workspace 1'
cmd-alt-ctrl-shift-f2 = 'move-node-to-workspace 2'
cmd-alt-ctrl-shift-f3 = 'move-node-to-workspace 3'
cmd-alt-ctrl-shift-f4 = 'move-node-to-workspace 4'
cmd-alt-ctrl-shift-f5 = 'move-node-to-workspace 5'
cmd-alt-ctrl-shift-f6 = 'move-node-to-workspace 6'
cmd-alt-ctrl-shift-f7 = 'move-node-to-workspace 7'
cmd-alt-ctrl-shift-f8 = 'move-node-to-workspace 8'
cmd-alt-ctrl-shift-f9 = 'move-node-to-workspace 9'
cmd-alt-ctrl-shift-f10 = 'move-node-to-workspace 0'
# https://nikitabobko.github.io/AeroSpace/guide
# https://nikitabobko.github.io/AeroSpace/commands
after-login-command = []
after-startup-command = []
start-at-login = true
enable-normalization-flatten-containers = true
enable-normalization-opposite-orientation-for-nested-containers = true
accordion-padding = 30
default-root-container-layout = 'tiles'
default-root-container-orientation = 'auto'
key-mapping.preset = 'qwerty'
# Mouse lazily follows focused monitor (default in i3)
on-focused-monitor-changed = ['move-mouse monitor-lazy-center']
# Mouse lazily follows any focus (window or workspace)
#on-focus-changed = ['move-mouse window-lazy-center']
[gaps]
inner.horizontal = 0
inner.vertical = 0
outer.left = 0
outer.bottom = 0
outer.top = 0
outer.right = 0
[workspace-to-monitor-force-assignment]
1 = 'main'
2 = 'main'
3 = 'main'
4 = 'main'
5 = 'main'
6 = 'main'
7 = 'secondary'
8 = 'secondary'
9 = 'secondary'
0 = 'secondary'
# See https://nikitabobko.github.io/AeroSpace/guide#exec-env-vars
[exec]
inherit-env-vars = true
[exec.env-vars]
PATH = '/opt/homebrew/bin:/opt/homebrew/sbin:${HOME}/.bin:${PATH}'
[mode.main.binding]
# - Letters. a, b, c, ..., z
# - Numbers. 0, 1, 2, ..., 9
# - Keypad numbers. keypad0, keypad1, keypad2, ..., keypad9
# - F-keys. f1, f2, ..., f20
# - Special keys. minus, equal, period, comma, slash, backslash, quote, semicolon, backtick,
# leftSquareBracket, rightSquareBracket, space, enter, esc, backspace, tab
# - Keypad special. keypadClear, keypadDecimalMark, keypadDivide, keypadEnter, keypadEqual,
# keypadMinus, keypadMultiply, keypadPlus
# - Arrows. left, down, up, right
# All possible modifiers: cmd, alt, ctrl, shift
#cmd-f1 = 'layout v_accordion'
#cmd-f2 = 'layout h_accordion'
#cmd-f3 = 'layout tiles horizontal vertical'
# «aerospace-mac-keyboard-bindings»
«aerospace-uhk-bindings»
This is the global keybinding manager for OSX. Here is an example configuration for yabai and here is a more generic example configuration demonstrating it’s capabilities.
It can be installed through homebrew:
brew install koekeishiya/formulae/skhd
skhd --install-service
skhd --start-service
hyper - r : emacsclient -c
hyper - i : emacsclient --eval "(im-globally (im-select-any-snippet))"
hyper - o : emacsclient --eval "(im-globally (im-people))"
hyper - g : emacsclient --eval "(im-globally (im-gitlab-select-project))"
hyper - v : emacsclient --eval "(empv-toggle-video)"
hyper - return : kitty $HOME
# Define a mode name shortcuts
:: shortcuts @
# From default mode, F13 opens shortcuts mode
f13 ; shortcuts
# In shortcuts mode, F13 returns back to default mode
shortcuts < f13 ; default
# In shortcuts mode, m returns back to normal mode by simulating f13
# key and then does the command
shortcuts < m : skhd -k "f13"; emacsclient --eval "(im-toggle-mic)"
cmd-l
(focus urlbar) clashes with my global shortcut, so I simply want to remap it to ctrl-l in Firefox. Unfortunately, Firefox does not exposecmd-l
in it’s menu, so its not possible to remap it natively using macOS’ “Keyboard Shortcuts” settings page. Here I remapctrl-l
toF6
(which also provides the “focus urlbar” functionality).
ctrl - l [
# F6 key
"Firefox" : skhd -k "0x61"
* ~
]
Port 2222
HostKey «sh("echo $HOME")»/.config/sshd/hostkey
PidFile «sh("echo $HOME")»/.config/sshd/pid
Create the host key and enable starting it at boot:
ssh-keygen -t rsa -f ~/.config/sshd/hostkey -N ''
launchctl load -w ~/Library/LaunchAgents/net.isamert.sshd.plist
«mk-launchagent(name="sshd", args='("/usr/sbin/sshd" "-f" "${HOME}/.config/sshd/cfg"))»
To enable it, run this:
launchctl load -w ~/Library/LaunchAgents/net.isamert.sshd.plist
«mk-launchagent(name="kdeconnect", args='("/Applications/kdeconnect-indicator.app/Contents/MacOS/kdeconnect-indicator"))»
launchctl load -w ~/Library/LaunchAgents/net.isamert.kdeconnect.plist
Save the script by running the next code block:
curl 'https://gist.githubusercontent.com/lancethomps/a5ac103f334b171f70ce2ff983220b4f/raw/50a04a65f16349a70884f490f856f27021ac396e/close_notifications_applescript.js' > ~/.local/bin/macos-clear-all-notifications.js
And here is the skhd binding:
hyper - y : osascript -l JavaScript "$HOME/.local/bin/macos-clear-all-notifications.js"
I use it minimally for some quality-of-life improvements.
brew install hammerspoon
I have a little menubar that shows the current clocked in task and the current tab-bar of Emacs in MacOS menu. I was going to use a socket instead of an HTTP server but didn’t manage to get hs.socket
to work for some reason.
-- * Menubar & Emacs
menubar = hs.menubar.new()
menubar:setTitle("-")
workspace = ""
task = ""
function updateTitle()
-- TODO: https://www.hammerspoon.org/docs/hs.styledtext.html
local taskIcon = (task == "") and "✖" or "✓"
menubar:setTitle(string.format("%s %s | ⭾ [%s]", taskIcon, task, workspace))
end
function cb(verb, path, headers, body)
if path == "/task" then
task = body
updateTitle()
elseif path == "/workspace" then
workspace = body
updateTitle()
else
print(">> Unknown request to: ", path, headers, body)
end
return "ok", 200, {}
end
server = hs.httpserver.new()
server:setPort(4562)
server:setCallback(cb)
server:start()
If the icons in the menubar takes a lot of place, some of them goes under the notch and becomes totally invisible, non-interactable. The following two things help:
- Setting a lower spacing and padding for the icons (need to restart your computer afterwards):
defaults -currentHost write -globalDomain NSStatusItemSpacing -int 5
defaults -currentHost write -globalDomain NSStatusItemSelectionPadding -int 3
- Hidden Bar → This lets you selectively hide some items so that only the things you want stay visible.
I use kitty in MacOs as it’s easiest one to configure specifically for MacOS and it has sane defaults mostly.
shell fish
macos_option_as_alt yes
font_size 16.0
macos_show_window_title_in none
hide_window_decorations titlebar-and-corners
macos_quit_when_last_window_closed yes
font_family Cascadia Code NF
scrollback_lines 50000
Journal files starts to take a lot of disk space. I put a simple limit to that here.
[Journal]
SystemMaxUse=500M
Unit files started with --user
will have the following variables.
$HOME/.bin:$HOME/.local/bin:$NPM_PACKAGES/bin:$GOPATH/bin:$HOME/.cargo/bin:$PATH
GOPATH="$HOME/.go"
R_LIBS_USER="$HOME/.rlibs"
NPM_PACKAGES="$HOME/.npm-packages"
NODE_PATH="$HOME/.npm-packages/lib/node_modules"
PATH=«path-variable»
KDE fucks-up the PATH variable (and only the PATH variable) while booting up. This fixes that:
export PATH=«path-variable»
After tangling all unit files, run this:
systemctl --user daemon-reload
systemctl --user enable emacsd
systemctl --user enable syncthing
Following snippet enables some configurations for pacman:
- Parallel
- Enables parallel downloads. Really makes a difference, especially while upgrading your system.
- Color
- Adds color to pacman output.
- VerbosePkgLists
- This gives you more information about the packages that are going to be installed.
- TotalDownload
- Adds ETA information for total progress etc.
«sh("cat /etc/pacman.conf | sed -E 's/^#(Parallel|Color|VerbosePkgLists|TotalDownload)/\\1/'")»
[main]
defaultyes=True
- Install
ddcutil
- Enable automatic loading of
i2c-dev
module with systemd.i2c-dev
- Add your user to the i2c group.
sudo usermod -aG i2c $USER
- The group should’ve been created by the
ddcutil
package. If not, do this first:sudo groupadd --system i2c
- The group should’ve been created by the
- Give permission to i2c user for
/dev/i2c-*
devices:sudo cp /usr/share/ddcutil/data/45-ddcutil-i2c.rules /etc/udev/rules.d # OR do this, if the file does not exist: echo 'KERNEL=="i2c-[0-9]*", GROUP="i2c"' >> /etc/udev/rules.d/10-i2c-user-permissions.rules
Now you should be able to do:
ddcutil getvcp 10 # Return current brightness value
ddcutil setvcp 10 50 # Set the current brightness value
Also see this gnome extension and it’s README for further information: https://github.com/daitj/gnome-display-brightness-ddcutil
I have a usb splitter that switches between machines when clicked on a physical button. But this does not change my monitors input automatically. The following script is designed to run-according to the given UDEV rule-when a keyboard (my UHK keyboard) is attached or removed and switches to the right monitor input.
ACTION=="add", ATTRS{idVendor}=="37a8", ATTRS{idProduct}=="0003", RUN+="/opt/bin/switch-monitor-on-keyboard-change add"
ACTION=="remove", ENV{PRODUCT}=="37a8/3/2", RUN+="/opt/bin/switch-monitor-on-keyboard-change remove"
Reload the udev rules.
sudo udevadm control --reload-rules
#!/usr/local/bin/bb
(require '[babashka.process :refer [shell process exec]]
'[babashka.fs :as fs])
;; TODO: Automatically switch UHK layout between Mac and Linux too
;;; Lock file stuff
;; This is required because there are lot's of events generated when
;; the keyboard is connected/disconnected at the same time. This
;; prevents concurrent runs.
(def lock-file "/tmp/switch-monitor-on-keyboard-change.lock")
(when (fs/exists? lock-file)
(println "Program is already running.")
(System/exit 1))
(spit lock-file "locked")
;;; Variables
(try
;;; Load state
(def state-file "/tmp/bb-device-state.edn")
(def state
(if (fs/exists? state-file)
(read-string (slurp state-file))
{}))
(def action (first *command-line-args*))
;;; Save state
;; Directly save it so that consequent runs are aware of it faster
(spit state-file (pr-str {:action action}))
;;; Act
(def usbc "27")
(def hdmi "17")
(cond
(and (= "add" action)
(= (:action state) "remove"))
(shell "ddcutil" "setvcp" "0x60" hdmi)
(and (= "remove" action)
(= (:action state) "add"))
(shell "ddcutil" "setvcp" "0x60" usbc)
:else (println "Doing nothing..."))
;;; Persist state
(spit state-file (pr-str {:action action}))
(finally
(fs/delete lock-file)))
In the past I used Xmodmap & xcpae based solution for remapping keys. Now I am experimenting with KMonad which give more or less the same flexibility with a better configuration format. It’s killer feature is that it also works on Mac[fn:: Well, almost. I had to change a few stuff in source to make it work.]. This means that I can truly keep my work computer and personal computers keyboard layouts & keyboard shortcuts in sync.
Some references for editing this configuration:
- https://github.com/kmonad/kmonad/blob/master/doc/quick-reference.md
- https://github.com/kmonad/kmonad/blob/master/keymap/tutorial.kbd
- https://github.com/kmonad/kmonad/blob/master/src/KMonad/Keyboard/Keycode.hs
- https://old.reddit.com/r/emacs/comments/oyzfz9/kmonad_and_the_power_of_infinite_leader_keys/
I use the AUR package kmonad-git
for my Linux machine and compile it manually on Mac. Following configuration is needed for Linux and taken from here.
# Add uinput group
sudo groupadd uinput
# Add current user to input and uinput groups
sudo usermod -aG input $USER
sudo usermod -aG uinput $USER
KERNEL=="uinput", MODE="0660", GROUP="uinput", OPTIONS+="static_node=uinput"
Restart your machine.
git clone --recursive https://github.com/kmonad/kmonad.git
cd kmonad
nix build "./nix?submodules=1"
(let ((usb-kbd (car (file-expand-wildcards "/dev/input/by-*/usb-*Microsoft*kbd")))
(onboard-kbd (car (file-expand-wildcards "/dev/input/by-*/platform*kbd"))))
(cond
((eq system-type 'darwin) "(iokit-name)")
((and usb-kbd (file-exists-p usb-kbd)) (format "(device-file \"%s\")" usb-kbd))
((and onboard-kbd (file-exists-p onboard-kbd)) (format "(device-file \"%s\")" onboard-kbd))))
(defcfg
input «kmonad-device()»
output «when-on(linux="(uinput-sink \"My KMonad output\")", darwin="(kext)")»
fallthrough true
allow-cmd true)
Here I use an external program (xtype
, which is explained below) to type unicode characters instead of utilizing XCompose as suggested by KMonad. Managing, making it running is hard with XCompose. Also it does not work on Mac.
Also see these:
- https://en.wikibooks.org/wiki/Unicode/List_of_useful_symbols
- https://isamert.net/2022/08/12/typing-unicode-characters-programmatically-on-linux-and-macos.html
(defalias
;; Cool unicode chars
¿ (cmd-button "xtype ¿")
λ (cmd-button "xtype λ")
≤ (cmd-button "xtype ≤")
≥ (cmd-button "xtype ≥")
¬ (cmd-button "xtype ¬")
✓ (cmd-button "xtype ✓")
↑ (cmd-button "xtype ↑")
↓ (cmd-button "xtype ↓")
← (cmd-button "xtype ←")
→ (cmd-button "xtype →")
≠ (cmd-button "xtype ≠")
« (cmd-button "xtype «")
» (cmd-button "xtype »")
⇒ (cmd-button "xtype ⇒")
↣ (cmd-button "xtype ↣")
↢ (cmd-button "xtype ↢")
⇄ (cmd-button "xtype ⇄")
;; Turkish chars
ş (cmd-button "xtype ş")
ğ (cmd-button "xtype ğ")
ü (cmd-button "xtype ü")
ı (cmd-button "xtype ı")
ö (cmd-button "xtype ö")
ç (cmd-button "xtype ç"))
This uses pynput
python package (which can be installed with pip install pynput
or with aur trizen -S python-pynput
). The alternative is using xdotool type
(or ydotool type
) but they both fail on unicode inputs, they simply skip them. pynput
works quite well. I found it here.
THIS ALSO WORKS FOR MAC. But I decided to not to use it for two reasons:
- It’s a bit slow on Mac.
- It’s a bit hard to manage python dependencies on Mac.
#!/usr/bin/env python
import sys
from pynput.keyboard import Controller
Controller().type(' '.join(sys.argv[1:]))
This is a simple program for inserting given characters (including unicode) to currently open application. Taken from here.
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
if (argc > 1) {
NSString *theString = [NSString stringWithUTF8String:argv[1]];
NSUInteger len = [theString length];
NSUInteger n, i = 0;
CGEventRef keyEvent = CGEventCreateKeyboardEvent(nil, 0, true);
unichar uChars[20];
while (i < len) {
n = i + 20;
if (n>len){n=len;}
[theString getCharacters:uChars range:NSMakeRange(i, n-i)];
CGEventKeyboardSetUnicodeString(keyEvent, n-i, uChars);
CGEventPost(kCGHIDEventTap, keyEvent); // key down
CGEventSetType(keyEvent, kCGEventKeyUp);
CGEventPost(kCGHIDEventTap, keyEvent); // key up (type 20 characters maximum)
CGEventSetType(keyEvent, kCGEventKeyDown);
i = n;
[NSThread sleepForTimeInterval:0.004]; // wait 4/1000 of second, 0.002 it's OK on my computer, I use 0.004 to be safe, increase it If you still have issues
}
CFRelease(keyEvent);
}
}
return 0;
}
Run this to install it:
cd ~/.cache
clang -framework Foundation -framework ApplicationServices TypeChars.m -l objc -o xtype
cp ./xtype ~/.local/bin/xtype
(defalias
;; Fat arrow
fa #(= >)
;; light arrow
la #(- >)
;; home path
hm #(~ /))
(string-join
(mapcar
(lambda (it)
(let ((chr (downcase (char-to-string it))))
(format "p%s C-M-A-S-%s" chr chr)))
(seq-remove (lambda (it) (seq-contains '(?\( ?_ ?\)) it))
(number-sequence ?! ?`)))
"\n")
(defalias
sym (layer-toggle symbols)
hyp (tap-next esc (layer-toggle hyper)))
(deflayer symbols
_ _ _ _ _ _ _ _ _ _ _ _ _
_ @« @» " @⇒ @↢ @↣ @⇄ _ _ _ _ @≠ _
_ \( @↑ \) @la @✓ _ @ü @ı @ö _ \( \)
_ @← @ş @→ @fa @ğ left down up rght _ _ _ _
_ _ _ @↓ @ç _ @λ @¬ _ @≤ @≥ _ _
_ _ _ _ _ _ _ _ _)
(defalias
pret C-M-A-S-ret
pspc C-M-A-S-spc
ptb C-M-A-S-tab
«kmonad-generate-aliases-for-hyper-layer()»)
;; Instead of utilizing Hyper key for creating shortcuts like I did
;; with my Xmodmap configuration, I use C-M-A-S as the so called hyper
;; key. This makes the key behave exactly same on Linux and Mac.
(deflayer hyper
_ _ _ _ _ _ _ _ _ _ _ _ _
@p` @p1 @p2 @p3 @p4 @p5 @p6 @p7 @p8 vold volu @p- @p= _
@ptb @pq @pw @pe @pr @pt @py @pu @pi @po @pp @p[ @p]
_ @pa @ps @pd @pf @pg @ph @pj @pk @pl @p; @p' @p\ @pret
_ @p\ @pz @px @pc @pv @pb @pn @pm @p, @p. @p/ _
_ _ _ _ @pspc _ _ _ _)
I use this config on both linux and mac. This is the configuration for my external keyboard. Some of the uses of \
character is just to make the total key count same as the generic layers I defined above. They are mapped to itself again in the main layer.
«kmonad-cfg»
«kmonad-unicode»
«kmonad-macros»
(defsrc
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12
grv 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ]
caps a s d f g h j k l ; ' \ ret
lsft \ z x c v b n m , . / rsft
\ lctl lmet lalt spc ralt rmet cmp rctl)
(deflayer main
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12
grv 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ]
@hyp a s d f g h j k l ; ' \ ret
lsft # z x c v b n m , . / rsft
\ lctl lmet lalt spc @sym rmet cmp rctl)
«kmonad-layers»
[Unit]
Description=KMonad keyboard config
[Service]
Type=simple
Restart=always
RestartSec=3
ExecStart=which("kmonad") %h/.config/kmonad-linux.kbd -l warn
Nice=-20
[Install]
WantedBy=xdg-desktop-autostart.target
This is the configuration for the embedded keyboard on mac.
«kmonad-cfg»
«kmonad-unicode»
«kmonad-macros»
(defsrc
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12
grv 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ]
caps a s d f g h j k l ; ' \ ret
lsft \ z x c v b n m , . / rsft
fn lctl lmet lalt spc rmet ralt cmp rctl)
(deflayer main
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12
grv 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ]
@hyp a s d f g h j k l ; ' \ ret
lsft # z x c v b n m , . / rsft
lctl fn lalt lmet spc @sym rmet rctrl rctl)
«kmonad-layers»
«kmonad-cfg»
«kmonad-unicode»
«kmonad-macros»
(defsrc
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12
grv 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ]
caps a s d f g h j k l ; ' \ ret
lsft \ z x c v b n m , . / rsft
lctl lmet lalt fn spc rmet ralt cmp rctl)
(deflayer main
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12
grv 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ]
@hyp a s d f g h j k l ; ' \ ret
lsft # z x c v b n m , . / rsft
lctl lalt lmet fn spc @sym rmet rctrl rctl)
«kmonad-layers»
PATH="$PATH:$HOME/.local/bin:$HOME/.bin"
BROWSER=jaro
VISUAL="jaro --method=edit"
EDITOR="jaro --method=edit"
# * Variables
set $mod Mod4
set $hypr Ctrl+Mod1+Mod4+Shift
set $left h
set $down j
set $up k
set $right l
set $term foot
set $menu rofi -terminal '$term' -window-thumbnail -sidebar-mode -markup -show-icons -show combi -combi-modes window#drun#run#recursivebrowser -modes window#drun#filebrowser -combi-modi
set $calc qalculate-gtk
# * Monitors
output * bg /usr/share/backgrounds/default.png fill
output * render_bit_depth 10
# * Visuals
smart_borders on
focus_wrapping no
default_border pixel 3
# * Behaviour
floating_modifier $mod normal
# * Keybindings - Apps
bindsym $hypr+a exec $menu
bindsym $hypr+w exec $calc
bindsym $hypr+s exec grimshot copy area
bindsym $mod+Return exec $term
bindsym $hypr+Return exec $term
bindsym $hypr+c exec copyq toggle
bindsym $hypr+t exec crow
bindsym $hypr+i exec emacsclient --eval "(im-globally (im-select-any-snippet))"
bindsym $hypr+p exec emacsclient --eval "(im-globally (im-password-act))"
bindsym Ctrl+Mod1+l exec loginctl lock-session
# * Keybindings - Window management
bindsym $mod+$left focus left
bindsym $mod+$down focus down
bindsym $mod+$up focus up
bindsym $mod+$right focus right
bindsym $mod+Shift+$left move left
bindsym $mod+Shift+$down move down
bindsym $mod+Shift+$up move up
bindsym $mod+Shift+$right move right
bindsym $mod+Shift+c reload
bindsym $mod+w kill
bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -B 'Yes, exit sway' 'swaymsg exit'
# * Keybindings - Workspaces
bindsym $mod+1 workspace number 1
bindsym $mod+2 workspace number 2
bindsym $mod+3 workspace number 3
bindsym $mod+4 workspace number 4
bindsym $mod+5 workspace number 5
bindsym $mod+6 workspace number 6
bindsym $mod+7 workspace number 7
bindsym $mod+8 workspace number 8
bindsym $mod+9 workspace number 9
bindsym $mod+0 workspace number 10
bindsym $mod+Shift+1 move container to workspace number 1
bindsym $mod+Shift+2 move container to workspace number 2
bindsym $mod+Shift+3 move container to workspace number 3
bindsym $mod+Shift+4 move container to workspace number 4
bindsym $mod+Shift+5 move container to workspace number 5
bindsym $mod+Shift+6 move container to workspace number 6
bindsym $mod+Shift+7 move container to workspace number 7
bindsym $mod+Shift+8 move container to workspace number 8
bindsym $mod+Shift+9 move container to workspace number 9
bindsym $mod+Shift+0 move container to workspace number 10
# * Keybindings - Splitting and container management
# You can "split" the current object of your focus with
# $mod+b or $mod+v, for horizontal and vertical splits
# respectively.
bindsym $mod+backslash splith
bindsym $mod+minus splitv
# Switch the current container between different layout styles
bindsym $mod+y layout stacking
bindsym $mod+u layout tabbed
bindsym $mod+i layout toggle split
# Make the current focus fullscreen
bindsym $mod+f fullscreen
# Toggle the current focus between tiling and floating mode
bindsym $mod+t floating toggle
# Swap focus between the tiling area and the floating area
bindsym $mod+space focus mode_toggle
# Move focus to the parent container
bindsym $mod+a focus parent
# * Keybindings - Scratchpad
# Move the currently focused window to the scratchpad
bindsym $hypr+e move scratchpad
# Show the next scratchpad window or hide the focused scratchpad window.
# If there are multiple scratchpad windows, this command cycles through them.
bindsym $hypr+r scratchpad show
# * Keybindings - Resize
mode "resize" {
bindsym $right resize shrink width 10px
bindsym $up resize grow height 10px
bindsym $down resize shrink height 10px
bindsym $left resize grow width 10px
# Return to default mode
bindsym Return mode "default"
bindsym Escape mode "default"
}
bindsym $mod+r mode "resize"
# * Window configurations
for_window [app_id="qalculate-gtk"] floating enable
for_window [app_id="com.github.hluk.copyq"] floating enable
for_window [app_id="org.kde.CrowTranslate"] floating enable
# * Include other stuff
# Include configs from 3 locations:
# - /usr/share/sway/config.d
# - /etc/sway/config.d
# - $XDG_CONFIG_HOME/sway/config.d ($HOME/.config/sway/config.d)
#
# If multiple directories contain the files with the same name, the later
# directory takes precedence; `$XDG_CONFIG_HOME/sway/config.d/20-swayidle.conf`
# will always be loaded instead of `/usr/share/sway/config.d/20-swayidle.conf`
# or `/etc/sway/config.d/20-swayidle.conf`
#
# This mechanism permits overriding our default configuration per-system
# (/etc) or per-user ($XDG_CONFIG_HOME) basis. Just create the file you
# want to modify/override in the higher-level directory.
#
# For example, to disable the default bar from Fedora configs, you'll need to
# $ echo -n > "$HOME/.config/sway/config.d/90-bar.conf"
#
# Note the quoting, the $() and the arguments quoting. All the parts are equally
# important to make the magic work. And if you want to learn the secret behind
# the trick, it's all in the `wordexp(3)`.
#
include '$(/usr/libexec/sway/layered-include "/usr/share/sway/config.d/*.conf" "/etc/sway/config.d/*.conf" "${XDG_CONFIG_HOME:-$HOME/.config}/sway/config.d/*.conf")'
if status is-interactive
starship init fish | source
if test -f ~/.extrarc
source ~/.extrarc
end
end
# * Stow aliases
alias ssync="stow -d ~/Nextcloud/Sync/ -t ~"
# * Package management
abbr -a -- paci 'sudo pacman -S'
abbr -a -- pacr 'sudo pacman -Rns'
abbr -a -- pacs 'pacman -Ss'
abbr -a -- pacupd 'sudo pacman -Sy'
abbr -a -- pacupg 'sudo pacman -Syu'
abbr -a -- pacbin 'pacman -F'
abbr -a -- dnfi 'sudo dnf install'
abbr -a -- dnfr 'sudo dnf remove'
abbr -a -- dnfs 'dnf search'
abbr -a -- dnfp 'dnf provides'
abbr -a -- dnfupd 'sudo dnf update'
abbr -a -- dnfupg 'sudo dnf upgrade'
abbr -a -- brews 'brew search'
abbr -a -- brewi 'brew install'
abbr -a -- brewr 'brew uninstall'
abbr -a -- brewupd 'brew update'
abbr -a -- brewupg 'brew upgrade'
function nixi
nix-env -iA "nixpkgs.$argv[1]"
end
alias nixr='nix-env -e'
alias nixs='nix search nixpkgs'
# * Systemctl
abbr -a -- ctl systemctl
abbr -a -- ctls 'systemctl status'
abbr -a -- ctlr 'systemctl restart'
abbr -a -- ctlu 'systemctl --full --user'
abbr -a -- ctlus 'systemctl --full --user status'
abbr -a -- ctlur 'systemctl --full --user restart'
abbr -a -- log 'journalctl --unit'
abbr -a -- logu 'journalctl --user --unit'
# * Opening stuff
abbr -a -- v 'jaro --method=view'
abbr -a -- e 'jaro --method=edit'
abbr -a -- g 'jaro --method=gallery'
abbr -a -- open jaro
# * File/folder stuff
abbr -a -- mkx 'chmod +x'
abbr -a -- tree 'lsd --tree'
abbr -a -- ls 'lsd --group-dirs=first --classify'
abbr -a -- ll 'lsd --group-dirs=first --classify --long --date=relative --timesort --blocks=date,size,name'
abbr -a -- lls 'lsd --group-dirs=first --classify --long --header --date=relative --timesort --git --hyperlink=auto'
abbr -a -- lla 'lsd --group-dirs=first --classify --long --header --date=relative --timesort --git --hyperlink=auto --almost-all'
abbr -a -- cdtemp 'cd $(mktemp -d)'
alias cdf='cd $(fd -t d -d 8 | fzf)' # cd fuzzy
alias find-dups='find . ! -empty -type f -exec md5sum {} + | sort | uniq -w32 -dD'
# * Streaming stuff
# Higlight json parts of the stream and print other lines plain
# ./program_that_may_output_json | logjson
abbr -a --position anywhere -- @logjson 'jq -R -r ". as \$line | try fromjson catch \$line"'
# Less that supports color
abbr -a @less --position anywhere --set-cursor "% | less -r"
# Complements the one above, adds --color=always to current command.
# somecommand @color @less
abbr -a --position anywhere -- @color --color=always
# * Git
abbr -a -- gcm 'git commit -m'
abbr -a -- gds 'git diff --staged'
abbr -a -- gs 'git status'
abbr -a -- gco 'git chekout'
# * Meta
abbr -a :q exit
# * Kubernetes
abbr -a -- kctx 'kubectl config current-context'
abbr -a -- kctxs-list 'kubectl config get-contexts --output=name'
abbr -a -- kctx-use 'kubectl config use-context'
[cmd_duration]
# Show system notifications for commands that takes longer than 5 seconds
min_time_to_notify = 5000
show_notifications = true
notification_timeout = 99999
Utilizing ~/.config/fish/functions/
instead of the config file or the conf.d
folder is a better idea because the funcitons inside functions
folder are lazy loaded.
function extract
if test -f $argv[1]
switch $argv[1]
case '*.tar.bz2'
tar xjf "$argv[1]"
case '*.tar.gz'
tar xzf "$argv[1]"
case '*.bz2'
bunzip2 "$argv[1]"
case '*.rar'
unrar x "$argv[1]"
case '*.gz'
gunzip "$argv[1]"
case '*.tar'
tar xf "$argv[1]"
case '*.tbz2'
tar xjf "$argv[1]"
case '*.tgz'
tar xzf "$argv[1]"
case '*.zip'
unzip "$argv[1]"
case '*.Z'
uncompress "$argv[1]"
case '*.7z'
7z x "$argv[1]"
case '*'
echo "'$argv[1]' cannot be extracted via extract()"
end
else
echo "Usage:"
echo "extract <archive-name>"
end
end
function compress
set EXT $argv[1]
set argv $argv[2..-1] # Shift the arguments to remove the first one
switch $EXT
case '-h' '--help'
echo "Usage:"
echo "compress <archive-name>.EXT file1 file2"
echo
echo "EXT can be one of the following: .7z .tar.gz .tgz .tar.bz2 .zip."
echo "Also you can add .nocompress to the end of EXT to archive without compressing."
return
case '*.7z'
7z a "$EXT" $argv
case '*.tar.gz' '*.tgz'
tar -czvf "$EXT" $argv
case '*.tar.gz.nocompress' '*.tgz.nocompress'
tar -cvf (string replace .nocompress '' $EXT) $argv
case '*.tar.bz2'
tar -cjvf "$EXT" $argv
case '*.zip'
zip -r "$EXT" $argv
case '*'
echo "Unrecognized EXT: $EXT"
echo
compress --help
end
end
function encrypt
switch $argv[1]
case '-h' '--help'
echo "Usage:"
echo "encrypt <input-file> [<output-file>]"
echo
echo "If <output-file> is skipped, then the output will be <input-file>.encrypted"
return
case '*'
set INPUT $argv[1]
set OUTPUT $argv[2]
if not test -f "$INPUT"
echo "$INPUT not found."
return 1
end
if test -z "$OUTPUT"
set OUTPUT "$INPUT.encrypted"
end
if test -f "$OUTPUT"
echo "$OUTPUT already exists."
return 1
end
gpg --symmetric --cipher-algo AES256 --output "$OUTPUT" "$INPUT"
end
end
function decrypt
switch $argv[1]
case '-h' '--help'
echo "Usage:"
echo "decrypt <input-file> [<output-file>]"
echo
echo "If <output-file> is skipped, then the output will be <input-file> but the last suffix is removed"
return
case '*'
set INPUT $argv[1]
set OUTPUT $argv[2]
if not test -f "$INPUT"
echo "$INPUT not found."
return 1
end
if test -z "$OUTPUT"
set OUTPUT (string trim --right --chars='.' (basename "$INPUT"))
end
if test -f "$OUTPUT"
echo "$OUTPUT already exists."
return 1
end
gpg --decrypt --output "$OUTPUT" "$INPUT"
end
end
function ipinfo
switch (uname)
case Linux
set localips (ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d/ -f1)
case Darwin
set localips (ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}')
end
echo $localips
echo
echo ======================
echo
curl --silent https://ipinfo.io | jq .
end
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
After issuing the command above, you need to do PREFIX I
to install all plugins.
# ####################################################
# __ ____
# / /_____ ___ __ ___ __ _________ ____ / __/
# / __/ __ `__ \/ / / / |/_// ___/ __ \/ __ \/ /_
# _/ /_/ / / / / / /_/ /> <_/ /__/ /_/ / / / / __/
# (_)__/_/ /_/ /_/\__,_/_/|_(_)___/\____/_/ /_/_/
# ####################################################
# Add the plugin manager (PREFIX I -> install them)
set -g @plugin 'tmux-plugins/tpm'
# PREFIX C-s -> save, PREFIX C-r -> restore
set -g @plugin 'tmux-plugins/tmux-resurrect'
# Highlight when prefix is pressed, in copy mode etc.
set -g @plugin 'tmux-plugins/tmux-prefix-highlight'
set -g @prefix_highlight_show_copy_mode 'on'
set -g @prefix_highlight_copy_mode_attr 'fg=white,bg=yellow,bold' # default is 'fg=default,bg=yellow'
set -g @prefix_highlight_show_sync_mode 'on'
set -g @prefix_highlight_sync_mode_attr 'fg=black,bg=green' # default is 'fg=default,bg=yellow'
# PREFIX o -> captures the output of last command
set -g @plugin 'artemave/tmux_capture_last_command_output'
set -g @command-capture-key o
set -g @command-capture-prompt-pattern '➜ '
set -g default-shell $PREFIX/bin/fish
set -g mouse on
set -g base-index 1 # Window indexes starts from 1
setw -g pane-base-index 1 # Pane indexes starts from 1
set -s escape-time 0 # Remove the delay after hitting <ESC>
set-option -g set-titles off
set-option -g allow-rename off
# Reload config
bind r source-file ~/.tmux.conf
# Open copy mode
bind -n M-y copy-mode
# Set prefix to A-a
unbind C-b
set -g prefix M-a
bind-key M-a send-prefix
# Increase the time of display-panes (PREFIX q)
set -g display-panes-time 4000
# Split remaps
bind \\ split-window -h -c '#{pane_current_path}'
bind - split-window -v -c '#{pane_current_path}'
unbind '"'
unbind %
# Vim-like pane switches
bind k selectp -U
bind j selectp -D
bind h selectp -L
bind l selectp -R
# Pane switches (without prefix key)
bind -n M-h select-pane -L
bind -n M-j select-pane -D
bind -n M-k select-pane -U
bind -n M-l select-pane -R
bind -n M-\\ split-window -h -c '#{pane_current_path}'
bind -n M-- split-window -v -c '#{pane_current_path}'
# Swapping shortcuts
bind-key W choose-tree -Zw "swap-window -t '%%'"
bind-key P choose-tree -Zw "swap-pane -t '%%'"
# Vi keys for copy-mode
setw -g mode-keys vi
bind-key -T copy-mode-vi v send-keys -X begin-selection
bind-key -T copy-mode-vi Enter send-keys -X copy-selection-and-cancel
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "xclip -selection clipboard"
bind -n M-s run-shell -b tmux-switch
# Status bar theme
set -g status-position bottom
set -g status-left-length 32
set -g status-fg white
set -g status-bg black
set -g status-left '#[fg=colour235,bg=colour252,bold] #S #[fg=colour252,bg=colour238,nobold]#[fg=colour245,bg=colour238,bold] #(whoami) #[fg=colour238,bg=black,nobold]'
set -g window-status-format "#[fg=white,bg=black] #I #W "
set -g window-status-current-format "#[fg=black,bg=colour39]#[fg=colour25,bg=colour39,noreverse,bold] #I #W #[fg=colour39,bg=black,nobold]"
set -g status-right "#{prefix_highlight}"
# Load tmux plugin manager
run '~/.tmux/plugins/tpm/tpm'
[user]
name = «sh("git config --global --get user.name", "Isa Mert Gurbuz")»
email = «sh("git config --global --get user.email", "[email protected]")»
[github]
user = isamert
[rebase]
autoStash = true
[pull]
rebase = true
[fetch]
prune = true
[status]
short = true
In this file I define some file associations. Please refer to jaro README for more info. It’s simply an xdg-open
alternative.
- To experiment associations/jaro, do:
$ guile guile> (load ".local/bin/jaro") guile> (load ".config/associactions")
;; -*- mode: scheme; -*-
;;; Configuration
(set!
dynamic-menu-program
(oscase
#:darwin "choose"
#:gnu/linux "rofi -dmenu"))
;;; Bindings
(bind
#:pattern '("(application|text)/(x-)?(pdf|postscript|ps|epub.*)" "image/(x-)?eps")
#:program '(zathura %f))
(bind
#:pattern '("^text/html" "^application/x?htm")
#:program 'browser
#:edit 'editor)
(bind
#:name 'editor
#:pattern '("^text/" "^application/(x-)?(shellscript|json|javascript|xml)")
#:emacs (elisp
(find-file "%F"))
;; If I simply give the file to emacsclient, it opens it in a split
;; for some reason, instead of making it the only window in the frame
#:program '(emacsclient -c --eval "(find-file \"%F\")")
#:term '(emacsclient -nw -c --eval "(find-file \"%F\")"))
(bind
#:name 'empv
#:pattern '("^video/" "^audio/")
#:program (elisp (empv-play "%F"))
#:on-error '(mpv %f))
(bind
#:pattern "inode/directory"
#:program '(thunar %f)
#:term '(yazi %f)
#:gallery 'nomacs)
(bind
#:pattern "https://.*zoom\\.us/j/(\\w+)\\?pwd=(\\w+)"
#:program '(zoom zoommtg://zoom.us/join?confno=%1&pwd=%2))
(bind
#:pattern '("^https?://(www.)?youtube.com/"
"^https?://(www.)?youtu.be/"
"^https?://(www.)?v.redd.it/\\w+/DASH"
"^https?://([a-zA-Z-]+)?streamable.com"
"^https?://giant.gfycat.com/.+"
"https?://v.redd.it/.+"
"^https?://.+/.+\\.(gifv|mp4|webm)(\\?.+)?$")
#:program 'empv
#:on-error 'browser)
(bind
#:pattern "^https?://.+/.+\\.(jpg|png|gif)(\\?.+)?$"
#:program `(imv %f))
(bind
#:pattern "^image/.*"
;; Start with given image, and open the directory of given file
#:program '(imv -n %f %d)
#:gallery 'nomacs)
(bind
#:pattern "^https?://(www.)?reddit.com/r/(\\w+)/comments/(.*?)/"
#:program (elisp (reddigg-view-comments "https://www.reddit.com/r/%2/comments/%3"))
#:on-error 'browser)
(bind
#:pattern '("^magnet:" "\\.torrent$")
#:program '(qbittorrent --skip-dialog=false %f))
(bind
#:name 'browser
#:pattern '("^https?://.*" "^.*\\.html?(#[\\w_-]+)?")
#:emacs (elisp (eww "%f"))
#:program (elisp (eww "%f"))
;; #:program '(qutebrowser %f)
;; #:test '(pgrep qutebrowser)
#:on-fail '(firefox %f)
#:edit 'editor)
(bind
#:pattern "^application/(x-)?(tar|gzip|bzip2|lzma|xz|compress|7z|rar|gtar|zip)(-compressed)?"
#:program '(file-roller %f))
(bind
#:pattern "^application/(x-)?(vnd.)?(ms-|ms)?(excel|powerpoint|word)"
#:program '(desktopeditors %F))
;;; Catch-all
(bind
#:pattern ".*"
#:program (select-one-of
#:alternatives
#:bindings
#:binaries))
;;; References
(bind
#:name 'bat
#:pattern ".*"
#:program '(bat --paging=always %f))
(bind
#:name 'nomacs
#:pattern "^image/.*"
#:program '(nomacs %f))
;; vi:syntax=scheme
Just redirect everything to jaro.
text/html; w3m -v -F -T text/html %s; edit=jaro --method=edit; compose=jaro --method=edit; nametemplate=%s.html; copiousoutput
text/*; jaro '%s'; copiousoutput
application/*; jaro '%s'
image/*; jaro '%s'
audio/*; jaro '%s'
video/*; jaro '%s'
message/*; jaro '%s'
model/*; jaro '%s'
*/*; jaro '%s'
Redirect everything to jaro.
COMMAND jaro
Signal messenger for terminal, see scli.
open-command=jaro %u
enable-notifications=true
save-history=true
use-formatting=true
wrap-at=75
contacts-autohide=true
color=true
partition-contacts=true
Key | Action |
---|---|
p | pause |
f | fullscreen |
C+l | show playlist |
<, > | playlist prev,next |
A+0-5 | change window scale |
9,0 | volume down/up |
m | mute |
a | change/switch audio |
z, Z | subtitle delay -/+ |
+, - | scale subtitle |
s | change/switch subtitle |
r, R | change sub-position |
T, A-t | download subtitle (en/tr) |
ctrl++ | increase audio delay |
ctrl+- | decrease audio delay |
[, ] | playback speed scale |
. , | one frame forward/backward |
1-2 | contrast |
3-4 | brightness |
5-6 | gamma |
7-8 | saturation |
i | show video info |
c | show youtube comments |
input-ipc-server=/tmp/mpvsocket
# Display Turkish subtitles if available, fall back to English otherwise.
slang=tr,en
# Play Korean audio if available, fall back to English otherwise.
# (I watch Korean stuff a lot and they always gets overridden by English audio)
alang=ko,en,eng
# If the file seems to be valid UTF-8, prefer UTF-8, otherwise use Turkish
# encoding.
sub-codepage=cp1254
# Search these directories for subtitles
sub-file-paths=sub:Sub:subs:Subs:subtitle:Subtitle:subtitles:Subtitles
# Load all subtitles from directories listed above
sub-auto=all
# 10 from bottom
sub-pos=90
# Filter subtitle additions for the deaf or hard-of-hearing (SDH)
sub-filter-sdh=yes
sub-filter-sdh-harder=yes
# Tile properly
no-keepaspect-window
# Show youtube comments
# This gets the video ID from filename, as mpv sets it this way.
c run "term" "--float" "-e" "/bin/bash" "-c" "pipe-viewer --comments-order=top --comments='${path}' --page=1 --no-interactive"
# Copy the filename
y run "/bin/sh" "-c" "printf ${filename} | xcopy"; show-text "Filename copied: ${filename}"
& run "/bin/sh" "-c" "jaro --program=browser '${path}'"; show-text "Opening ${path} in browser..."
! add chapter -1 # skip to previous chapter
@ add chapter 1 # next
# Download subtitle
T run "mediastuff" "mpv-subdl" "${path}" "eng" # english subtitle
Alt+t run "mediastuff" "mpv-subdl" "${path}" "tur" # turkish subtitle
l seek 5
h seek -5
j seek -60
k seek 60
L no-osd seek 1 exact
H no-osd seek -1 exact
J no-osd seek 5 exact
K no-osd seek -5 exact
f cycle fullscreen
p cycle pause
m cycle mute
b cycle-values loop-file "inf" "no"
0 add volume 2
9 add volume -2
s cycle sub
a cycle audio # switch audio streams
# resize subtitle
+ add sub-scale +0.1
- add sub-scale -0.1
Alt+0 set window-scale 0.25
Alt+1 set window-scale 0.5
Alt+2 set window-scale 0.75
Alt+3 set window-scale 1
Alt+4 set window-scale 1.5
Alt+5 set window-scale 2
CTRL+l script-message osc-playlist
Use b
key to disable/enable it. It’s on by default.
mkdir -p ~/.config/mpv/scripts/
curl https://codeberg.org/jouni/mpv_sponsorblock_minimal/raw/branch/master/sponsorblock_minimal.lua -o ~/.config/mpv/scripts/sponsorblock_minimal.lua
# By default it only skips "sponsor" category, I want more:
sed -Ei 's/([ \t]+)categories =.*/\1categories = '"'"'"sponsor","selfpromo","interaction","intro","outro"'"'"'/' ~/.config/mpv/scripts/sponsorblock_minimal.lua
UI for mpv. Pretty looking and very functional. Has a menu that is searchable. Also allows you to switch stream quality on YouTube videos etc. Spectacular.
Installation:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/tomasklaen/uosc/HEAD/installers/unix.sh)"
Thumbnail plugin. Works with uosc.
Installation:
curl https://raw.githubusercontent.com/po5/thumbfast/master/thumbfast.lua -o ~/.config/mpv/scripts/thumbfast.lua
I had a fat neovim configuration at past but I don’t use vim anymore. This is just the minimal configuration I’ve started maintaining
" ##################################################
" (_)
" __ ___ _ __ ___ _ __ ___
" \ \ / / | '_ ` _ \| '__/ __|
" \ V /| | | | | | | | | (__
" (_)_/ |_|_| |_| |_|_| \___|
" ##################################################
" visuals {{{
set background=dark " rearranges colors for dark background
set colorcolumn=80 " 80-col line
set termguicolors " true color support
set number relativenumber " line numbers relative to current line ()
set cursorline " highlight current line
"hi Normal guibg=none ctermbg=none| " transparent background
" }}}
" tabs and spaces {{{
set mouse=a " enable mouse (helps precise resizing etc)
set tabstop=4 " tab-char width
set shiftwidth=4 " indent-level width
set softtabstop=4 " column count inserted by the tab key
set expandtab " tabs -> spaces
set smartindent " do it smart
filetype plugin indent on " determine indent by plugins
" }}}
" better defaults {{{
" search/completion
set ignorecase " ignore case while searching
set smartcase " abc -> Abc and abc, Abc -> only Abc (works in combination with ^^)
set splitbelow
set splitright
set foldmethod=syntax " (indent, marker: fold between {{{ }}})
" }}}
" utility {{{
set showmatch " visually indicate matching parens
set autoread " update buffer if file is edited externally
set title " terminal inherits title
set clipboard=unnamedplus " use system clipboard
set inccommand=nosplit " show effects of a command live
set spelllang=en_us " default spelllang
set signcolumn=yes " removes flickering caused by lang server
set undofile " saves undo history to file (nvim's undodir default is OK)
set completeopt=menu,menuone,preview,noselect,noinsert
" }}}
" netrw (file browser) {{{
" :help netrw-quickmap
let g:netrw_banner = 0 " remove banner
let g:netrw_liststyle = 3 " tree style listing
let g:netrw_browse_split = 4 " ...
let g:netrw_altv = 1 " spawn it at left split
let g:netrw_usetab = 1 " use tab for expanding/shrinking folders
let g:netrw_winsize = 10 " occupies 10% of window
" }}}
" trailing spaces {{{
set listchars=tab:▸\ ,trail:· " Show trailing spaces and tabs
set list " ^^ enable it
autocmd BufWritePre * :%s/\s\+$//e " remove trailing spaces on save
" }}}
" stuff {{{
nmap <space> <leader>
inoremap jk <ESC>| " jk escapes to normal mode
tnoremap jk <C-\><C-n>| " jk escapes to normal mode (in terminal mode)
tnoremap <Esc> <C-\><C-n>| " esc escapes to normal mode
" }}}
" split mappings {{{
" next sections looks pretty much like my i3 config except Win key is replaced
" with the Alt key
" move between buffers with alt+hjkl
nnoremap <A-h> <C-w>h
nnoremap <A-j> <C-w>j
nnoremap <A-k> <C-w>k
nnoremap <A-l> <C-w>l
" faster resize for buffers
nnoremap <A-J> <C-w>+
nnoremap <A-K> <C-w>-
nnoremap <A-L> <C-w>>
nnoremap <A-H> <C-w><
tnoremap <A-J> <C-\><C-n><C-w>+
tnoremap <A-K> <C-\><C-n><C-w>-
tnoremap <A-L> <C-\><C-n><C-w>>
tnoremap <A-H> <C-\><C-n><C-w><
" faster split creation/deletion
nnoremap <silent> <A--> :split<CR>
nnoremap <silent> <A-\> :vsplit<CR>
nnoremap <silent> <A-d> :bd<CR>
" change buffers
nnoremap <silent> <C-l> :bn<CR>
nnoremap <silent> <C-h> :bp<CR>
" }}}
" tabs {{{
nnoremap <silent> <A-.> :tabnext<CR>| " alt-. -> next tab
tnoremap <silent> <A-.> <C-\><C-n>:tabnext<CR>| " alt-. -> next tab (terminal mode)
nnoremap <silent> <A-,> :tabprevious<CR>| " alt-, -> prev tab
tnoremap <silent> <A-,> <C-\><C-n>:tabprevious<CR>| " alt-, -> prev tab (terminal mode)
nnoremap <silent> <A-1> :1 tabn<CR>| " alt-1 -> goes to tab 1
nnoremap <silent> <A-2> :2 tabn<CR>| " ^^
nnoremap <silent> <A-3> :3 tabn<CR>| " ^^
nnoremap <silent> <A-4> :4 tabn<CR>| " ^^
nnoremap <silent> <A-5> :5 tabn<CR>| " ^^
nnoremap <silent> <C-t> :tabnew<CR>| " ctrl-t -> new tab
" }}}
" indention mappings {{{
vnoremap <Tab> >gv| " tab indents in visual mode
vnoremap <S-Tab> <gv| " s-tab de-indents in visual mode
inoremap <S-Tab> <C-d>| " s-tab de-indents in insert mode
" }}}
" move visual lines (j,k works in traditional way) {{{
onoremap <silent> j gj
onoremap <silent> k gk
nnoremap <silent> j gj
nnoremap <silent> k gk
vnoremap <silent> j gj
vnoremap <silent> k gk
" }}}
" Master Wq bindings {{{
command! Wq wq
command! W w
command! Q q
nnoremap <silent> <C-s> :w<CR>| " ctrl-s -> save
nnoremap <silent> <C-q> :q<CR>| " ctrl-q -> quit
tnoremap <silent> <C-q> <C-\><C-n>:q<CR>| " ctrl-q -> quit (term)
" }}}
" Turkish keyboard mappings {{{
nnoremap Ş :
nnoremap ı i
nnoremap ğ [
nnoremap ü ]
nnoremap Ğ {
nnoremap Ü }
nnoremap ç .
nnoremap Ö <
nnoremap Ç >
vnoremap Ş :
vnoremap ı i
vnoremap ğ [
vnoremap ü ]
vnoremap Ğ {
vnoremap Ü }
vnoremap ç .
vnoremap Ö <
vnoremap Ç >
" }}}
" vi: foldmethod=marker
{
"name": "Vimium C",
"@time": "8/28/2024, 12:28:14 AM",
"time": 1724797694599,
"environment": {
"extension": "1.99.997",
"platform": "mac",
"firefox": 129
},
"exclusionRules": [],
"keyLayout": 2,
"keyMappings": [
"#!no-check",
"map b Vomnibar.activateTabs",
"map t Vomnibar.activateInNewTab",
"map T Vomnibar.activateEditUrlInNewTab",
"map O Vomnibar.activateEditUrl",
"map sf LinkHints.activateSearchLinkText",
"unmap <f1>",
"unmap <f2>",
""
],
"localeEncoding": "",
"searchEngines": [
"s|sp|startpage:",
"https://www.startpage.com/sp/search?abp=-1&t=device&lui=english&sc=xJgFkqH2tfCu20&cat=web&prfe=bcfd50b9911b2c8c90fe567dcc034a47c25b6bbad9d49325c02d5e7063258f5310102504f00de9c5b9f11331d7811b22555d35fa08425db6ca42cb38773906a0c08e86291a93527d8d2183e9&query=%s \\",
" blank=https://startpage.com/ Startpage",
"b|bing: https://www.bing.com/search?q=%s \\",
" blank=https://www.bing.com/ Bing",
"g|go|gg|google|Google: https://www.google.com/search?q=%s \\",
" www.google.com re=/^(?:\\.[a-z]{2,4})?\\/search\\b.*?[#&?]q=([^#&]*)/i\\",
" blank=https://www.google.com/ Google",
"b|br|brave: https://search.brave.com/search?q=%s Brave",
"d|dd|ddg|duckduckgo: https://duckduckgo.com/?q=%s DuckDuckGo",
"qw|qwant: https://www.qwant.com/?q=%s Qwant",
"y|ya|yd|yandex: https://yandex.com/search/?text=%s Yandex",
"maps|gm|gmap|gmaps: https://www.google.com/maps?q=%s \\",
" blank=https://www.google.com/maps Google Maps",
"y|yt: https://isamertiv.duckdns.org/search?q=%s \\",
" blank=https://www.youtube.com/ YouTube",
"w|wiki: https://www.wikipedia.org/w/index.php?search=%s Wikipedia",
"gh|github: https://github.com/search?q=$s \\",
" blank=https://github.com/ GitHub",
""
],
"searchUrl":
"https://www.startpage.com/sp/search?abp=-1&t=device&lui=english&sc=xJgFkqH2tfCu20&cat=web&prfe=bcfd50b9911b2c8c90fe567dcc034a47c25b6bbad9d49325c02d5e7063258f5310102504f00de9c5b9f11331d7811b22555d35fa08425db6ca42cb38773906a0c08e86291a93527d8d2183e9&query=$s Startpage",
"vimSync": true,
"vomnibarOptions": {
"actions": "",
"maxMatches": 15,
"queryInterval": 200,
"sizes": "77,3,44,0.8",
"styles": "mono-url"
}
}
Here is my sidebery config export:
{
"settings": {
"nativeScrollbars": true,
"nativeScrollbarsThin": true,
"nativeScrollbarsLeft": false,
"selWinScreenshots": false,
"updateSidebarTitle": true,
"markWindow": false,
"markWindowPreface": "[Sidebery] ",
"ctxMenuNative": false,
"ctxMenuRenderInact": true,
"ctxMenuRenderIcons": true,
"ctxMenuIgnoreContainers": "",
"navBarLayout": "vertical",
"navBarInline": true,
"navBarSide": "left",
"hideAddBtn": false,
"hideSettingsBtn": false,
"navBtnCount": true,
"hideEmptyPanels": true,
"hideDiscardedTabPanels": false,
"navActTabsPanelLeftClickAction": "none",
"navActBookmarksPanelLeftClickAction": "none",
"navTabsPanelMidClickAction": "discard",
"navBookmarksPanelMidClickAction": "none",
"navSwitchPanelsWheel": true,
"subPanelRecentlyClosedBar": true,
"subPanelBookmarks": true,
"subPanelHistory": false,
"groupLayout": "grid",
"containersSortByName": false,
"skipEmptyPanels": false,
"dndTabAct": true,
"dndTabActDelay": 750,
"dndTabActMod": "none",
"dndExp": "pointer",
"dndExpDelay": 750,
"dndExpMod": "none",
"dndOutside": "win",
"dndActTabFromLink": true,
"dndActSearchTab": true,
"dndMoveTabs": false,
"dndMoveBookmarks": false,
"searchBarMode": "dynamic",
"searchPanelSwitch": "any",
"searchBookmarksShortcut": "",
"searchHistoryShortcut": "",
"warnOnMultiTabClose": "collapsed",
"activateLastTabOnPanelSwitching": true,
"activateLastTabOnPanelSwitchingLoadedOnly": false,
"switchPanelAfterSwitchingTab": "always",
"tabRmBtn": "hover",
"activateAfterClosing": "next",
"activateAfterClosingStayInPanel": false,
"activateAfterClosingGlobal": false,
"activateAfterClosingNoFolded": true,
"activateAfterClosingNoDiscarded": false,
"askNewBookmarkPlace": true,
"tabsRmUndoNote": true,
"tabsUnreadMark": false,
"tabsUpdateMark": "all",
"tabsUpdateMarkFirst": true,
"tabsReloadLimit": 5,
"tabsReloadLimitNotif": true,
"showNewTabBtns": true,
"newTabBarPosition": "after_tabs",
"tabsPanelSwitchActMove": false,
"tabsPanelSwitchActMoveAuto": true,
"tabsUrlInTooltip": "full",
"newTabCtxReopen": false,
"tabWarmupOnHover": true,
"tabSwitchDelay": 0,
"moveNewTabPin": "start",
"moveNewTabParent": "last_child",
"moveNewTabParentActPanel": false,
"moveNewTab": "end",
"moveNewTabActivePin": "start",
"pinnedTabsPosition": "panel",
"pinnedTabsList": false,
"pinnedAutoGroup": false,
"pinnedNoUnload": true,
"pinnedForcedDiscard": false,
"tabsTree": true,
"groupOnOpen": true,
"tabsTreeLimit": 3,
"autoFoldTabs": false,
"autoFoldTabsExcept": "none",
"autoExpandTabs": false,
"autoExpandTabsOnNew": false,
"rmChildTabs": "folded",
"tabsLvlDots": true,
"discardFolded": false,
"discardFoldedDelay": 0,
"discardFoldedDelayUnit": "sec",
"tabsTreeBookmarks": true,
"treeRmOutdent": "branch",
"autoGroupOnClose": false,
"autoGroupOnClose0Lvl": false,
"autoGroupOnCloseMouseOnly": false,
"ignoreFoldedParent": false,
"showNewGroupConf": true,
"sortGroupsFirst": true,
"colorizeTabs": true,
"colorizeTabsSrc": "domain",
"colorizeTabsBranches": false,
"colorizeTabsBranchesSrc": "url",
"inheritCustomColor": true,
"previewTabs": true,
"previewTabsMode": "p",
"previewTabsPageModeFallback": "i",
"previewTabsInlineHeight": 100,
"previewTabsPopupWidth": 280,
"previewTabsSide": "right",
"previewTabsDelay": 500,
"previewTabsFollowMouse": true,
"previewTabsWinOffsetY": 36,
"previewTabsWinOffsetX": 6,
"previewTabsInPageOffsetY": 0,
"previewTabsInPageOffsetX": 0,
"previewTabsCropRight": 0,
"hideInact": false,
"hideFoldedTabs": false,
"hideFoldedParent": "none",
"nativeHighlight": false,
"warnOnMultiBookmarkDelete": "collapsed",
"autoCloseBookmarks": false,
"autoRemoveOther": false,
"highlightOpenBookmarks": false,
"activateOpenBookmarkTab": false,
"showBookmarkLen": true,
"bookmarksRmUndoNote": true,
"loadBookmarksOnDemand": true,
"pinOpenedBookmarksFolder": true,
"oldBookmarksAfterSave": "ask",
"loadHistoryOnDemand": true,
"fontSize": "s",
"animations": true,
"animationSpeed": "norm",
"theme": "plain",
"density": "default",
"colorScheme": "ff",
"sidebarCSS": false,
"groupCSS": false,
"snapNotify": true,
"snapExcludePrivate": false,
"snapInterval": 0,
"snapIntervalUnit": "min",
"snapLimit": 0,
"snapLimitUnit": "snap",
"snapAutoExport": false,
"snapAutoExportType": "json",
"snapAutoExportPath": "Sidebery/snapshot-%Y.%M.%D-%h.%m.%s",
"snapMdFullTree": false,
"hScrollAction": "switch_panels",
"onePanelSwitchPerScroll": false,
"wheelAccumulationX": true,
"wheelAccumulationY": true,
"navSwitchPanelsDelay": 128,
"scrollThroughTabs": "panel",
"scrollThroughVisibleTabs": true,
"scrollThroughTabsSkipDiscarded": false,
"scrollThroughTabsExceptOverflow": true,
"scrollThroughTabsCyclic": false,
"scrollThroughTabsScrollArea": 0,
"autoMenuMultiSel": true,
"multipleMiddleClose": false,
"longClickDelay": 500,
"wheelThreshold": false,
"wheelThresholdX": 10,
"wheelThresholdY": 60,
"tabDoubleClick": "none",
"tabsSecondClickActPrev": false,
"tabsSecondClickActPrevPanelOnly": false,
"shiftSelAct": true,
"activateOnMouseUp": false,
"tabLongLeftClick": "none",
"tabLongRightClick": "none",
"tabMiddleClick": "close",
"tabMiddleClickCtrl": "discard",
"tabMiddleClickShift": "duplicate",
"tabCloseMiddleClick": "close",
"tabsPanelLeftClickAction": "none",
"tabsPanelDoubleClickAction": "tab",
"tabsPanelRightClickAction": "menu",
"tabsPanelMiddleClickAction": "tab",
"newTabMiddleClickAction": "new_child",
"bookmarksLeftClickAction": "open_in_act",
"bookmarksLeftClickActivate": false,
"bookmarksLeftClickPos": "default",
"bookmarksMidClickAction": "open_in_new",
"bookmarksMidClickActivate": false,
"bookmarksMidClickRemove": false,
"bookmarksMidClickPos": "default",
"historyLeftClickAction": "open_in_act",
"historyLeftClickActivate": false,
"historyLeftClickPos": "default",
"historyMidClickAction": "open_in_new",
"historyMidClickActivate": false,
"historyMidClickPos": "default",
"syncName": "",
"syncSaveSettings": false,
"syncSaveCtxMenu": false,
"syncSaveStyles": false,
"syncSaveKeybindings": false,
"selectActiveTabFirst": true
},
"sidebar": {
"panels": {
"nqYWdHQS2bL0": {
"type": 2,
"id": "nqYWdHQS2bL0",
"name": "Tabs",
"color": "toolbar",
"iconSVG": "icon_tabs",
"iconIMGSrc": "",
"iconIMG": "",
"lockedPanel": false,
"skipOnSwitching": false,
"noEmpty": false,
"newTabCtx": "none",
"dropTabCtx": "none",
"moveRules": [],
"moveExcludedTo": -1,
"bookmarksFolderId": -1,
"newTabBtns": [
"Work",
"Personal"
],
"srcPanelConfig": null
},
"zkxIyW_E6AZ0": {
"type": 2,
"id": "zkxIyW_E6AZ0",
"name": "Work",
"color": "orange",
"iconSVG": "briefcase",
"iconIMGSrc": "",
"iconIMG": "",
"lockedPanel": false,
"skipOnSwitching": false,
"noEmpty": false,
"newTabCtx": "none",
"dropTabCtx": "none",
"moveRules": [],
"moveExcludedTo": -1,
"bookmarksFolderId": -1,
"newTabBtns": [
"Work"
],
"srcPanelConfig": null
},
"dmRm04pnK_B5": {
"type": 2,
"id": "dmRm04pnK_B5",
"name": "Personal",
"color": "blue",
"iconSVG": "fingerprint",
"iconIMGSrc": "",
"iconIMG": "",
"lockedPanel": false,
"skipOnSwitching": false,
"noEmpty": false,
"newTabCtx": "none",
"dropTabCtx": "none",
"moveRules": [],
"moveExcludedTo": -1,
"bookmarksFolderId": -1,
"newTabBtns": [],
"srcPanelConfig": null
},
"6pf1fzYMrrkm": {
"type": 2,
"id": "6pf1fzYMrrkm",
"name": "Static",
"color": "turquoise",
"iconSVG": "icon_clipboard",
"iconIMGSrc": "",
"iconIMG": "",
"lockedPanel": false,
"skipOnSwitching": false,
"noEmpty": false,
"newTabCtx": "none",
"dropTabCtx": "none",
"moveRules": [],
"moveExcludedTo": -1,
"bookmarksFolderId": -1,
"newTabBtns": [],
"srcPanelConfig": null
},
"KaZEk8lZmkkm": {
"type": 2,
"id": "KaZEk8lZmkkm",
"name": "Stuff",
"color": "red",
"iconSVG": "icon_code",
"iconIMGSrc": "",
"iconIMG": "",
"lockedPanel": false,
"skipOnSwitching": false,
"noEmpty": false,
"newTabCtx": "none",
"dropTabCtx": "none",
"moveRules": [],
"moveExcludedTo": -1,
"bookmarksFolderId": -1,
"newTabBtns": [],
"srcPanelConfig": null
},
"9HCG-gD6CUjm": {
"type": 2,
"id": "9HCG-gD6CUjm",
"name": "TODO",
"color": "purple",
"iconSVG": "icon_flask",
"iconIMGSrc": "",
"iconIMG": "",
"lockedPanel": false,
"skipOnSwitching": false,
"noEmpty": false,
"newTabCtx": "none",
"dropTabCtx": "none",
"moveRules": [],
"moveExcludedTo": -1,
"bookmarksFolderId": -1,
"newTabBtns": [],
"srcPanelConfig": null
},
"history": {
"type": 4,
"id": "history",
"name": "History",
"color": "toolbar",
"iconSVG": "icon_clock",
"tempMode": false,
"lockedPanel": false,
"skipOnSwitching": false,
"viewMode": "history"
}
},
"nav": [
"nqYWdHQS2bL0",
"zkxIyW_E6AZ0",
"dmRm04pnK_B5",
"6pf1fzYMrrkm",
"KaZEk8lZmkkm",
"9HCG-gD6CUjm",
"sp-0",
"history",
"remute_audio_tabs",
"add_tp",
"settings"
]
},
"ver": "5.2.0",
"keybindings": {
"_execute_sidebar_action": "F1",
"next_panel": "Alt+Period",
"prev_panel": "Alt+Comma",
"new_tab_on_panel": "MacCtrl+Space",
"new_tab_in_group": "MacCtrl+Shift+Space",
"rm_tab_on_panel": "Alt+D",
"up": "MacCtrl+Alt+K",
"down": "MacCtrl+Alt+J",
"up_shift": "Alt+Shift+Up",
"down_shift": "Alt+Shift+Down",
"activate": "Alt+Space",
"reset_selection": "Alt+R",
"fold_inact_branches": "F3",
"move_tabs_up": "Alt+Shift+K",
"move_tabs_down": "Alt+Shift+J",
"tabs_indent": "Alt+Shift+L",
"tabs_outdent": "Alt+Shift+H",
"switch_to_panel_0": "Alt+1",
"switch_to_panel_1": "Alt+2",
"switch_to_panel_2": "Alt+3",
"switch_to_panel_3": "Alt+4",
"switch_to_panel_4": "Alt+5",
"move_tabs_to_panel_0": "Alt+Shift+1",
"move_tabs_to_panel_1": "Alt+Shift+2",
"move_tabs_to_panel_2": "Alt+Shift+3",
"move_tabs_to_panel_3": "Alt+Shift+4",
"move_tabs_to_panel_4": "Alt+Shift+5",
"search": "F2",
"switch_to_next_tab": "Alt+J",
"switch_to_prev_tab": "Alt+K"
}
}
- I use Sidebery so I hide the tab bar and siderbar heading.
- I also decrease the width of “flexible space” so that it becomes something useful.
#TabsToolbar {
visibility: collapse;
}
#sidebar-header {
visibility: collapse !important;
}
#nav-bar toolbarspring {
min-width: 10px !important;
max-width: 20px !important;
}
Also need to enable following config to make userChrome.css work:
user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true);
user_pref("browser.toolbars.bookmarks.visibility", "never");
user_pref("browser.fullscreen.exit_on_escape", false)
// Don't show password suggestions from other subdomains
user_pref("signon.includeOtherSubdomainsInLookup", false);
// Enable syncing of UI customizations
user_pref("services.sync.prefs.sync.browser.uiCustomization.state", true);
// Rest is generated by https://ffprofile.com
user_pref("app.normandy.api_url", "");
user_pref("app.normandy.enabled", false);
user_pref("app.shield.optoutstudies.enabled", false);
user_pref("app.update.auto", false);
user_pref("beacon.enabled", false);
user_pref("breakpad.reportURL", "");
user_pref("browser.aboutConfig.showWarning", false);
user_pref("browser.crashReports.unsubmittedCheck.autoSubmit", false);
user_pref("browser.crashReports.unsubmittedCheck.autoSubmit2", false);
user_pref("browser.crashReports.unsubmittedCheck.enabled", false);
user_pref("browser.disableResetPrompt", true);
user_pref("browser.newtab.preload", false);
user_pref("browser.newtabpage.activity-stream.section.highlights.includePocket", false);
user_pref("browser.newtabpage.enhanced", false);
user_pref("browser.newtabpage.introShown", true);
user_pref("browser.safebrowsing.appRepURL", "");
user_pref("browser.safebrowsing.blockedURIs.enabled", false);
user_pref("browser.safebrowsing.downloads.enabled", false);
user_pref("browser.safebrowsing.downloads.remote.enabled", false);
user_pref("browser.safebrowsing.downloads.remote.url", "");
user_pref("browser.safebrowsing.enabled", false);
user_pref("browser.safebrowsing.malware.enabled", false);
user_pref("browser.safebrowsing.phishing.enabled", false);
user_pref("browser.search.suggest.enabled", false);
user_pref("browser.selfsupport.url", "");
user_pref("browser.send_pings", false);
user_pref("browser.sessionstore.privacy_level", 0);
user_pref("browser.shell.checkDefaultBrowser", false);
user_pref("browser.startup.homepage_override.mstone", "ignore");
user_pref("browser.tabs.crashReporting.sendReport", false);
user_pref("browser.urlbar.groupLabels.enabled", false);
user_pref("browser.urlbar.quicksuggest.enabled", false);
user_pref("browser.urlbar.speculativeConnect.enabled", false);
user_pref("browser.urlbar.trimURLs", false);
user_pref("datareporting.healthreport.service.enabled", false);
user_pref("datareporting.healthreport.uploadEnabled", false);
user_pref("datareporting.policy.dataSubmissionEnabled", false);
user_pref("device.sensors.ambientLight.enabled", false);
user_pref("device.sensors.enabled", false);
user_pref("device.sensors.motion.enabled", false);
user_pref("device.sensors.orientation.enabled", false);
user_pref("device.sensors.proximity.enabled", false);
user_pref("dom.battery.enabled", false);
// This breaks pasting images
// user_pref("dom.event.clipboardevents.enabled", false);
user_pref("experiments.activeExperiment", false);
user_pref("experiments.enabled", false);
user_pref("experiments.manifest.uri", "");
user_pref("experiments.supported", false);
user_pref("[email protected]", "");
user_pref("[email protected]", "");
user_pref("[email protected]", "");
user_pref("extensions.getAddons.cache.enabled", false);
user_pref("extensions.getAddons.showPane", false);
user_pref("extensions.greasemonkey.stats.optedin", false);
user_pref("extensions.greasemonkey.stats.url", "");
user_pref("extensions.pocket.enabled", false);
user_pref("extensions.shield-recipe-client.api_url", "");
user_pref("extensions.shield-recipe-client.enabled", false);
user_pref("extensions.webservice.discoverURL", "");
user_pref("media.autoplay.default", 0);
user_pref("media.autoplay.enabled", true);
user_pref("media.eme.enabled", false);
user_pref("media.gmp-widevinecdm.enabled", false);
user_pref("media.navigator.enabled", false);
user_pref("media.video_stats.enabled", false);
user_pref("network.allow-experiments", false);
user_pref("network.captive-portal-service.enabled", false);
user_pref("network.cookie.cookieBehavior", 1);
user_pref("network.dns.disablePrefetch", true);
user_pref("network.dns.disablePrefetchFromHTTPS", true);
user_pref("network.http.referer.spoofSource", true);
user_pref("network.http.speculative-parallel-limit", 0);
user_pref("network.predictor.enable-prefetch", false);
user_pref("network.predictor.enabled", false);
user_pref("network.prefetch-next", false);
user_pref("network.trr.mode", 5);
user_pref("privacy.donottrackheader.enabled", true);
user_pref("privacy.donottrackheader.value", 1);
user_pref("privacy.query_stripping", true);
user_pref("privacy.trackingprotection.cryptomining.enabled", true);
user_pref("privacy.trackingprotection.enabled", true);
user_pref("privacy.trackingprotection.fingerprinting.enabled", true);
user_pref("privacy.trackingprotection.pbmode.enabled", true);
user_pref("privacy.usercontext.about_newtab_segregation.enabled", true);
user_pref("security.ssl.disable_session_identifiers", true);
user_pref("services.sync.prefs.sync.browser.newtabpage.activity-stream.showSponsoredTopSite", false);
user_pref("signon.autofillForms", false);
user_pref("toolkit.telemetry.archive.enabled", false);
user_pref("toolkit.telemetry.bhrPing.enabled", false);
user_pref("toolkit.telemetry.cachedClientID", "");
user_pref("toolkit.telemetry.enabled", false);
user_pref("toolkit.telemetry.firstShutdownPing.enabled", false);
user_pref("toolkit.telemetry.hybridContent.enabled", false);
user_pref("toolkit.telemetry.newProfilePing.enabled", false);
user_pref("toolkit.telemetry.prompted", 2);
user_pref("toolkit.telemetry.rejected", true);
user_pref("toolkit.telemetry.reportingpolicy.firstRun", false);
user_pref("toolkit.telemetry.server", "");
user_pref("toolkit.telemetry.shutdownPingSender.enabled", false);
user_pref("toolkit.telemetry.unified", false);
user_pref("toolkit.telemetry.unifiedIsOptIn", false);
user_pref("toolkit.telemetry.updatePing.enabled", false);
user_pref("webgl.renderer-string-override", " ");
user_pref("webgl.vendor-string-override", " ");
I filter distracting content on websites I frequently visit. You need to manually import these to uBlock.
Enabling uBlock cloud storage feature may help.
! youtube.com
www.youtube.com##ytd-watch-next-secondary-results-renderer.ytd-watch-flexy.style-scope > .ytd-watch-next-secondary-results-renderer.style-scope
www.youtube.com##ytd-rich-section-renderer.ytd-rich-grid-renderer.style-scope
www.youtube.com###shorts-container
www.youtube.com##ytd-reel-shelf-renderer.ytd-item-section-renderer.style-scope
! stack-exchange
##.tex2jax_ignore.module
##.m0.p0.d-block
##.overflow-hidden.blr-sm.fc-black-600.pb6.p12.bc-black-075.bb.bl.bt
##.js-sticky-leftnav.left-sidebar--sticky-container
##.js-dismissable-hero.ps-relative.fc-black-200.bg-black-750.py24.sm\:d-none
##.py2.fs-body2.ff-sans.fc-white.bg-black-700.js-announcement-banner
##.js-footer.site-footer
stackoverflow.com##.js-footer.site-footer
! https://eksisozluk.com
eksisozluk.com###partial-index
eksisozluk.com###aside
eksisozluk.com###bgright
eksisozluk.com###rightwrap
eksisozluk.com##.main-left-frame.robots-nocontent
||seyler.eksisozluk.com/sozluk/baslik/294386?style=dark$subdocument
c.content.blocking.adblock.lists = ['https://easylist.to/easylist/easylist.txt', 'https://easylist.to/easylist/easyprivacy.txt']
c.content.blocking.method = 'both'
c.content.blocking.enabled = True
c.content.pdfjs = True
c.fonts.default_family = ['Iosevka Nerd Font']
c.fonts.default_size = '14pt'
c.hints.chars = 'asdfghjklqweuio'
c.fonts.hints = 'normal 16pt Helvetica'
c.hints.uppercase = True
c.input.insert_mode.auto_load = True
c.input.mouse.rocker_gestures = True
c.statusbar.position = 'top'
c.statusbar.show = 'never'
c.completion.shrink = True
c.url.default_page = 'https://start.duckduckgo.com/'
c.url.searchengines = {
'DEFAULT': 'https://google.com/search?q={}',
'g': 'https://google.com/search?q={}',
'd': 'https://duckduckgo.com/?q={}',
'yt': 'https://www.youtube.com/results?search_query={}',
'r': 'https://reddit.com/r/{}',
'a': 'https://web.archive.org/web/{}',
'nix': 'https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query={}',
}
c.url.yank_ignored_parameters = ['ref', 'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content']
c.editor.command = ['emacsclient', '-c', '{}']
c.fonts.hints = 'normal 16pt Helvetica'
c.window.hide_decoration = True
config.bind('t', 'cmd-set-text -s :open -t')
config.bind('T', 'cmd-set-text :open -t -r {url:pretty}')
config.bind('O', 'cmd-set-text :open {url:pretty}')
config.bind('b', 'cmd-set-text -sr :tab-focus')
config.bind('B', 'cmd-set-text -s :quickmark-load -t')
config.bind('j', 'scroll-px 0 200')
config.bind('k', 'scroll-px 0 -200')
config.bind('J', 'tab-next')
config.bind('K', 'tab-prev')
config.bind('<Alt-J>', 'tab-move -')
config.bind('<Alt-K>', 'tab-move +')
config.bind('<Alt-x>', 'cmd-set-text :')
config.bind(',m', 'spawn mpv {url}')
config.bind(',M', 'hint links spawn mpv {hint-url}')
config.bind(';i', 'hint images tab')
config.bind(';I', 'hint images yank')
# Ctrl-E is the go-to EOL binding and I don't want qutebrowser to
# override it
config.unbind('<Ctrl-E>', mode='insert')
config.bind('<Alt-A>', 'edit-text', mode='insert')
config.bind('<Alt-E>', 'edit-text', mode='insert')
c.content.blocking.whitelist = ['https://*.trendyol.com']
config.bind('P', 'spawn --userscript org-pass')
c.aliases = {
'w': 'session-save',
'q': 'close',
'qa': 'quit',
'wq': 'quit --save',
'wqa': 'quit --save',
}
config.load_autoconfig(False)
[Desktop Entry]
Name=jaro
GenericName=Resource opener
Terminal=false
Exec=jaro %F
Type=Application
Categories=Utility;
This part is almost completely untouched. Needs some revamp.
Run PARAM=VALUE
for every parameter passed as --param=value
. Dashes are converted into underscores before doing the assignment. As an example, if your script is called like ./script --param1=value --param-2=value2
then you’ll have PARAM1
variable set to value
and PARAM_2
variable set to VALUE2
inside your script.
while [[ $# -gt 0 ]]; do
case $1 in
--*)
TMP_ARG=${1#--}
TMP_ARG=${TMP_ARG%=*}
TMP_ARG=${TMP_ARG//-/_}
TMP_VAL=${1#*=}
declare "${TMP_ARG^^}"="$TMP_VAL"
;;
esac
shift
done
Shorten given url. To make this work:
- I simply created a firebase application.
- Added my domain to it (from “Build → Hosting” menu). I used a subdomain, like “urlshortener.mydomain.com”. You’ll see the why in a minute.
- Installed firebase cli application
yarn global add "firebase-tools"
- Configured my project with firebase-tools.
firebase login
firebase projects:list
→ Just to check if it works or notfirebase init
→ Select “Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploy”.- Here is the firebase.json that I use which rewrites all requests to your domain with the ones provided by “Dynamic Links” application. So it’s wise use a subdomain for this application as I outlined above.
{ "hosting": { // Following two lines are the important ones "appAssociation": "AUTO", "rewrites": [ { "source": "/**", "dynamicLinks": true } ], "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ] } }
- Then you may need to open “Engage → Dynamic Links” page and click to “Get Started”. Select your domain from the list and finish it.
#!/bin/bash
set -eo pipefail
case "$1" in
-h|--help)
echo "Usage:"
echo " $(basename "$0") URL"
echo " some-command-that-outputs-a-long-url | $(basename "$0")"
exit
;;
esac
URL=$(echo "${1:-$(</dev/stdin)}" | xargs)
curl \
--silent \
-H 'Content-Type: application/json' \
-d '{"dynamicLinkInfo":{"domainUriPrefix":"'$FIREBASE_URL_SHORTENER_PREFIX'","link":"'$URL'",},"suffix":{"option":"SHORT"}}' \
"https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=$FIREBASE_WEB_API_KEY" \
| jq -r '.shortLink' | tee >(xcopy)
Uploads given file to a predetermined folder in your box.com
account and returns you a public download link for the file.
Need to install boxcli
for this to work.
- You need to create an application on box.com first.
- Go figure out in the developer console.
- Select
User Authentication (OAuth 2.0)
for your application. It works well with box cli. - Go to your application page, go to “Configuration” and select “Write all files and folders stored in Box” to give write permissions.
yarn global add "@box/cli"
box login
The variable BOX_UPLOAD_DIR
is defined in ~/.extrarc
(I don’t upload this file as it contains personal information). This variable simply holds the id of a folder you’ve created in box.com
. You can list all folders in your root by issuing this command: box folders:items 0
. Then copy the folder id that you want your files to be uploaded and set this variable. I use this script for being able to quickly share files with people, I don’t do complex uploads with it, so all files under one folder suffices my needs.
#!/bin/bash
set -eo pipefail
FILE=$1
FILE_ID=$(box files:upload --id-only "$FILE" --parent-id "$BOX_UPLOAD_DIR")
box shared-links:create --json "$FILE_ID" file | jq -j '.url' | tee >(xcopy)
#!/bin/bash
# This whole script is based on the fact that I'm not that retard to
# listen/watch more than one audio/video streams at the same time.
# If I do, I'll get punished for that sin.
MPV_SOCKET=/tmp/mpvsocket
mpv_pause() {
echo '{ "command": ["set_property", "pause", true] }' | socat - "$MPV_SOCKET"
}
mpv_toggle() {
echo '{"command": ["cycle", "pause"]}' | socat - "$MPV_SOCKET"
}
mpv_seek() {
if [[ $1 == *% ]]; then # seek $1 percent
echo 'percent'
echo '{"command": ["seek", "'"${1%\%}"'", "relative-percent"]}' | socat - "$MPV_SOCKET"
else # seek $1 seconds
echo '{"command": ["seek", "'"$1"'"]}' | socat - "$MPV_SOCKET"
fi
}
# TODO: somehow pause videos/audios playing in firefox/qutebrowser
all_pause() {
mpv_pause
mpc pause
}
all_toggle() {
# Give priority to mpv
if pgrep mpv; then
mpv_toggle
else
mpc toggle
fi
}
all_seek() {
if pgrep mpv; then
mpv_seek "$@"
else
mpc seek "$@"
fi
}
get_sink_name_from_sink_id() {
local ids="${1:-$(</dev/stdin)}"
echo "$ids" | while read -r id; do
echo "($id) $(pactl list sinks | grep -E "(Sink #$id)|(device.description)" | grep -A1 "Sink #$id" | sed -n "2p" | cut -d'"' -f2)"
done
}
switch_audio_channel() {
if [[ $1 = "--help" ]]; then
echo "Changes default sink to next one and moves all inputs to new default sink."
echo "Try to use it when something is already playing."
fi
readarray -t sinks <<< "$(pactl list sinks short | cut -f1)"
readarray -t inputs <<< "$(pactl list sink-inputs short | cut -f1)"
current_sink=$(pactl list sinks short | grep "RUNNING" | head -c 1)
if [[ -z $current_sink ]]; then
notify-send "Error while switching audio channels" "Could not detect default sink. Playing something may help."
exit 1
fi
if [[ $1 = --interactive ]]; then
new_sink=$(printf "%s\n" "${sinks[@]}" | get_sink_name_from_sink_id | rofi -dmenu | grep -Po "\(\K[0-9]*")
else
new_sink=${sinks[0]}
for sink in "${sinks[@]}"; do
if (( sink > current_sink )); then
new_sink="$sink"
break
fi
done
fi
[[ -z $new_sink ]] && exit;
notify-send "Switching audio channel" "New default channel is $(get_sink_name_from_sink_id $new_sink), moving all inputs to that."
# Move every input to new sink
for input in "${inputs[@]}"; do
pacmd move-sink-input "$input" "$new_sink"
done
# Make new sink the default
pactl set-default-sink "$new_sink"
}
# Get the movie name from file/folder name and find the imdb-id
find_imdb_id_from_filename() {
MOVIE_NAME=$(echo "$@" | sed -r 's/((\w{1,}[-. ]?)*?)(\(?[0-9]{4}\)?[. -]).*/\1\3/; s/[.()-]/ /g; s/ / /g')
curl 'https://searx.prvcy.eu/search' \
--data-urlencode "q=$MOVIE_NAME" \
--data-urlencode 'language=en-US' \
--data-urlencode 'format=csv' \
--silent \
| grep -oP 'imdb.com/title/\K\w+' -m 1
}
mpv_subdl() {
MPV_SOCKET=/tmp/mpvsocket
file_path=$1
language=$2
sub_file_path="${file_path%.*}.srt"
# First try if there is a zip/rar file that has been downloaded in last 5 mins
# if so try to extract it
SUB_FILE=$(find ~/Downloads -cmin -5 | grep -E '(rar|zip)')
if [[ -n $SUB_FILE ]]; then
if sub-extract --no-confirm --auto "$SUB_FILE"; then
echo 'show-text "Subtitle EXTRACTED from ~/Downloads."' | socat - $MPV_SOCKET
echo "sub-add \"$sub_file_path\"" | socat - $MPV_SOCKET
exit
else
echo 'show-text "Failed to extract, trying to download."' | socat - $MPV_SOCKET
sleep 2
fi
fi
# Now try `subdl`
echo 'show-text "Downloading subtitle with subdl..."' | socat - $MPV_SOCKET
if subdl --lang="$language" "$file_path"; then
echo 'show-text "Subtitle downloaded."' | socat - $MPV_SOCKET
echo "sub-add \"$sub_file_path\"" | socat - $MPV_SOCKET
else
IMDB_ID=$(find_imdb_id_from_filename "$file_path")
echo "show-text \"Failed! Trying for $IMDB_ID.\"" | socat - $MPV_SOCKET
if subdl --lang="$language" --imdb-id="$IMDB_ID" --force-imdb --download=best-rating "$file_path"; then
echo 'show-text "Alternative method worked!"' | socat - $MPV_SOCKET
echo "sub-add \"$sub_file_path\"" | socat - $MPV_SOCKET
exit
fi
fi
# Try `subliminal`
echo 'show-text "Downloading subtitle with subliminal..."' | socat - $MPV_SOCKET
SUBLIMINAL_OUTPUT=$(subliminal download -l "$language")
if [[ -n $(echo $SUBLIMINAL_OUTPUT | sed -nr '/Downloaded [1-9] subtitle/p') ]]; then
# Load all srt files into mpv, subliminal does not output the srt name
for srt in ./*.srt; do
echo "sub-add \"$srt\"" | socat - $MPV_SOCKET
done
echo 'show-text "Subtitle downloaded with subliminal."' | socat - $MPV_SOCKET
exit
fi
}
opt=$1; shift
case "$opt" in
*help) echo "mediastuff [mpv-(subdl|toggle|pause|seek)|all-(toggle|pause|seek)|switch-audio-channel|connect-bt-headphones|find-imdb]" ;;
mpv*toggle) mpv_toggle "$@" ;;
mpv*pause) mpv_pause "$@" ;;
mpv*seek) mpv_seek "$@" ;;
all*toggle) all_toggle "$@" ;;
all*pause) all_pause "$@" ;;
all*seek) all_seek "$@" ;;
switch*audio*channel) switch_audio_channel "$@" ;;
connect*bt*headphones) connect_bt_headphones "$@" ;;
mpv*subdl) mpv_subdl "$@" ;;
find*imdb) find_imdb_id_from_filename "$@" ;;
esac
#!/bin/bash
function trim {
local var="${*:-$(</dev/stdin)}"
var="${var#"${var%%[![:space:]]*}"}"
var="${var%"${var##*[![:space:]]}"}"
echo -n "$var"
}
function dmenu {
rofi -dmenu -fuzzy -i "$@"
}
function files {
f=$( ( git --git-dir="$HOME"/.dotfiles/ --work-tree="$HOME" ls-files; fd . --no-ignore-vcs --color=never --max-depth=5 ) | dmenu)
if [[ "$1" == "--open" ]] && [[ -n "$f" ]]; then
jaro "$f"
else
echo "$f"
fi
}
function folders {
f=$(fd . "$HOME" --no-ignore-vcs --color=never --type=d --max-depth=5 | dmenu)
if [[ "$1" == "--open" ]] && [[ -n "$f" ]]; then
jaro "$f"
else
echo "$f"
fi
}
function file_contents {
term --float -e /bin/sh -c "fuzzy file-contents Documents \$(git --git-dir="$HOME"/.dotfiles/ --work-tree="$HOME" ls-files --full-name)"
}
function bookmarks {
grep -E '^*' ~/Documents/notes/bookmarks.org | grep '\[\[' | sed -E 's/\[\[(.*)\]\[(.*)\]\]/\2 <span foreground="grey" size="small">\1<\/span>/; s/\**//' | dmenu -i -markup-rows | grep -Eo 'https?://[^ ]+' | sed 's/<\/span>//' | jaro
}
cmd="$1"
shift
case $cmd in
*help) echo "menu [files|folders|file-contents|passwords]";;
files) files "$@";;
folders) folders "$@";;
file*contents) file_contents "$@";;
bookmarks) bookmarks "$@";;
calc*) rofi -show calc -modi calc -no-show-match -no-sort ;;
*) rofi -show combi "$@" ;;
esac
#!/bin/python
import os
import sys
def extract_auto():
""" Automatically find the movie and extract SUB_ARCHIVE with proper name """
movies = get_movies()
movies_normalized = list(enumerate(map(normalize, movies)))
movie_index, _ = max(movies_normalized, key=lambda tup: matches(tup[1]))
movie_full_path = movies[movie_index]
extract(movie_full_path)
def extract_interactive():
import subprocess
selected_movie = subprocess \
.run(['/bin/sh', '-c', 'echo -n "' + '\n'.join(get_movies()) + '" | fzf --header="Subtitle name: '+ SUB_ARCHIVE +'" --preview=""'], stdout=subprocess.PIPE) \
.stdout.decode('utf-8') \
.strip()
if selected_movie != "":
extract(selected_movie)
def extract(movie_full_path):
""" Extract sub file from SUB_ARCHIVE """
srt_full_path = mk_srt_path(movie_full_path)
srt_archive_ext = os.path.splitext(SUB_ARCHIVE)[1]
print("Given sub file: " + SUB_ARCHIVE)
print("Movie: " + movie_full_path)
print("Sub : " + srt_full_path)
yn = 'y' if NOCONFIRM else input("y/n? ")
if yn != 'y':
exit(1)
if srt_archive_ext == ".zip":
import zipfile
with zipfile.ZipFile(SUB_ARCHIVE) as z:
# Just take the first srt file
srt_file = list(filter(lambda f: ".srt" in f, [file_info.filename for file_info in z.filelist]))[0]
with open(srt_full_path, 'wb') as f:
f.write(z.read(srt_file))
elif srt_archive_ext == ".rar":
import rarfile
with rarfile.RarFile(SUB_ARCHIVE) as z:
# Just take the first srt file
srt_file = list(filter(lambda f: ".srt" in f, z.namelist()))[0]
with open(srt_full_path, 'wb') as f:
f.write(z.read(srt_file))
else:
print("wut? (for now)")
print("Done.")
# #############################################################################
# Utility functions
# #############################################################################
def get_movies():
movie_exts = [".mkv", ".mp4", ".avi"]
movies = []
for movie_dir in MOVIE_DIRS:
for root, _, fs in os.walk(movie_dir):
for f in fs:
name, ext = os.path.splitext(os.path.basename(f))
# Skip non-movie files and sample files
# (and hope the movie name does not contain "sample")
if ext in movie_exts and not "sample" in name.lower():
movies.append(os.path.join(root, f))
return movies
def mk_srt_path(movie_full_path):
""" Replace movie extension with .srt """
return os.path.splitext(movie_full_path)[0] + ".srt"
def normalize(s):
# 1080p, 720p etc makes matching harder because sometimes the downloaded
# subtitle has different resolution spec
return s.lower() \
.replace("-", " ") \
.replace(".", " ") \
.replace("_", " ") \
.replace("1080p", "") \
.replace("720p", "") \
.replace("bdrip", "") \
.replace("blueray", "") \
.replace("x264", "")
def matches(text):
return sum(word in text for word in SUB_NAME)
# #############################################################################
# Here we go
# #############################################################################
SUB_ARCHIVE = sys.argv[-1]
SUB_NAME = normalize(SUB_ARCHIVE).split()
MOVIE_DIRS = [os.path.expanduser("~/Videos")]
NOCONFIRM = "--no-confirm" in sys.argv
if "--movie_dirs" in sys.argv:
arg_index = sys.argv.index("--movie_dirs")
MOVIE_DIRS = sys.argv[arg_index + 1].split(",")
MOVIE_DIRS = [os.path.expanduser(x.strip()) for x in MOVIE_DIRS]
for mdir in MOVIE_DIRS:
if not os.path.exists(mdir):
print("Movie directory does not exist: " + mdir)
exit(1)
if "--help" in sys.argv:
print("sub-extract [--(interactive|auto)] [--noconfirm] [--help] archive-file")
print("This program extracts a subtitle file from an archive file into the selected movie folder.")
print("")
print("\t--auto")
print("\t\tAutomatically matches the sub file with the movie using some heuristics. (Default)")
print("\t--interactive")
print("\t\tOpen fzf to find matching movie file.")
print("\t--no-confirm")
print("\t\tDo not ask for user consent and automatically copy the sub file.")
print("\t--movie-dirs")
print("\t\tA comma separated list of movie directories that you want to be searched. (Default: ~/Videos)")
print("\t\tExample: sub-extract --movie-dirs ~/Movies,~/Shows")
elif os.path.exists(SUB_ARCHIVE):
if "--auto" in sys.argv and "--interactive" not in sys.argv:
extract_auto()
elif "--interactive" in sys.argv and "--auto" not in sys.argv:
extract_interactive()
else:
print("File not found: " + SUB_ARCHIVE)
print("Archive path should be the last argument.")
#!/bin/bash
# When using st, it expects window class properties while urxvt expects
# window name properties for enabling floating windows. So
# Rule for urxvt:
# bspc rule --add '*:float' state=floating
# Rule for st:
# bspc rule --add 'float' state=floating
# st, urxvt, urxvtc, alacritty
RUNNER='alacritty'
FLOAT=''
OPAQUE=''
GEOMETRY=''
TITLE=''
OPTS=()
for arg; do
case "$arg" in
"--term="*) RUNNER=${arg#*=}; shift ;;
"--title="*) TITLE=${arg#*=}; shift ;;
"--geometry="*) GEOMETRY=${arg#*=}; shift ;;
"--float") FLOAT='1'; shift ;;
"--opaque") OPAQUE='1'; shift ;;
"--tophalf") TOPHALF='1'; shift ;;
esac
done
if [[ $RUNNER == 'urxvtc' ]]; then
if ! pgrep urxvtd; then
urxvtd & disown
sleep 0.5
fi
fi
if [[ -n "$FLOAT" ]]; then
case "$RUNNER" in
"st") OPTS+=(-c float) ;;
"urxvt"*) OPTS+=(-name float) ;;
"alacritty") OPTS+=(--class float) ;;
esac
fi
if [[ -n "$TOPHALF" ]]; then
case "$RUNNER" in
"st") OPTS+=(-c tophalf) ;;
"urxvt"*) OPTS+=(-name tophalf) ;;
"alacritty") OPTS+=(--class tophalf) ;;
esac
fi
if [[ -n "$TITLE" ]]; then
case "$RUNNER" in
"st") OPTS+=(-t "$TITLE") ;;
"urxvt"*) OPTS+=(-name "$TITLE") ;;
"alacritty") OPTS+=(--title "$TITLE") ;;
esac
fi
if [[ -n "$OPAQUE" ]]; then
case "$RUNNER" in
"st") OPTS+=(-A 1) ;;
"urxvt"*) OPTS+=(-bg "$(xrdb-get-value '*background')") ;;
"alacritty") OPTS+=(--option background_opacity=1) ;;
esac
fi
if [[ -n "$GEOMETRY" ]]; then
case "$RUNNER" in
"st"|"urxvt"*) OPTS+=(-g "$GEOMETRY") ;;
"alacritty")
echo "Not supported"
# TODO: Use bspwm rules for geometry
;;
esac
fi
echo "${OPTS[@]}"
$RUNNER "${OPTS[@]}" "$@"
#!/bin/bash
in_file="$1"
out_file="$2"
height_px=512
start_sec=00
end_sec=59
color_count=256
framerate=15
for i in "$@"; do
case $i in
-i=*|--input=*) in_file="${i#*=}"; shift ;;
-o=*|--output=*) out_file="${i#*=}"; shift ;;
-h=*|--height=*) height_px="${i#*=}"; shift ;;
-s=*|--start=*) start_sec="${i#*=}"; shift ;;
-e=*|--end=*) end_sec="${i#*=}"; shift ;;
-c=*|--color=*) color_count="${i#*=}"; shift ;;
-r=*|--framerate=*) framerate="${i#*=}"; shift ;;
esac
done
if [ $1 = "help" ] || [ $1 = "--help" ] || [ $1 = "-h" ] || [ $1 = "" ]; then
echo -e "togif in_file out_file [OPTION...]\n"
echo -e "OPTIONS"
echo -e "\t-i FILE, --input=FILE\n"
echo -e "\t-o FILE, --output=FILE\n"
echo -e "\t-h HEIGHT, --height=HEIGHT"
echo -e "\t\tWidth will be scaled according to given HEIGHT. Default: 512\n"
echo -e "\t-s SEC, --start=SEC"
echo -e "\t\tStarts the video from given SEC. Default: 00\n"
echo -e "\t-e SEC, --end=SEC"
echo -e "\t\tEnds the video at the given SEC. Default: 59\n"
echo -e "\t-c COUNT, --color=COUNT"
echo -e "\t\tReduce the color palette to COUNT colors. (If it's lower already, does nothing.) (Only works for gif outputs) Default: 256\n"
echo -e "\t-r COUNT, --framerate=COUNT"
echo -e "\t\tReduce videos framerate to COUNT. Default: 15"
else
echo "=== CONVERTING ==="
ffmpeg \
-i "$in_file" \
-r $framerate \
-vf scale=$height_px:-1 \
-ss 00:00:$start_sec -to 00:00:$end_sec \
"$out_file"
convert_result=$?
echo "=== DONE ==="
# Optimize if it's a gif
if [[ $convert_result == 0 ]] && [[ "$out_file" == *.gif ]]; then
echo ""
echo "=== OPTIMIZING ==="
gifsicle -i "$out_file" --optimize=3 --colors $color_count -o "${out_file}_optimized"
rm "$out_file"
mv "${out_file}_optimized" "$out_file"
echo "=== DONE ==="
fi
fi
#!/bin/bash
# When a job that is called with tsp finishes, this script is called.
# Need to set $TS_ONFINISH variable to path of this script. (See ~/.profile)
job_id="$1"
err="$2"
out_file="$3"
cmd="$4"
remaining_job_count=$(($(tsp | tail -n +2 | grep -cvE '^[0-9]+ +finished') - 1))
if [[ "$err" = 0 ]]; then
icon=terminal
title="finished"
duration=5
else
icon=error
title="failed"
duration=10
# Put cmd into clipboard
echo "$cmd" | xclip -selection clipboard
fi
notify-send \
-i "$icon" \
-t $((duration*1000))\
"[TSP] job $title (remaining: $remaining_job_count)" \
"$cmd"
#!/bin/sh
file="$1"
input="$*"
if which xclip &>/dev/null; then
CLIP_CMD="xclip -selection clipboard"
elif which pbcopy &>/dev/null; then
CLIP_CMD="pbcopy"
else
echo "Install xclip."
exit 1
fi
if [[ -f "$file" ]]; then
if [[ CLIP_CMD = "pbcopy" ]]; then
echo "Not supported by pbcopy."
exit 1
fi
xclip -selection clipboard -t "$(file -b --mime-type "$file")" -i "$file"
elif [[ -z "$input" ]]; then
$CLIP_CMD <&0
else
printf "$input" | "$CLIP_CMD"
fi
Downloads given file in given folder with given name. Useful for adding keybindings in browsers etc.
#!/bin/bash
«bash-initialize-variables»
URL=${URL-$(zenity --entry --text="Enter url to download:")}
FILE_NAME=${FILE_NAME-$(zenity --entry --text="Enter file name (without extension).")}
SAVE_PATH=${SAVE_PATH-$(zenity --entry --text="Where to save?" --entry-text="${HOME}/")}
cd "${SAVE_PATH}" || exit
if [[ -n "$FILE_NAME" ]]; then
youtube-dl --no-mtime --output "$FILE_NAME.%(ext)s" "$URL"
else
youtube-dl --no-mtime "$URL"
fi
echo -n "$(pwd)/$(/bin/ls -tr | tail -n 1)" | xcopy
notify-send "Download finished!" "File path copied to your clipboard."
#!/bin/bash
# Source: https://askubuntu.com/questions/1308613/how-to-remove-slightly-modified-duplicate-images
if [[ $1 = "--help" ]] || [[ $1 = "-h" ]]; then
echo "Find duplicate images in current directory. Images are compared WITHOUT the metadata."
echo "It lists duplicate files. You need to delete them manually."
echo
echo "USAGE:"
echo " find-duplicate-images"
exit
fi
echo "Scanning images... This may take some time..."
find -type f -a '(' \
-iname '*.jpg' -o \
-iname '*.png' -o \
-iname '*.jpeg' -o \
-iname '*.mov' -o \
-iname '*.mpg' -o \
-iname '*.mpeg' -o \
-iname '*.avi' \
')' -print0 |perl -n0e '
my $f = $_;
chomp($f);
(my $fe = $f) =~ s|\x27|\x27\\\x27\x27|g;
my $md5;
if($f =~ m|\.[aA][vV][iI]$| or $f =~ m|\.[mM][pP][gG]$|) {
$md5 = `cat \x27$fe\x27 |md5sum`;
} else {
$md5 = `exiftool \x27$fe\x27 -all= -o - |md5sum`;
}
chomp($md5); $md5 =~ s| +-\n||;
print("$md5 $f\n");
' | sort | uniq --check-chars=32 --all-repeated
#!/usr/bin/env ruby
require 'net/http'
require 'uri'
require 'json'
CONDITIONS = {
"A" => "Açık",
"AB" => "Az Bulutlu",
"PB" => "Parçalı Bulutlu",
"CB" => "Çok Bulutlu",
"HY" => "Hafif Yağmurlu",
"Y" => "Yağmurlu",
"KY" => "Kuvvetli Yağmurlu",
"KKY" => "Karla Karışık Yağmurlu",
"HKY" => "Hafif Kar Yağışlı",
"K" => "Kar Yağışlı",
"YKY" => "Yoğun Kar Yağışlı",
"HSY" => "Hafif Sağanak Yağışlı",
"SY" => "Sağanak Yağışlı",
"KSY" => "Kuvvetli Sağanak Yağışlı",
"MSY" => "Mevzi Sağanak Yağışlı",
"DY" => "Dolu",
"GSY" => "Gökgürültülü Sağanak Yağışlı",
"KGY" => "Kuvvetli Gökgürültülü Sağanak Yağışlı",
"SIS" => "Sisli",
"PUS" => "Puslu",
"DMN" => "Dumanlı",
"KF" => "Kum veya Toz Taşınımı",
"R" => "Rüzgarlı",
"GKR" => "Güneyli Kuvvetli Rüzgar",
"KKR" => "Kuzeyli Kuvvetli Rüzgar",
"SCK" => "Sıcak",
"SGK" => "Soğuk",
"HHY" => "Yağışlı"
}
def fetch_data(url, params)
uri = URI(url)
uri.query = URI.encode_www_form(params)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri.request_uri)
request['Origin'] = 'https://mgm.gov.tr'
request['Host'] = 'mgm.gov.tr'
request['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
http.request(request)
response = http.request(request)
return JSON.parse(response.body)
end
if ARGV.empty?
puts "Usage: mgm SEHIR"
exit 1
end
merkez = fetch_data('https://servis.mgm.gov.tr/web/merkezler', { il: ARGV.first })[0]
durum = fetch_data("https://servis.mgm.gov.tr/web/sondurumlar", { merkezid: merkez["merkezId"] })[0]
puts <<-HERE
Hadise :: #{CONDITIONS[durum["hadiseKodu"]]}
Sicaklik :: #{durum["sicaklik"]} °C
Nem :: #{durum["nem"]}%
Yagmur olasiligi :: #{durum["yagis00Now"]}%
HERE
#!/bin/bash
# TODO: Create an emacs wrapper which fuzzy searches through these
# results and opens the file on that revision using
# (vc-revision-other-window REV)
case "$1" in
-h|--help)
echo "Search STRING in all revisions of given FILE."
echo
echo "Usage:"
echo "git-file-hist-grep STRING FILE"
;;
*)
SEARCH_STRING=$1
FILE_NAME=$2
git rev-list --all "$FILE_NAME" | while read REVISION; do
git --no-pager grep -F "$SEARCH_STRING" "$REVISION" "$FILE_NAME"
done
;;
esac
dconf-editor
- List and explore gnome/gshell/app settings.
d-feet
- List and explore running dbus instances.
peek
- Screen recorder (records gifs etc.)
tokei
- CLOC (count lines of code)
subdl
- dowload subtitles from opensubtitles.org
socat
- needed for communicating with mpv trough unix sockets
entr
- Listen/subscribe to file changes. (linux)
fswatch
- Listen/subscribe to file changes. (cross-platform)
- fswatch -o src/main | xargs -n1 ./mvnw compile
-o
one per batch
- fswatch -o src/main | xargs -n1 ./mvnw compile
To be able to access my personal computer while I’m on my work computer (or vice-versa) without needing to physically switch keyboards, I use barrier. See here for detailed configuration documentation.
section: screens
trendyol:
x220:
end
section: aliases
end
section: links
trendyol:
right = x220
x220:
left = trendyol
end
section: options
screenSaverSync = true
clipboardSharing = true
keystroke(alt+BracketL) = switchToScreen(trendyol)
keystroke(alt+BracketR) = switchToScreen(x220)
end
- The following thing automatically loads the code necessary when this file is opened.
- This basically makes use of file local variables.
- It also changes
org-babel-noweb-wrap-{start,end}
variables so that when noweb references are used inside sh/bash blocks, it does not mess up the code highlighting. You need to use«ref»
instead of<<ref>>
to include noweb references inside code blocks.