kqtran

Synchronize Workspaces Across Platforms

·

I rotate between Windows laptop, macOS, Windows desktop, and Linux remote servers several times within a day. At the same time, I might go weeks without touching any of these at all. For this reason, it's important that my experience is as consistent as possible to lower the barrier to whatever the reason is I'm logged into that device. Especially for someone who is easily distracted, I believe my key to working efficiently is removing minutiae.

Hotkeys

A big part of achieving my flow involves the use of hotkeys. As hotkeys are not universal across platforms, it made sense to try to find the ones that were most ubiquitous / useful, and then use third-party programs to condense them all together.

For macOS, use HammerSpoon. For Windows, use AutoHotkey.

Window Walking

A concept you will see re-iterated here is the use of fuzzy-finding.

On macOS, I use Contexts which has a native feature to fuzzy-find your open windows. Note that it looks like it might be abandonware - look to alternatives.

To replicate this functionality in Windows, use PowerToys and use the Command Palette feature, specifically. This is the successor to PowerToys Run. The equivalent functionality is to pull up the Command Palette and type the global shortcut for the Window-Walk functionality. By default it is mapped to <.

My shortcut for Contexts was arbitrarily mapped to Ctrl+Space, as Alt+Space was used by Spotlight already. To map this in AutoHotkey, use the following example:

^Space::{
    Send("!{Space}")
    Loop 40 {
        if WinActive("ahk_class PowerToys.PowerLauncher") || WinActive("ahk_class WinUIDesktopWin32WindowClass")
            break
        Sleep(1)
    }
    if WinActive("ahk_class PowerToys.PowerLauncher") || WinActive("ahk_class WinUIDesktopWin32WindowClass")
        Send("<")
}

Firefox / Edge

A useful native shortcut in Edge is Ctrl+Shift+A which will fuzzy-find your tabs. You can mimic this behavior in Firefox with the following HammerSpoon shortcut:

local TabSearch = {}

function TabSearch.trigger()
    local frontApp = hs.application.frontmostApplication()
    if frontApp:name() == "Firefox" then
        -- Focus the address bar
        hs.eventtap.keyStroke({"cmd"}, "l")  -- Cmd+L equivalent to focus address bar
        hs.eventtap.keyStrokes("% ")
    else
        -- hs.alert("This shortcut only works in Firefox!")
    end
end

return TabSearch

Remap this in AutoHotkey:

#Requires AutoHotkey v2.0
^+a::
{
    if WinActive("ahk_exe firefox.exe")
    {
        Send "^l"         ; Focus address bar
        Send ("`%")         ; Type percent sign
        Send " "          ; Space to trigger tab search
    }
}

I've always found Windows Search and macOS spotlight search to completely pale in comparison to the explicit %PATH%. while Windows 10 Search is a little better, it occasionally fails to load and is just slower than hitting Win+R for the Run prompt and issuing a command.

Specifying my own PATH location in allows me to create shortcuts such as ~ to navigate to $HOME, run ff to open Firefox, or write a custom script accepting custom parameters for quick administration. you can even perform simple aliases by adding shortcuts to binaries that may not be added to your PATH such as pip3 or openssl - these will carry with you over several computers in a way that serves as documentation for what tools you have used in the past.

Adding the new %PATH% folder to your OneDrive folder is a great start, but a lot of CLI tools may be administration-related, requiring elevation (stopping and starting services). Or, they may require impersonation but not elevation (managing MECM with a privileged account) or they may require both (remote server administration tools). You may need to log in as another user to run a command un-elevated, which by default does not have access to the remote storage of OneDrive.

  1. To start with the simple alias of Firefox to ff, simply create the folder in your OneDrive storage and copy the shortcut to Firefox and rename it.
  2. Make the directory junction to a public path such as C:\bin by issuing mklink /D C:\bin "c:\Users\k\OneDrive - corp\bin"
  3. Give your privileged account access to this folder. Right click the folder, go to Give access to..., and Choose people on your network - you can specify your privileged account here with read access so that it can execute the binaries.
  4. Add C:\bin to your computer's %PATH% (not your user's path).
  5. Add .cmd, .bat, and .lnk to your %PATHEXT. Some other notable useful ones might be .jlnp

You can now log in from any computer, from any user, and execute portable binaries such as putty or psexec64.

synchronize Library folders to OneDrive

This is just a feature rather than a workaround, but try to understand which folders make use of your Documents library specifically to store configuration files (as opposed to an absolute path to the Documents folder.)

Moving the Documents library inside OneDrive can easily synchronize your config files for several softwares without you even realizing it. Examples: Azure Data Studio, PowerShell, SSMS, Visual Studio Code.

map OneDrive as a network drive

This isn't really a productivity hack and I've personally never used it. I was asked about the possibility of mounting OneDrive as a network share letter. The use-case scenario was to keep filepaths intact for a network drive to OneDrive migration.

This can be accomplished by issuing net use X: \localhost\C$\Users\k\OneDrive - corp

a repository for dotfiles

I've tried the bare git repository method, but I didn't find it intuitive to set up. I found it far simpler to just choose an arbitrary location (such as $XDG_CONFIG_HOME, $HOME/.config by default) and create separate git repositories inside this structure.

├── alacritty
   ├── .git
   ├── .gitignore
   ├── .stow-local-ignore
   ├── alacritty.yml -> ubuntu-alacritty.yml
   ├── ubuntu-alacritty.yml
   └── win-alacritty.yml
├── macos
   ├── brew_list.txt
   ├── brew_list_cask.txt
   └── setup.sh
├── nvim
   ├── .git
   ├── .stow-local-ignore
   ├── after
   ├── init.lua
   ├── lazy-lock.json
   └── lua
├── tmux
   ├── .git
   ├── .gitmodules
   ├── .stow-local-ignore
   ├── .tmux
   ├── .tmux-darwin
   ├── .tmux.conf
   └── README.md
└── zsh
    ├── .aliases
    ├── .git
    ├── .gitignore
    ├── .stow-local-ignore
    ├── .zim
    ├── .zimrc
    ├── .zprofile
    ├── .zsh_sessions
    ├── .zshenv
    ├── .zshrc
    └── README.md

Using this in conjunction with stow makes it trivial to synchronize the base configuration of cross-platform programs such as neovim while not ignoring isolated cases like tmux.

Note the existence of a .stow-local-ignore and .gitignore in each repository:

$ cat ~/.config/zsh/.stow-local-ignore
.git
.gitignore
.gitmodules
.zsh_history
README.md

*_history files can be moved to $XDG_CACHE_HOME (default $HOME/.cache) to keep the dotfiles organized and to make the setup easier. If you don't manually specify moving these files, you will not be allowed to stow over existing files that are not managed by stow.

Additionally, since tmux is quite flexible and allows for conditional execution of conf files (as seen by .tmux-darwin for macOS), applications without this luxury are simply symlinked (see alacritty repository). this means that one extra step is required during the initial clone.