Mouseless Workflow (WIP)


These are my dotfiles. Some are pretty heavily commented. If you have interest in tui/cli programs, keyboard-based programs, keyboard ergonomics, colemak, vim, and/or emacs, this repo may be of some use. It’s still kind of a mess, and some things really need to be cleaned up or updated (e.g. my config for bspwm here won’t work for the latest version). Feel free to make an issue if you have an comments, questions, or suggestions.

  • Table of Contents
  • [[#pictures][Pictures]]
  • [[#summary][Summary]]
  • [[#why-the-keyboard][Why the Keyboard?]]
  • [[#why-emacs][Why Emacs?]]
  • [[#programs][Programs]]
  • [[#working-on][Working On]]
  • [[#cool-things-i-stole][Cool Things I Stole]]
  • [[#interesting-workflow-excerpts][Interesting Workflow Excerpts]]
    • [[#make-any-terminal-emulator-dropdown-regardless-of-wm][Make Any Terminal Emulator Dropdown Regardless of WM]]
    • [[#consolidate-bspwm-resizing-keybindings][Consolidate Bspwm Resizing Keybindings]]
    • [[#empty-desktop-keybindings][Empty Desktop Keybindings]]
    • [[#use-ranger-instead-of-default-gui-popup-for-file-saving][Use Ranger Instead of Default GUI Popup for File Saving]]
    • [[#block-layout-in-emacsvim-and-examples-of-context-dependent-keybindings][Block Layout in Emacs/Vim and Examples of Context-dependent Keybindings]]
    • [[#stream-any-video-in-mpv][Stream Any Video in MPV]]
    • [[#make-gifswebms-in-mpv][Make Gifs/Webms in MPV]]
    • [[#home-row-window-mangement][Home Row Window Mangement]]
    • [[#create-a-modal-interface-for-programs-that-dont-support-rebinding][Create a Modal Interface for Programs That Don’t Support Rebinding]]
  • [[#credit][Credit]]

I have some notes on software related to aesthetics (e.g. compton and conky) [[./aesthetics/][here]]. [[./browsing/][Here]] are some notes on browser-related software (e.g. pentadactyl and vimperator). I’ll eventually add my notes on vim, emacs, and text editing [[./emacs/.emacs.d/][here]] and my notes on keyboards, keyboard layouts, and keybindings/remappings [[./remap/][here]].

Also see [[][my blog]] if you’re interested.

Some resources from others: - [[][stevep99’s Colemak Mod-DH (Dvbg/Hm swap)]] - [[][Tarmak - Colemak transitional layouts]]

  • Pictures #+CAPTION: Words of Wisdom [[./keyboard_ftw.gif]]

See [[./aesthetics/][aesthetics/]] for more info on theming, panels, etc.

#+CAPTION: Clean Desktop [[./clean.png]]

#+CAPTION: Unclean Desktop [[./dirty.png]] * Summary The goals for my workflow are to achieve speed and efficiency, cut wasted time and movement, and eliminate hand, pinky, and wrist pain.

My philosophy when choosing software is to pick customizable, keyboard-friendly programs that are configured in plain text. Setup should be automated. Human-editable configuration files prevent the need to repeatedly configure programs with a GUI, and keeping these files in a central location allows for better organization and easier backups (which should be performed regularly).

Modal editing should be used any time consecutive commands/actions are taken. Prefix keys, letter chords (e.g. vim-arpeggio and key-chord or dual-role keys), and thumb modifiers should be used for commands/actions that take place one at a time (e.g. deleting the last word when making a typo or window management). The fewest number of keys possible should be used to perform all actions, and the most comfortable keys should be personalized for the most frequently used actions.

The keyboard and keyboard layout used should ideally limit necessary movement away from the home row (and horizontal movement that requires hand repositioning), eliminate the need for pinky modifiers, and keep wrists straight. This can be achieved by using an ergonomic keyboard and ergonomic keyboard layout with a wide mod if necessary. Ideally, a keyboard should be split, vertically staggered, adjustably tented, support hardware remapping (with tmk firmware), and have a well positioned thumbcluster. In the absence of an ergonomic keyboard, a wide mod can help to keep wrists straight and is also useful for making RAlt more accessible to the thumb. An ISO layout can allow for a wider wide mod. A long term goal of mine is to learn stenography, but the barrier of entry is high.

The most frequently used programs should be opened automatically and bound to a key instead of opened with a launcher. Sessions should be automatically saved and set up. Navigation of any sort (window, file, etc.) should be quick and not get in the way of the task at hand. Time shouldn’t be wasted switching to and using the rodent. Symbols (e.g. parentheses, brackets, and programming operators) and keys like backspace and enter should be remapped or put on a layer based on their frequency of use. Similarly, modifier keys should be re-arranged and put into the most comfortable locations.

  • Why the Keyboard? I prefer software that was created with keyboard usage in mind. Some general things I look for are as follows:

  • Can be operated entirely with the keyboard

  • Has modality (à la vim)

  • Allows for sequence/multi-key keybindings (à la vim)

  • Has some level of scriptability and the ability to call shell commands

None are these are absolute requirements of course. I’m happy to use a mouse with GIMP or games. However, the keyboard is usually faster for any action that doesn’t involve precise movement or interaction with specific pixels. This is mainly because the keyboard allows for lot more possible actions (through single, combined, and/or sequential keypresses) and because there is no need for precision. Certainly, mice can have a huge number of potential actions if you consider small parts of the screen as separate actions, but a system designed in this way would require inhuman precision and be unintuitive. The upside of the mouse in the first place is that it allows for a more intuitive user interface. GUIs designed with the mouse in mind use nested menus to prevent taking up too much screen space. Using keys instead of navigating through menus may require some memorization (though software like which-key eliminates the need for that), but it is ultimately far more efficient and frees up screen space as a bonus.

I’ve found the keyboard to be more efficient for pretty much everything, including navigating to an arbitrary character in some text. People often seem to bring this up as case where the mouse is quicker. I’ve tested myself using vim-sneak and the mouse and found sneak to be significantly faster for me. Furthermore, I don’t generally want to move to a random character, and the keyboard is far more elegant when you want to move by an actual unit like a sentence or paragraph or when you want to do something like jump to a typo or error.

Standard keyboards may generally be poorly designed (QWERTY, horizontal stagger, lack of thumb keys, and poorly placed modifiers), but the mouse is inefficient /by design/ without possibility for improvement (except for making it more like the keyboard by adding more buttons). That’s not to say it’s completely useless or that learning keybindings is always best. I’m happy to use the mouse for lesser-used programs (e.g. GParted) or to type out commands on the command line when it makes sense. However, I’ve found that for most simple applications, learning keybindings takes a few minutes, and for more complicated ones (e.g. vim), some investment pays off a lot (with regards to both efficiency and possibly wrist pain).

When it comes to modality, I’m not a complete purist either. Modality doesn’t make sense for actions taken in isolation (like deleting one word backwards or moving to the end of the line before continuing to type). Of course, modality doesn’t preclude the use of modifier keybindings, so I use them when it makes sense. That said, I find modality (or just letter keybindings if there is no text entry) makes sense most everywhere. Modality saves keypresses in any situation where you start executing multiple actions in a row. For every new action, you save the need to press a modifier you would have had to press otherwise. Furthermore, the vim style of having operators, motions, and text objects makes for great composability. The main exception for me is window managers. You can have modal keybindings with quite a few window managers, and [[][howm]] even embraces this style by default and provides operators and motions. Since I personally don’t usually take more than one or two window management related actions at a time, I’d find modality to be extremely inefficient here though and stick mainly to thumb-modifier keybindings.

It’s also worth noting that modality isn’t exclusive to vim. Even emacs users who have little interest in vim make use of [][hydra] to save keypresses. Org speedkeys (or [[][worf]]) and [[][lispy]] could also be seen as “contextually” modal.

As for sequence keybindings, I find them vital for programs where a lot of actions need to be bound. I much prefer two keypresses on the home row to using Control or some modifier, but that in part has to do with not having a decent keyboard with easily accessible thumb keys.

Finally, scriptability is almost always nice. I especially love software that is configured in an actual language or in commands that would be valid for that program’s “command line” (e.g. vim, emacs, vimus, and pentadactyl). It’s not even necessary for the program itself to provide the scripting language. For example, bspwm and lemonbar can be scripted in essentially any language. In many cases a simple config file will do for me though, especially when keys can be bound to external programs.

  • Why Emacs? I have no attachment to the Unix philosophy. I care mainly about practicality and reusability. If you consider emacs as a single, monolithic program, then it completely violates the Unix philospohy. On the other hand, if you consider it to be an ecosystem, there are many individual packages written for it that do one thing well, and they can usually be combined to work well with each other.

It turns out that, for me, emacs is the best interface for anything text-related from a user and developer standpoint. Standalone programs that aim to be vim-like have to re-implement a modal keybinding system, vim motions, etc., and it’s very unlikely that they’ll have advanced functionality like fuzzy searching or text objects or be easily programmable. Every application for emacs gets vim functionality for free with evil. Motions, text objects, and operators are always available for navigating and copying text, and modal keybindings can be used for anything. Even for those who dislike modality, emacs offers programmability and many other useful packages. With ivy (or helm) and flx, you can fuzzy search the text of any buffer with immediate, visible context displayed for results. This, of course, applies even if the buffer is not a file on the disk (e.g. an irc buffer or terminal). You can use abbreviations, snippets, and autocompletion anywhere you can type text if you so desire. You can use a package like [[][link-hint]] to copy or open links, buttons, file paths, etc. using the home row. Packages like avy, hydra, ivy, and evil can be useful even when you’re not editing text but instead reading your mail or chatting on irc or jabber. If you choose to have emacs be your mail client, irc client, mpd client, feed reader, man page viewer, etc., you have a whole ecosystem of functionality that would not otherwise be available.

Some people scoff at the idea of running a terminal in a text editor. Certainly, there are some general ways to get some of the useful functionality I mentioned without re-implementing it across programs. Terminal programs are often keyboard friendly. Consider the vim navigation mode for scrollback and copying provided by some terminals. Tmux’s copy mode allows for using vim keys for navigation regardless of the terminal. There are plenty of ways to do “link-hinting” for terminal programs. Zsh has text objects builtin now. You can integrate fasd and fzf with a lot of terminal applications (like ranger). Still, none of this comes close to the functionality available in emacs. How may tui applications provide full, customizable vim keys for navigation and copying? None. Tmux’s copy mode is not all that efficient, especially when compared to navigating text with more advanced vim motions and avy (compare to sneak or easymotion). For some types of applications, there aren’t even any that allow for sequence keybindings (i.e. I don’t know of any standalone feed readers that do). Link-hinting in terminals is often error prone (e.g. for urls split across lines) and lacks customizability (e.g. one must use numbers for termite’s link opening functionality). For this reason, I’m actually using [[][emacs to do this]] even when opening urls outside of emacs. Integration with fzf is usually limited to actions on files or directories. On the other hand, many applications in emacs have good integration with helm and ivy. For example, you can use helm to search your emails or to switch to an IRC channel you have open.

Also consider that emacs has an advantage over most tui programs in that it can nicely display formatted text and images. This isn’t to say that I think emacs is always the best for any type of application. I’d never use it as my primary image viewer or browser, but there are some things it does unexpectedly well. Using eww can be great for reading html, and though I was skeptical at first, I’ve found myself liking pdf-tools more than zathura in some cases. Being able to use bookmarks or helm to get to my recently viewed pdfs is great. Unfortunately, pdfs in emacs aren’t text, so you don’t get all the features you would get otherwise. There are useful commands like =pdf-occur= though, and the outline menu can help with navigation. While you can’t use vim keys to copy text directly, you can open a buffer with the text from the current page iserted and use evil to copy what you want there. In zathura and apvlv, there currently isn’t any way at all to use the keyboard to copy text.

Let’s also not forget the wonder of being able to customize everything in emacs lisp. As much as I prefer other lisps, emacs lisp still makes a great configuration and scripting language for a text editor.

The only slight disadvantage I’ve found of using emacs for these types of applications is that things may not look as good. For example, while I think emacs’ irc clients look pretty good, I doubt they’ll ever look anywhere as good as a riced weechat or irssi. Mingus looks ugly compared to ncmpcpp. Mu4e doesn’t look as good as mutt. The same goes for elfeed when compared to newsbeuter or canto. In all these cases, the emacs versions are more minimal too, which some may prefer. I care more about functionality, so this doesn’t really bother me.

  • Programs Here I’ve organized my thoughts from trying from trying out and choosing various programs.

| Type | Program | |————————-+————————————————| | distro | arch | | package manager | pacman+powerpill+pacnanny+ | | | nix | | boot loader | rEFind and GRUB | | config management/setup | bash+saltstack+stow | | display manager | none | | DE | none | | window manager | bspwm | | hotkey daemon | sxhkd and xchainkeys | | remapping | xmodmap (meh; stuck with it) | | screen locker | slimlock | | text editor | emacs and vim | | shell | zsh (fish is fine too; eshell occasionally) | | network manager | connman (stuck on NetworkManager for now) | | terminal emulator | termite+tdrop+tmuxinator+tmux (also ansi-term) | | launcher | bemenu | | wallpaper setter | setroot | | panel | lemonbar-xft | | compositor | compton | | notifications | dunst | | file manager | ranger | | mass renaming | ranger’s :bulkrename (and wdired) | | browser | firefox+pentadactyl (eventually qutebrowser) | | password manager | pass | | image viewer | pqiv (previously sxiv and feh) | | media player | mpv | | mail sending | msmtp | | mail fetching | isync (previously offlineimap) | | mail client | emacs+mu4e (previously mutt+abook+notmuch) | | irc client | emacs+circe (previously weechat) | | feed reader | emacs+elfeed (previously canto) | | pdf viewer | emacs+pdf-tools and zathura (previously apvlv) | | music | mpd+vimus | | cd ripping | abcde | | music tagging | beets | | scheduling | fcron | | firewall | ufw | | encryption | truecrypt/undecided | | backup | rsync/undecided | | fuzzy searching | ivy+flx (emacs), FZF (terminal), unite (vim) | | pager | vimpager (and woman in emacs) | | screenshots | maim+slop (goodbye scrot) | | torrent client | transmission | | video recording | ffmpeg+slop | | audio/video conversion | ffmpeg | | torrent client | transmission | | tagging | tmsu (dont’ really use) | | download manager | aria2c (haven’t tried saldl) | | calendar | emacs+org+calfw | | language input | ibus/undecided | | typesetting | have only tried LaTeX (and groff I guess) | | markup/notes | org | | VC | git | | fonts | inconsolata (LGC), fira-mono, uushi, siji |

** OS and Package Manager I started out using debian-based distros but quickly switched to Arch mainly for the minimal base installation, pacman, the aur, the wiki, and the rolling-release system. I love that essentially all the software I use is available in the aur. On the other hand, I hate having to recompile all my aur packages to ensure nothing breaks after a system update. This isn’t always necessary if major packages (like gpg) haven’t been updated, but it often makes me wish that more programs were in the official repos. As for aur helpers, I don’t really have a strong preference. I’ve mainly used yaourt, but I’ve been using aura and pacaur more recently. I like that pacaur and yaourt can be used for both the aur and official repos at once, and I like that aura is run as root from the start like pacman, but I don’t really use any of their advanced functionality. As for my actual kernel, I’m using linux-ck for bfq and bfs. I’ve found bfq to help to prevent my laptop from freezing as badly during large file transfers.

I’ve been using [[][nix]] more and more, and it solves most of the annoyances I have with pacman. Nix is great because it’s a distro-independent package manager that takes a “functional” approach to package management. I really love being able to have multiple versions of packages (and of their dependencies) installed at once. This makes it easy for me to test my emacs packages with multiple versions of emacs. It also means updating something like ncurses or gtk won’t break an older version of a program (different programs can use different versions of a dependency). Having everything under =/nix= means that nix can be used on any distro without conflicting with any packages installed by another package manager. Nix also gives you a good level of customizability by allowing packages to be compiled with or without certain features, but it also provides binaries if you don’t need to customize a package.

I’ve ended up liking most things about nix a lot more than other package managers, and despite its non-traditional approach, it still makes writing packages fairly simple. To be honest, for the few simple packages I’ve written, it was even more straightforward than writing a PKGBUILD. That said, nix isn’t as polished as pacman. By default, searching for packages is extremely slow (though [[][nox]] fixes this), and while installing packages isn’t slow, it’s definitely not as fast as using pacman and powerpill. It is also missing some of the packages I use, but that is changing quickly, and anyone can make a pull request to add a package.

I doubt I’ll switch away from Arch for primarily practical reasons (popularity and good support), but I am interested in trying out other distros like CRUX and gentoo. For me the, the most important features of a distro are the package manager, the size of the community, maturity, and how easily the installation can be scripted (e.g. not having to uninstall a bunch of default programs, a DE, or a display manager). [[][NixOS]] is exceptional with regards to the last point. NixOS provides a single central configuration file that replaces the fstab and pretty much all root config files. You can use it to do things like create your user, set your hostname, set your timezone, and install all the packages you use. Changes are saved, so you can rollback to a previous configuration in GRUB if you break something. This means that NixOS has builtin support for a declarative installation without the need to do almost any manual setup. My first install in virtualbox took about ten minutes using the basic template configuration. You configure your system once and then forget about it; this is how things should be. It’s not too hard to achieve this with scripts on Arch, but the way NixOS does things is much simpler and cleaner.

On the other hand, the way NixOS works makes it harder (or impossible) to manually install software. You can’t just ~make && make install~. Nix doesn’t put programs under =/usr/bin= or =/bin=; they go under =/nix= and are symlinked into ~~/.nix-profile/bin~. There are a few programs that I need to update frequently (some bug has been fixed or feature added), and while the process to do this on NixOS can be mostly automated, it’s not nearly as simple as updating a package from the aur. This isn’t a big deal, but it could pose a problem for me in the case that I needed to quickly install a package that wasn’t already in the repos. Some other reasons I’m hesitant to switch are the lack of a lot of packages I use, the lack of startx, and the lack of support/popularity (e.g. the documentation/wiki is lacking). The package situation is constantly improving though, and nix has a lot of packages that aren’t even in the official Arch repos. For now I’m happy to be able to use both nix and pacman.

As for guix, I see it as a less popular (less packages), more restricted (only libre packages are allowed) version of nix. My laptop won’t even work properly with linux-libre, so GuixSD isn’t really an option for me. I’d probably prefer to use scheme over the nix DSL, but the nix DSL is pretty simple and good enough for the task I think (especially considering that a lot of package managers just use bash). What major benefits guix has to the end user, I’m not sure. The command names for guix seem more reasonable to me, and it has a nice emacs package. On the other hand, it’s worth noting that nix is on github, whereas the primary way to interact with the guix community is the mailing list. For these reasons, I have to doubt that guix will ever be useful to more than a small niche of people. I still hope to play around with guix and Sheperd (previously dmd) more in the future and would still recommend checking it out.

** Configuration Management/ Installation Automation Installing Arch manually every time is needlessly tedious. Automation of this process isn’t nearly as nice as on NixOS or GuixSD, but it’s not too hard to write a script to do the initial configuration you would always do. The post-install setup is a lot more tedious, especially if you don’t remember what packages you normally install. This is why I prefer a declarative setup. Initially I had an ugly bash script do everything before deciding to try using a Configuration Management tool. I’m not that familiar with the different CM tools, but I ended up choosing saltstack as it seemed to be simpler for what I wanted to do and I liked the use of simple yaml files (I did not look too much into ansible though).

I’m still using a bash script as a base to do the necessary setup for my salt configuration. It updates the pacman mirrorlist and installs salt, powerpill, and aura. I’m using aura for installing aur packages with salt because it can be run as root without problems (and salt doesn’t have a plugin to install aur packages). My salt configuration has formulas for creating my user, setting up my root configuration files, installing all my packages (including those installed by other programs like =nix= and =pip=), and enabling/starting my services. The feedback given by salt is really nice and is one reason I prefer it to just installing a list of packages despite the increased verbosity.

After all this, my bash script just uses [[][stow]] to set up the configuration files in my home directory. I prefer to keep all my dotfiles under =~/dotfiles= since it is less cluttered and means I don’t have to make my home directory a git repository. Stow also allows me to have my dotfiles further categorized into sections (e.g. =music=). I’ve looked at the countlss “dotfile managers”, and most of them just make things more complicated (e.g. by requiring every managed config file have an entry) or don’t allow for categorizing dotfiles into different directories. Stow is simple and does everything I need, so I have no intention of switching to something else.

See [[./root]] for these scripts. I’ll add my install and post-install bash scripts once I get the chance to test them more thoroughly.

** Window Manager This is probably my most selective pick, considering just how many window managers there are (I’ve tried dozens, many when testing [[][tdrop]]). After finding out about tiling window managers, I used awesome and xmonad with a DE for a while before switching to using just bspwm. I tried herbstluftwm and i3 as well and like them for mostly the same reasons I like bspwm, but bspwm is by far my favorite. The reason is that while it is extremely simple, it is also extremely scriptable and has a lot of advanced functionality if you need it.

When I was using xmonad and awesome, I knew very little about haskell or lua and had config files full of snippets I didn’t understand just to have basic the functionality I wanted. In contrast, bspwm has a simple, straightforward configuration file and has everything I want out of the box (e.g. highly customizable keybindings). I like that the hotkey daemon is separate (unlike with most window managers) and that all interaction with bspwm is done through a command line program, bspc. This basically makes bspwm scriptable in pretty much any language (though I’ve never needed to use anything other than bash). I don’t use a lot of bspwm’s more advanced functionality (read the man page; it’s capable of a ton), but I do use its query, subscribe, and rule commands a lot. They make doing a lot of things trivial (e.g. automatically taking actions when certain events occur).

** Hotkey Daemon Here’s one area where I prefer adherence to the Unix philosophy. I find it kind of annoying that there are so many window managers that implement keybinding functionality that can’t be used with other window managers. I also happen to like sxhkd better than the WM specific alternatives. Compared to xbindkeys, it has saner syntax (imho) and a lot more functionality. It allows for prefix, modal, and modifier keybindings. That said, last time I tried using deeply nested keys, it was buggy, so I generally use xchainkeys when I want to mess around with that sort of thing.

** Panel I’m using [][lemonbar]. You use it by simply piping text into it, so it’s scriptable in pretty much any language. For this reason, it may also be hard o get started with, but bspwm’s [[][example panel]] is a good start. It doesn’t have tray or image support, but I don’t personally need these.

** Browser Pentadactyl is a mammoth of vimmy goodness, and, unfortunately, nothing else currently comes close. As for firefox itself, I do like that it has a lot of security and privacy related settings, but I don’t like the direction it’s been taking recently, and it is extremely slow. Every time I use qutebrowser, I’m astonished by how blazingly fast it is. It already supports pass integration. As soon as it allows for domain-specific settings/keybindings and has tabgroups and support for userscripts, I’ll probably switch to it.

** Image Viewer My image manager of choice is [[][pqiv]]. I was previously using sxiv but never found it to be very convenient/hospitable. Pqiv is a keyboard-focused image viewer like sxiv, but it fixes pretty much everything I disliked about sxiv. Unlike sxiv, it has an actual config file that’s read at run time. You can bind shell commands to any key directly in the config file, whereas in sxiv you can only have one external key-handler used with a prefix key. For this reason, I’d previously been using a fork of sxiv with ugly, duplicated code to add more key-handlers. Pqiv is also the only image viewer I’m aware of that has vim-like sequence key bindings. It allows for binding keys to multiple commands and even allows for cycling the behavior of keys. This means you can implement something like a 4-corner cycle for reading comics directly in the config file. Speaking of comics, it supports viewing images in archives (e.g. cbz). It’s even scriptable, and you can send commands to a running instance or have it watch a directory and automatically update its image list. It also allows viewing the output of running commands on an image (e.g. imagemagick). Pqiv even supports viewing video and webms if you want.

Given all this, I think it’s a crime pqiv isn’t more popular. I’d definitely recommend trying it out.

** Wallpaper Setter I pretty much tried every wallpaper setter without being happy with any of them even for basic functionality (most of them don’t have feh’s option to fit to either the width or height to fill the screen). The best I’d tried were imlibsetroot and feh. I don’t use feh as an image viewer, and ended up liking [[][setroot]] even better, so it takes the cake for me. I’ve written some more about it [[./aesthetics/][here]].

** File Manager Dired can be a good file manager, and I’m using it more, but ranger is far more polished out of the box. I especially love rifle and how well ranger does previews. The only thing that bothers me about it is how slow it can be to load when starting or entering certain directories.

As for mass renaming, there are a ton of solutions (e.g. vidir, wdired, vim-renamer, and tmfan), but they all basically end up involving editing the directory structure in a file. I end up using ranger’s =:bulkrename= and emacs’ wdired since they are both builtin and work well.

** Pdf Viewer I mentioned my reasons for liking pdf-tools above. Zathura is also a nice vim-like pdf viewer, but I dislike the lack of tab support (apvlv has tabs btw), especially when I have related pdfs open. Using tabbed is disgusting for any program (just compare pressing a single key to creating a new tab with some global key like =alt+shift+t=).

  • Working On

  • Cleaning up all config files and adding them here

  • Cleaning up and adding emacs init file

  • Cleaning up older bash scripts

  • Testing post-install scripts

  • Patiently waiting for my keyboardio so I can experiment with multiple persistent key layers, dual-role letter keys, and keyboard macros using tmk firmware

  • Hoping xmodmap dies and we can get better remapping software with smartly implemented dual-role capability on linux; especially with the standard keyboard, this is important for eliminating pinky modifiers (shift hurts my pinky; I often have to use other fingers to press it when typing for extended periods of time, and my hand still ends up hurting)

  • Cool Things I Stole ** Use Shell Functions in Ranger


In, replace the matching line with the following under =class shell(Command):=

#+BEGIN_EXAMPLE‘bash -c “source /path/to/file;’ + command + ‘”’, flags=flags) #+END_EXAMPLE

Note that you shouldn’t use the line in the thread because the quoting order will kill ranger’s handling of escaping.

The downside of this is that the shell command is slower if you have a lot of functions. Because of this, it may make sense to source a file only with the needed functions instead of the entire rc file. You bind keys to shell commands directly in the =rc.conf= instead, but this is nice for more complex functions that don’t quite warrant their own script.

See [[./media/.config/ranger/ranger_functions][my ranger functions]].

  • Interesting Workflow Excerpts ** Make Any Terminal Emulator Dropdown Regardless of WM I’ve tried to create a much more generalized version of my dropdown script that works well with more window managers and has extra functionality that other dropdowns don’t have. For example, it can automatically resize a dropdown when changing monitors and supports turning any window into a dropdown.

See [[][tdrop]] and make an issue if there isn’t already floating support for your wm.

** Consolidate Bspwm Resizing Keybindings I never really liked the default way of resizing in bspwm. I prefer to have keybindings do something else in cases where the normal command would fail. I’ve been using the style where the directions “act on the split.” Consider an example where there are only two windows (left and right). If the left window was selected, =super + alt + h= would shrink the left window on the right and grow the right window on the left (moving the split between them to the left). It would act the same if the right window was selected instead.

I find this behavior more consistent, and it consolidates two sets of keybindings (the default =super + alt + {h,j,k,l}= and =super + alt + shift {h,k,j,l}=). Now that bspwm’s resizing command works on both tiled and floating windows, all three types of the resizing keybindings can be combined into one. Using the following script, =super + alt + {h,j,k,l}= can both have the behavior described above on tiled windows and resize in a direction for floating windows. It might be more useful to actually move a floating window, but I don’t use floating windows that often, so I don’t have a strong opinion here. That would require an extra check to see if the window was floating.

Unfortunately, the resize commands don’t have a non-zero exit status if they don’t do anything, so unlike with the tiled-only solution (see the commented out commands), the width and height need to be explicitly checked to see if they have changed. I’m getting the dimensions from =xwininfo=, but they could also be gotten from bspc’s query command. #+begin_src bash wid=$(xdotool getactivewindow) wininfo=$(xwininfo -id “$wid”) width=$(echo “$wininfo” | awk ‘/Width/ {print $2}’) height=$(echo “$wininfo” | awk ‘/Height/ {print $2}’) case $1 in left) # bspc node @east -r -40 || bspc node @west -r -40 bspc node -z left -40 0 if [[ $width == “$(xwininfo -id “$wid” |
awk ‘/Width/ {print $2}’)” ]]; then bspc node -z right -40 0 fi ;; down) # bspc node @south -r +35 || bspc node @north -r +35 bspc node -z bottom 0 +35 if [[ $height == “$(xwininfo -id “$wid” |
awk ‘/Height/ {print $2}’)” ]]; then bspc node -z top 0 +35 fi ;; up) # bspc node @north -r -35 || bspc node @south -r -35 bspc node -z top 0 -35 if [[ $height == “$(xwininfo -id “$wid” |
awk ‘/Height/ {print $2}’)” ]]; then bspc node -z bottom 0 -35 fi ;; right) # bspc node @west -r +40 || bspc node @east -r +40 bspc node -z right +40 0 if [[ $width == “$(xwininfo -id “$wid” |
awk ‘/Width/ {print $2}’)” ]]; then bspc node -z left +40 0 fi ;; esac #+end_src

You can see [[./scripts/bin/wm_action]] for my current version of the script with support for resizing based on a percentage of the screen. Neeasade has also [[][rewriten my script]] to additionally support resizing window groups

** Empty Desktop Keybindings Why use modifier keys to start a program if there is no active window? I’m using bspc’s subscribe command to monitor for when a desktop becomes empty and then switch to a different sxhkd config. This way, I can start my programs with the home row on empty desktops.

It would also be possible to use a single config file and check for every single key whether the desktop is empty, but this would be uglier, so I haven’t bothered trying it. The approach I’m using doesn’t usually cause problems, and I’ve mostly prevented rapid changes between an empty and non-empty desktop (e.g. dropdown toggling) from resulting in the wrong sxhkd config being loaded.

See my [[file:./common/.config/bspwm/bspwmrc][bspwmrc]] and the corresponding [[file:./scripts/bin/bspwm/maybe_reload_sxhkd][script]].

** Use Ranger Instead of Default GUI Popup for File Saving Pentadactyl already has :w and ;s, which allow for typing out file paths with tab completion. This is cumbersome especially for deeply nested directories. I used to just use an alias to open ranger in my downloads folder and save there automatically. I found even then that I didn’t always get around to moving stuff, so now I have an autocommand to send the file name on download to a script which will open a floating terminal with ranger running and pass the file location to ranger’s –selectfile and cut it (see [[file:./scripts/bin/ranger/dl_move][dl_move]]). I also have a dired section which, when used with emacsclient, can start a lot faster than ranger.

See [[][this post]] for more detailed information and other possibilities.

I’ve found that pentadactyl’s =upload file:= prompt that appears when you hint an upload link to be nice but not a universal solution for uploads (i.e. this doesn’t work for every website). Right now, I do image uploads and mail attachment from the commandline/ranger (see [[file:./media/.config/ranger/ranger_functions][ranger_functions]]). When I have to use the upload gui I often paste in file locations after copying them in ranger.

** Block Layout in Emacs/Vim and Examples of Context-dependent Keybindings Using tabs is only useless if you’re trying to use one buffer per tab (in an editor that supports buffers/a bufferline). I use tabs (or workgroups in emacs) as workspaces. I set them up with names so I can see which tab corresponds to which subject and can easily jump to them with ==. In vim, I use a script that also sets up custom keybindings for different tab names. For example, I use comma as a prefix key to jump to specific files depending on tab name. I have a general set of these “quickmarks” and specific ones that either correspond to files by frequency of use (,f ,s ,t for first, second, and third) or by name.

This drastically reduces the time it takes to get to a specific file as well as the complexity of the keybindings. This is the order of preference for me when it comes to file navigation:

  1. navigate to open buffer or quickmarks (2-4 keys; 2 for right tab/workgroup, maybe 2 for getting correct pane or using a quickmark)
  2. interactive search of open buffers, mru files, current dir, and current project (unite in vim; helm, ivy, and projectile in emacs)
  3. search with locate (or maybe ag if searching for by contents) (unite in vim; helm or ivy in emacs)
  4. file manager w/ quickmarked dirs as last resort (ranger if in terminal vim; otherwise dired or vimfiler)

On the commandline, I find fasd to usually be the fastest way to get to a specific directory. Previously I was using deer, blscd, or just ranger with bookmarks and =f= to get places. Enhancd is also worth noting, and fzf is what I use if I don’t already have a directory in my fasd history. That said, I’m working less on the command line and more in my editor.

Quickmarks for files are fast, but the less you use a keybinding, the more forgettable it is. I find workspaces that are automatically set up with my most frequently used files and the “f s t” keybindings I previously described to be a nice way to keep both keystrokes and memorization to a minimum. Which-key can also serve as a useful reminder, but even without quickmarks, helm or unite can be used to very quickly get to pretty much anywhere. I have one key bound to open helm with sources for open buffers, most recently used files, and the current directory all at once. If nothing is found, it automatically falls back to using locate. If I’m working in a repo, I use fuzzy searching with ivy and projectile, which is lightning fast.

In vim/emacs, I am using =m= as a prefix key for whatever major mode/filetype I’m currently in (with =M= instead used for marks). In org mode, =m= performs org mode navigation, clocking, todo, etc. In code files, I use =m= to compile or run the current file as well as for repl interaction, error navigation, etc.

As for other, non-vim/emacs examples, I have context bindings for empty vs. non-empty workspaces/desktops. On empty desktops, I have sxhkd automatically restarted with a custom config where single keys are mapped to open programs and switch desktops. Why use more keys than necessary? The transition time to get used to the difference was insignificant, so I don’t think consistency is of any benefit here.

In firefox, I also use the space bar as a prefix key for tab navigation. I bind == to a command that will go to tab 1-10 in the curent tab range (e.g. =a= on tab 24 will go to tab 21). I also have key bindings to switch to specific tab groups and setup a few custom key bindings depending on tab group. I haven’t done much with this though since TabGroupie works very inconsistently. Pentadactyl’s groups (not related to tab groups) are probably the best example for taking advantage of different contexts. I use them to set up site-specific keybindings. For example, on reddit, I pass through keys for use with RES and also add custom goto bindings with the prefix g for going to specific subreddits. I use this to set up more convenient zoom bindings on image urls. This also allows setting up custom key bindings for sites that have non-configurable key bindings.

The best example I’ve seen of key-reuse is [[][lispy]]. Org speed keys and [[][worf]] are also good examples.

See: - [[file:./vim/.navigation.vim][.navigation.vim]] and [[file:./emacs/.emacs.d/navigation.el][navigation.el]] - [[file:./common/.config/bspwm/bspwmrc][bspwmrc]] and [[file:./remap/.config/sxhkd/empty_sxhkdrc][empty_sxhkdrc]] - [file:./browsing/.pentadactylrc][.pentadactylrc] - [[file:./browsing/.pentadactyl/groups.penta][groups.penta]]

** Stream Any Video in MPV Existing solutions for playing videos in the player of your choice (e.g. mplayer or vlc) are limited in what they work with. There are quite a few programs that allow this for a few sites such as youtube and daily motion. Consider youtube-viewer, quvi, and youtube-dl (used by mpv by default), which now supports a large number of popular websites. Still, youtube-dl doesn’t work on a lot of sites I use, and I’m not particularly fond of the mozplugger/viewtube approach either where your player is basically embedded in the browser(even if this worked with all sites).

This is a relatively simple thing to do in actuality. The reason existing solutions are site specific is because they operate based on the site url. Mpv will have no problem playing pretty much any video if you pass it the direct link, so all you need to do is write a script to fetch the link of playing media.

There’s certainly a much better way to do this, but I only know how to get this link manually: you open up firebug (or control+shift+j in chrome) and go to the net/media tab. When you play the video, the direct link will show up. You can also use the media sniffer firefox plugin (which is short and could probably easily be turned into a pentdactyl plugin). What I’ve done is scripted the clicks. This is mouse location dependent; the areas that need to be clicked will depend on menu size (which depends on the gtk theme or window size if firebug or something similar is being used). Because of this, doing things this way is kind of an ugly hack compared to using youtube-dl, but it works consistently for me. You can also just use a key to open firebug and copy the link by hand.

Requirements: Firefox with pentadactyl, firebug or the media sniffer plugin, MPV, and Firefox

Some problems with playing videos in mpv is that very rarely the video will quit in the middle or the buffering will be slow (it usually depends on the site). For some sites, the playing video can’t be detected by firebug, but I’ve only encountered this on two websites out of the dozens I’ve tried.

See: - [file:./browsing/.pentadactylrc][.pentadactylrc]

** Make Gifs/Webms in MPV I thought it would be efficient to set up bindings within mpv to create gifs. Now that mpv has an a-b loop (issue #1241), I’ve gone back to using a script (=ffcut=) that first cuts part of a video out and then optionally makes a gif from that part. I’ve also fixed =ffcut= to accurately cut videos by default. he alternative, directly copying sections of the video, is faster but requires starting from a key frame making it innacurate. [[][These]] [[][two]] mpv plugins may be better ways to cut/crop/convert a video, but I personally like =ffcut=.

The =makegif= script is just a wrapper for ffmpeg, imagemagick, and optionally gifsicle that takes a video, makes frames from it, and then creates an optimized 600 width 10 fps gif. It has much improved (though it may be annoying as-is to users other than myself due to the default output directory). For example, if the output gif is not satisfactory, one can simply use the frames already created and try different options:

#+begin_src shell makegif

notice that there are some extra frames at the end

go to the location of the frames and delete a few at the end

makegif -u

use max optimization with gifsicle and increase fuzz percent

makegif -u -O 3 -z 1.8

changing fps or width values requires remaking the frames

(unless you want something sped up/slowed down):

makegif -w 800 -O 3 -f 15 -o mygif.gif #+end_src

I also have a =makewebm= script that behaves similarly.

An example gif with default settings (made within mpv): [[./example.gif]]

See: - [[file:./scripts/bin/video/][bin/video]] - [[file:./media/.mpv/input.conf][input.conf]]

** Home Row Window Mangement This started as something I did for fun, but I’ve actually found it pretty useful, especially for switching desktops. This setup is a litle weird and not universally applicable. For that reason, I can’t say it is a better way of doing window management, but I think it is interesting. I might abandon this method in favor of thumbkey modifiers if I get a better keyboard.

For me, window management is pretty much split between tmux and bspwm. Bspwm takes care of all my gui windows (and occasionally a terminal window), and tmux takes care of all my terminal sessions, windows, splits, etc. There is also tab/split management within programs, but that already doesn’t require the use of modifier keys.

The idea of modal window management has interested me, but modal window management isn’t really efficient when most of the time you only execute one wm command (it just requires an extra key for escaping as opposed to using a prefix key). It introduces other problems as well. Escape can’t be used to enter this “window management mode” (with sxhkd this would make escape lose functionality everywhere else). Unlike in vim, “normal mode” would be infrequently entered and immediately exited. Although I am a fan of modality, I do not think having modes within modes does anything other than overcomplicate things. Instead of trying to mirror this functionality, I’ve found it most efficient to eliminate window management as a separate entity and build it in to all my programs just as I would set up the same (or similar) bindings for split navigation for different programs.

My most used gui programs (emacs, gvim, firefox, mpv, apvlv/zathura, and pqiv) all allow for bindings to terminal commands as well as sequence key bindings (thanks to wm4 for implementing this in mpv!) which makes this possible. This probably won’t be as useful for anyone who uses a lot of gui programs, without doing something particularly convulted like using sxhkd as a wrapper for modal keybindings (see below). The difference between pressing =super+5= and =rd= (qwerty “sg”) may not seem to be a big deal, but it’s been quite noticeable to me. As for delay/lag, it should be noted that =-ex= and not =-builtin= should be used for pentadactyl keybindings (=builtin= is much slower and will cause a noticeable delay).

I’ve also made tmux keybindings in all of tui my programs (vim, zsh, less, weechat, ranger, emacs, mutt, tig, w3m, and vimus). The only downside of this is that zsh keybindings obviously won’t work if you have something running (not a problem if you’re running zsh in emacs or vim though!). On the other hand, this isn’t that big of a deal because tmux allows use of a prefix key on a layer (e.g. mine is grave/backquote, which is =mode_switch+f= for me). Repls can also be run in emacs or vim to keep modal keybindings

Previously I was repurposing =r= and =s= as these prefix keys. I’ve switched to just using =r=, since I didn’t feel that this functionality warranted taking up two home row keys. I’ve started using the =wm_action= script as a wrapper for my window management keybindings. This is kind of ugly, but it has already allowed me to get rid of some old scripts I was using. For example, I’ve set it up to determine whether mpv is being run in a terminal or not so that bspc or tmux key bindings are used accordingly. I’ve also started binding keys in sxhkd to it instead of directly to bspc, so that I don’t have to use a different sxhkd config for different window managers (I check the window manager in the script). Lastly, I’m using =wm_action= so that I can change the actions for =r= in one place instead of 10 and have them work in whatever window manager I’m working with (as long as it supports interaction through the command line like i3, herbstluftwm, and stumpwm do).

I’d also like to try window management with chording or dual-roled keys at some point (pressing qwerty =s + {h,j,k,l}= simultaneously will do window switching). This gets pretty messy without a universal way of doing chording, and it may just be better/cleaner to do window management with well-placed thumbkeys instead.

See: - [[file:./vim/.vimrc][.vimrc]] - [[file:./scripts/bin/wm_action][wm_action]] - [[file:./remap/][remap/]]

** Create a Modal Interface for Programs That Don’t Support Rebinding I’ve pretty much abandoned software that doesn’t support modality and prefix bindings, but this may be a useful hack for users of such software.

There are many programs that have extensive keyboard shortcuts that could potentially be useful if their default bindings weren’t oriented towards masochists. For some programs, the few available shortcuts can still be massively useful when implemented in vim-like modes (e.g. Libre Office). One way to do his is to rebind keys to fake existing keyboad shortcuts. It is worth noting that this isn’t that great of an approach. For example, a better solution exists at least for Libre Office (see [[][vibreoffice]]). Hopefully embedded vim/neovim will further prevent the need for solutions like this. An alternate possibility is to implement modality for all text boxes on an OS (I think OSX has something like this?).

As an example, I’ve done this with Libre Writer to emulate a normal and visual mode with keys for moving by words, characters, and lines.

[[][Video Demonstration With Libre Writer]]


This solution is restricted to X currently (though something similar could probably done with AHK). It makes use of xchainkeys for the modal keybindings and xdotool and xsendkey to fake the necessary keyboard input. A potentially “software independent” solution would be to use tmk firmware to make layers with macros and keys for “mode” (layer) switching. I have not been able to test this.

See [[file:./remap/.config/xchainkeys/xchainkeys.examplevimlayer.conf][xchainkeys.examplevimlayer.conf]] for the example configuration for Libre Writer. Since I’ve started using LaTeX or simple markup instead for the most part, I haven’t done anything else with this, but I think that it would be more desirable to have the modal interface automatically started (setting up and deconstructing keybindings on window change) for the program it is being used for (using bspc –subscribe and awk to run a bash script on window change that checks if the current window is, for example, Libre Office).

  • Credit Anything I’ve swiped for my config files has a url.

Some general stuff:

Credit to vaskozl for [[][his thread]] on not using the mouse, which is one of the main reasons I ever took interest in any of this. Credit to DreymaR and lalop for inspiration on layout stuff after I switched to colemak and to bunnfly for the colemak vim config (all from the colemak forum).

Thanks to baskerville/bloom for bspwm and sxhkd. Thanks to kana, Shougo, tpope, junegunn, dhruvasagar, rhysd, etc. for all their awesome vim plugins. Thanks to abo-abo for his awesome emacs packages. Thanks to tuhdo for his great guide on emacs and helm. Thanks to codestation for qcma. Thanks to sol, haasn, etc. for vimus. Thanks to ttzhou for setroot. Thanks to phillipberndt for pqiv.

Related Repositories



:octocat: dotfiles ❤ Testing my dotfiles repo on OS X to get my work environment ready in just a few moments. #VIM + #ZSH + #TMUX = Best Developer Environment ...



dotfiles for vim, git, zsh, weechat, openbox, xterm, and many others. Install with: lndir -silent /path/to/dotfiles $HOME ...



:art: I created a logo for your dotfiles. Well, for @pengwynn's [dotfiles](, but you can use it too. ...



To use: git clone --bare [email protected]:bronson/dotfiles.git .dotfiles.git ; alias .f="git --work-tree='$HOME' --git-dir='$HOME'/.dotfiles.git" ; WARNING .f reset --hard HEAD ...



dotfiles dotfiles!! ...

Top Contributors