Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions bin/pbpaste-img
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
#
# Save the current Windows clipboard image into WSL and copy its WSL path.

set -Eeuo pipefail

script_file="$(readlink -f -- "${BASH_SOURCE[0]}")"
script_dir="$(cd -- "$(dirname -- "$script_file")" && pwd -P)"
out_root="${PBPASTE_IMG_DIR:-$HOME/.local/pbpaste-img}"
script_path="$script_dir/pbpaste-img.ps1"
bashlib_path="$script_dir/../zsh/bashlib.sh"

if ! command -v powershell.exe >/dev/null 2>&1; then
echo "ERROR: powershell.exe is required for Windows clipboard access." >&2
exit 1
fi

if ! command -v wslpath >/dev/null 2>&1; then
echo "ERROR: wslpath is required to bridge WSL and Windows paths." >&2
exit 1
fi

mkdir -p "$out_root"

script_path_windows="$(wslpath -w "$script_path")"
out_root_windows="$(wslpath -w "$out_root")"

if [[ -f "$bashlib_path" ]]; then
# shellcheck source=/dev/null
source "$bashlib_path"
fi

powershell_args=(
-NoLogo
-NoProfile
-ExecutionPolicy Bypass
-STA
-File "$script_path_windows"
-OutRootWindows "$out_root_windows"
)

if declare -F is_wsl >/dev/null 2>&1 && is_wsl >/dev/null; then
powershell_args+=(-OutRootWsl "$out_root")
else
powershell_args+=(-WindowsPathToClipboard)
fi

powershell.exe "${powershell_args[@]}" "$@" | tr -d '\r'
97 changes: 97 additions & 0 deletions bin/pbpaste-img.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
[CmdletBinding()]
param(
[string]$OutRootWindows,
[string]$OutRootWsl = $env:PBPASTE_IMG_ROOT_WSL,
[switch]$WindowsPathToClipboard
)

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

function Invoke-WslText {
param([string[]]$Arguments)

$output = & wsl.exe @Arguments
if ($LASTEXITCODE -ne 0) {
throw "wsl.exe $($Arguments -join ' ') failed with exit code $LASTEXITCODE"
}

return (($output -join "`n").Trim())
}

function Invoke-WslChecked {
param([string[]]$Arguments)

& wsl.exe @Arguments | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "wsl.exe $($Arguments -join ' ') failed with exit code $LASTEXITCODE"
}
}

function Join-WslPath {
param(
[string]$Root,
[string]$Child
)

return (($Root.TrimEnd("/", "\")) + "/" + $Child)
}

if ([string]::IsNullOrWhiteSpace($OutRootWsl) -and
[string]::IsNullOrWhiteSpace($OutRootWindows)) {
$wslHome = Invoke-WslText -Arguments @("sh", "-lc", 'printf %s "$HOME"')
$OutRootWsl = Join-WslPath -Root $wslHome -Child ".local/pbpaste-img"
}

$month = Get-Date -Format "yy-MM"
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
$fileName = "$timestamp.png"

if (-not [string]::IsNullOrWhiteSpace($OutRootWsl)) {
$outDirWsl = Join-WslPath -Root $OutRootWsl -Child $month
Invoke-WslChecked -Arguments @("mkdir", "-p", $outDirWsl)
} else {
$outDirWsl = $null
}

if ([string]::IsNullOrWhiteSpace($OutRootWindows)) {
if ([string]::IsNullOrWhiteSpace($outDirWsl)) {
throw "Either -OutRootWindows or -OutRootWsl must be set."
}
$outDirWindows = Invoke-WslText -Arguments @("wslpath", "-w", $outDirWsl)
} else {
$outDirWindows = Join-Path $OutRootWindows $month
New-Item -ItemType Directory -Force -Path $outDirWindows | Out-Null
}

$outFileWindows = Join-Path $outDirWindows $fileName

if (-not [string]::IsNullOrWhiteSpace($outDirWsl)) {
$outFileWsl = Join-WslPath -Root $outDirWsl -Child $fileName
} else {
$outFileWsl = $null
}

$image = [System.Windows.Forms.Clipboard]::GetImage()
if ($null -eq $image) {
Write-Error "No bitmap image found on the clipboard."
exit 1
}

try {
$image.Save($outFileWindows, [System.Drawing.Imaging.ImageFormat]::Png)
} finally {
$image.Dispose()
}

if ($WindowsPathToClipboard -or [string]::IsNullOrWhiteSpace($outFileWsl)) {
$clipboardPath = $outFileWindows
} else {
$clipboardPath = $outFileWsl
}

Set-Clipboard -Value $clipboardPath
Write-Output $clipboardPath
29 changes: 29 additions & 0 deletions css/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# CSS Assets

## `github-markdown.min.css`

Downloaded from Cloudflare cdnjs for local Pandoc/Markdown previews.

- Package: `github-markdown-css`
- Version: `5.8.1`
- Source URL: `https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.8.1/github-markdown.min.css`
- Local path: `$DOTFILES/css/github-markdown.min.css`

## `github-markdown-pandoc.css`

Small local override for Pandoc-generated HTML. The upstream
`github-markdown-css` package expects rendered Markdown to live inside
`.markdown-body`, but it does not set the GitHub-like page width/padding by
itself.

- Local path: `$DOTFILES/css/github-markdown-pandoc.css`
- Adds GitHub's typical `max-width: 980px`, centered layout, and `45px` page
padding for `.markdown-body`.

Example usage:

```bash
GH_MD_CSS="$DOTFILES/css/github-markdown.min.css"
GH_PANDOC_CSS="$DOTFILES/css/github-markdown-pandoc.css"
auto-pandoc calc-liq.md -s --katex --css="$GH_MD_CSS" --css="$GH_PANDOC_CSS" -o index.html
```
19 changes: 19 additions & 0 deletions css/github-markdown-pandoc.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
}

@media (max-width: 767px) {
.markdown-body {
padding: 15px;
}
}

@media (prefers-color-scheme: dark) {
body {
background-color: #0d1117;
}
}
1 change: 1 addition & 0 deletions css/github-markdown.min.css

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ alias t := test

# Install baseline Ubuntu/WSL shell dependencies.
i-bash:
sudo apt install -y build-essential ripgrep gh libclang-dev wslu
sudo apt install -y build-essential ripgrep gh libclang-dev wslu \
ca-certificates gnupg curl trash-cli

# Install shell dependencies needed by CI tests.
i-bash-ci:
Expand Down
22 changes: 12 additions & 10 deletions skillsSync.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ const makeSkill = async (

const runSkillsSync = async (
homeDir: string,
bokuPath: string,
repoPath: string,
args: string[] = ["--run"],
): Promise<void> => {
const proc = Bun.spawn(["bun", scriptPath, ...args], {
cwd: import.meta.dir,
env: {
...process.env,
HOME: homeDir,
BOKU_PATH: bokuPath,
REPO: repoPath,
},
stderr: "pipe",
stdout: "pipe",
Expand Down Expand Up @@ -57,19 +57,20 @@ describe("skills-sync", () => {
let testCfg: {
root: string
syncHomeDir: string
syncBokuPath: string
syncRepoPath: string
syncPublicDir: string
syncPrivateDir: string
dryRunHomeDir: string
dryRunBokuPath: string
dryRunRepoPath: string
dryRunPublicDir: string
}

test("setup fixtures", async () => {
const root = await mkdtemp(join(tmpdir(), "skills-sync-test-"))

const syncHomeDir = join(root, "sync-home")
const syncBokuPath = join(root, "sync-boku")
const syncRepoPath = join(root, "sync-repo")
const syncBokuPath = join(syncRepoPath, "boku")
const syncRuntimeDir = join(syncHomeDir, ".cursor/skills")
const syncPublicDir = join(syncBokuPath, "jiyuu/ai-skills")
const syncPrivateDir = join(syncBokuPath, "priv-skills")
Expand Down Expand Up @@ -111,7 +112,8 @@ describe("skills-sync", () => {
)

const dryRunHomeDir = join(root, "dry-run-home")
const dryRunBokuPath = join(root, "dry-run-boku")
const dryRunRepoPath = join(root, "dry-run-repo")
const dryRunBokuPath = join(dryRunRepoPath, "boku")
const dryRunRuntimeDir = join(dryRunHomeDir, ".cursor/skills")
const dryRunPublicDir = join(dryRunBokuPath, "jiyuu/ai-skills")

Expand All @@ -122,23 +124,23 @@ describe("skills-sync", () => {
testCfg = {
root,
syncHomeDir,
syncBokuPath,
syncRepoPath,
syncPublicDir,
syncPrivateDir,
dryRunHomeDir,
dryRunBokuPath,
dryRunRepoPath,
dryRunPublicDir,
}
})

test("defaults to dry run unless --run is passed", async () => {
await runSkillsSync(testCfg.dryRunHomeDir, testCfg.dryRunBokuPath, [])
await runSkillsSync(testCfg.dryRunHomeDir, testCfg.dryRunRepoPath, [])

expect(await dirNames(testCfg.dryRunPublicDir)).toEqual(["stale-public"])
})

test("syncs direct runtime skills to public and private repos", async () => {
await runSkillsSync(testCfg.syncHomeDir, testCfg.syncBokuPath)
await runSkillsSync(testCfg.syncHomeDir, testCfg.syncRepoPath)

expect(await dirNames(testCfg.syncPublicDir)).toEqual([
"public-false",
Expand Down
8 changes: 5 additions & 3 deletions skillsSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,18 @@ if (help) {

const defaultConfig = (env: NodeJS.ProcessEnv): SkillsSyncConfig => {
const home = env.HOME
const bokuPath = env.BOKU_PATH
const repo = env.REPO

if (!home) {
throw new Error("HOME is not set")
}

if (!bokuPath) {
throw new Error("BOKU_PATH is not set")
if (!repo) {
throw new Error("REPO is not set")
}

const bokuPath = resolve(repo, "boku")

return {
skillsRuntime: resolve(home, ".cursor/skills"),
publicSkillsDir: resolve(bokuPath, "jiyuu/ai-skills"),
Expand Down
19 changes: 9 additions & 10 deletions zsh/aliases.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,27 @@

alias ohmyzsh="nvim ~/.oh-my-zsh"

# MongoDB alias commands
# MongoDB alias commands
alias mongo="/mnt/c/Program\ Files/MongoDB/Server/5.0/bin/mongo.exe"
alias mongod="/mnt/c/Program\ Files/MongoDB/Server/5.0/bin/mongod.exe"
alias mongosh="/mnt/c/Users/realu/AppData/Local/Programs/mongosh/mongosh.exe"
alias mongos="/mnt/c/Program\ Files/MongoDB/Server/5.0/bin/mongos.exe"

# Unique Divine linux commands
alias ls="exa" # cargo install exa
alias la='exa -a'
alias s='sudo'
alias yarn-offline='yarn --prefer-offline'
alias cat="bat" # cargo install bat
alias ls="exa" # cargo install exa
alias la="exa -a"
alias s="sudo"
alias yarn-offline="yarn --prefer-offline"
alias cat="bat" # cargo install bat
# NOTE: This is important - sudo apt install build-essential
alias rm="trash -v"

alias vi="nvim"
alias vim="nvim"

alias rt="ud rs test-short"

# vv: short for "vim view". Piping to vv lets you read stdout in a vi editor
alias vv="view -"
alias vvjq="jq | vv"
alias vvjq="jq | view -"

alias ess="2>&1"

Expand All @@ -34,7 +33,7 @@ git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.ac '!git add -A && git commit'
git config --global alias.ac "!git add -A && git commit"
git config --global core.editor "nvim"

# Broadcast tx and open it in vim.
Expand Down
Loading