Compare commits

..

31 Commits

Author SHA1 Message Date
renovate[bot]
5630200d95 chore(deps): update ivuorinen/actions action (v2025.12.07 → v2025.12.16) (#264)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-17 16:21:29 +02:00
961efec364 feat: switch to biome, apply formatting, shellcheck (#227)
* feat: switch to biome, apply formatting, shellcheck
* chore: apply cr comments
* chore: few config tweaks, shellcheck hook now py-based
* chore: lint fixes and pr comments
* chore(lint): megalinter, and other fixes

Signed-off-by: Ismo Vuorinen <ismo@ivuorinen.net>
2025-12-17 16:03:29 +02:00
4b0e38ffd2 chore(tmux): config cleanup
Signed-off-by: Ismo Vuorinen <ismo@ivuorinen.net>
2025-12-17 12:51:41 +02:00
github-actions[bot]
c6ba0e4036 chore: update pre-commit hooks (#263)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2025-12-15 09:35:47 +02:00
renovate[bot]
7b1ed2f596 chore(deps): update pre-commit hook igorshubovych/markdownlint-cli (v0.46.0 → v0.47.0) (#262)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-13 20:55:07 +00:00
renovate[bot]
82d48c8989 chore(deps): update node.js (v24.11.1 → v24.12.0) (#261)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 14:07:47 +00:00
github-actions[bot]
48f61fa917 chore: update pre-commit hooks (#260)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2025-12-11 13:56:31 +02:00
renovate[bot]
abc3408609 chore(deps): update image python to v3.14.2 (#259)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-11 04:16:31 +00:00
renovate[bot]
8bef11095e chore(deps)!: update peter-evans/create-pull-request (v7.0.11 → v8.0.0) (#258) 2025-12-10 01:23:11 +02:00
7d427d29bb chore: update workflows, go and yarn (#253) 2025-12-08 20:40:21 +02:00
renovate[bot]
fd71a1ad32 chore(deps): update peter-evans/create-pull-request action (v7.0.9 → v7.0.11) (#256)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-08 05:48:14 +00:00
renovate[bot]
277d47098f chore(deps): update image python to v3.14.1 (#255)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-08 05:48:06 +00:00
github-actions[bot]
d35014ed2e chore: update pre-commit hooks (#257) 2025-12-08 07:41:13 +02:00
github-actions[bot]
8e7af8ddc7 chore: update pre-commit hooks (#254) 2025-12-04 12:06:46 +02:00
099e6672c8 chore: upgrade actions 2025-12-02 23:54:02 +01:00
e578e52aff chore: upgrade yarn 2025-12-02 23:29:04 +01:00
renovate[bot]
0b5f80cb03 chore(deps): update pre-commit hook renovatebot/pre-commit-hooks (42.27.0 → 42.27.1) (#251)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-01 09:15:57 +02:00
github-actions[bot]
72f42835ff chore: update pre-commit hooks (#252)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2025-12-01 09:14:14 +02:00
renovate[bot]
a949f0d4cf chore(deps): update actions/setup-python action (v6.0.0 → v6.1.0) (#250)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-27 05:54:45 +00:00
renovate[bot]
8b1e4462b3 chore(deps): update ivuorinen/actions action (v2025.11.02 → v2025.11.23) (#249)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-27 05:54:39 +00:00
github-actions[bot]
055cf7ef2e chore: update pre-commit hooks (#242) 2025-11-27 07:51:23 +02:00
renovate[bot]
8c2b3fb475 chore(deps): update peter-evans/create-pull-request action (v7.0.8 → v7.0.9) (#246)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-24 18:39:10 +00:00
3fa1efe88d chore(ci): remove .github/dependabot.yml
Signed-off-by: Ismo Vuorinen <ismo@ivuorinen.net>
2025-11-24 14:21:30 +02:00
9cc81c4cbf chore(deps): update github actions 2025-11-22 09:40:16 +02:00
bba76843db chore(deps): update pre-commit hooks 2025-11-22 09:39:37 +02:00
9018d1a038 chore(deps): update go version to 1.25.4 2025-11-22 09:38:39 +02:00
github-actions[bot]
a8595e2e07 chore: update pre-commit hooks (#241) 2025-11-17 08:10:49 +02:00
renovate[bot]
beb89e9490 chore(deps): update pre-commit hook renovatebot/pre-commit-hooks (42.7.0 → 42.11.0) (#240)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-17 04:10:37 +00:00
dependabot[bot]
cb381fe57d chore(deps): bump js-yaml in the npm_and_yarn group across 1 directory (#239) 2025-11-16 01:22:30 +02:00
renovate[bot]
7be770a2af chore(deps): update node.js (v24.11.0 → v24.11.1) (#238)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-15 00:39:45 +00:00
github-actions[bot]
d16ce9ad0f chore: update pre-commit hooks (#237) 2025-11-13 13:21:31 +02:00
96 changed files with 888 additions and 9266 deletions

View File

@@ -1,53 +0,0 @@
{{- $hostname := .chezmoi.hostname -}}
{{- $username := .chezmoi.username -}}
{{- $osid := .chezmoi.os -}}
sourceDir: {{ .chezmoi.sourceDir | quote }}
data:
hostname: {{ $hostname | quote }}
username: {{ $username | quote }}
osid: {{ $osid | quote }}
# Detect if we're on macOS
is_macos: {{ eq $osid "darwin" }}
# Detect if we're on Linux
is_linux: {{ eq $osid "linux" }}
# Host-specific flags
is_air: {{ eq $hostname "air" }}
is_lakka: {{ eq $hostname "lakka" }}
is_tunkki: {{ eq $hostname "tunkki" }}
is_s: {{ eq $hostname "s" }}
# Merge strategy for dealing with conflicts
merge:
command: "nvim"
args:
- "-d"
- "{{ "{{" }} .Destination {{ "}}" }}"
- "{{ "{{" }} .Source {{ "}}" }}"
- "{{ "{{" }} .Target {{ "}}" }}"
# Template options
template:
options:
- "missingkey=error"
# Diff options
diff:
exclude:
- "scripts"
pager: "delta"
# Git options
git:
autoCommit: false
autoPush: false
# Hooks
hooks:
read-source-state:
pre:
command: ".local/share/chezmoi/.chezmoihooks/pre-read-source-state.sh"

View File

@@ -1,13 +0,0 @@
#!/usr/bin/env bash
# Pre-read-source-state hook for chezmoi
# This runs before chezmoi reads the source state
set -e
DOTFILES="${CHEZMOI_SOURCE_DIR:-$HOME/.local/share/chezmoi}"
# Update git submodules if they exist
if [ -d "$DOTFILES/.git" ]; then
cd "$DOTFILES"
git submodule update --init --recursive --quiet || true
fi

View File

@@ -1,90 +0,0 @@
# Chezmoi ignore file
# Files and directories that should not be managed by chezmoi
# Git and version control
.git/
.gitignore
.gitattributes
.gitmodules
# GitHub
.github/
# Documentation
README.md
*.md
docs/
AGENTS.md
# Development tools
.vscode/
.serena/
.claude/
node_modules/
# Testing
tests/
test-all.sh
# Configuration files for the repo itself
.editorconfig
.editorconfig-checker.json
.eslintrc.json
.prettierrc.js
.prettierignore
.markdownlint.json
.markdownlintignore
.mega-linter.yml
.commitlintrc.json
.releaserc.json
.shellcheckrc
.yamlignore
.yamllint.yml
.browserslistrc
.actrc
.luarc.json
.ignore
stylua.toml
phpcs.xml
# Package management
package.json
yarn.lock
# Python and Node version files
.python-version
.nvmrc
.go-version
# Dotbot (old system)
install.conf.yaml
tools/dotbot/
tools/dotbot-*/
tools/dotbot-defaults.yaml
# Installation and build scripts in root
install
add-submodules.sh
# Chezmoi-specific directories (not to be managed)
.chezmoihooks/
# Host-specific directories (will be handled via templates)
{{- if not .is_air }}
hosts/air/
{{- end }}
{{- if not .is_lakka }}
hosts/lakka/
{{- end }}
{{- if not .is_tunkki }}
hosts/tunkki/
{{- end }}
{{- if not .is_s }}
hosts/s/
{{- end }}
# Secrets (should use separate secrets management)
secrets/
# macOS specific files
.DS_Store

View File

@@ -9,7 +9,7 @@ insert_final_newline = true
trim_trailing_whitespace = true
[*.fish]
max_line_length = 80
max_line_length = 120
[*.md]
max_line_length = 120
@@ -49,3 +49,6 @@ ignore = true
[plan]
trim_trailing_whitespace = false
max_line_length = off
[base/hammerspoon/hammerspoon.types.lua]
max_line_length = off

View File

@@ -1,3 +0,0 @@
{
"extends": ["@ivuorinen"]
}

View File

@@ -1,8 +0,0 @@
---
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'weekly'

View File

@@ -16,10 +16,10 @@ module.exports = {
excludeTypes: [],
renderTypeSection: function (label, commits) {
renderTypeSection: (label, commits) => {
let text = `\n## ${label}\n\n`
commits.forEach(commit => {
commits.forEach((commit) => {
const scope = commit.scope ? `**${commit.scope}:** ` : ''
text += `- ${scope}${commit.subject}\n`
})
@@ -27,10 +27,10 @@ module.exports = {
return text
},
renderChangelog: function (release, changes) {
renderChangelog: (release, changes) => {
const now = new Date()
const d = now.toISOString().substring(0, 10)
const header = `# ${release} - ${d}\n`
return header + changes + '\n\n'
return `${header}${changes}\n\n`
},
}

View File

@@ -18,7 +18,7 @@ jobs:
permissions: write-all
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Create changelog text
id: changelog

View File

@@ -27,7 +27,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Yarn Lock Changes
uses: Simek/yarn-lock-changes@61d1a0595070b79c1abdc8e1e5a5f5d98b18918c # v0.12.2
@@ -35,4 +35,4 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Run PR Lint
uses: ivuorinen/actions/pr-lint@ff0ca4bc920c518b2ce2dc20c5e5a6e95f76dee0 # v2025.11.02
uses: ivuorinen/actions/pr-lint@f6ed49a6dda8b718d3cdfca095dd155c2543f359 # v2025.12.16

View File

@@ -24,7 +24,7 @@ jobs:
version: ${{ steps.daily-version.outputs.version }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Create tag if necessary
uses: fregante/daily-version-action@fb1a60b7c4daf1410cd755e360ebec3901e58588 # v2.1.3
@@ -40,7 +40,7 @@ jobs:
- name: Create release
if: steps.daily-version.outputs.created
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag_name: ${{ steps.daily-version.outputs.version }}

View File

@@ -23,13 +23,13 @@ jobs:
pull-requests: write
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
- uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
- run: pip install pre-commit && pre-commit autoupdate
- uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
- uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: update/pre-commit-hooks

View File

@@ -29,4 +29,4 @@ jobs:
issues: write
steps:
- uses: ivuorinen/actions/sync-labels@ff0ca4bc920c518b2ce2dc20c5e5a6e95f76dee0 # v2025.11.02
- uses: ivuorinen/actions/sync-labels@f6ed49a6dda8b718d3cdfca095dd155c2543f359 # v2025.12.16

View File

@@ -22,7 +22,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
submodules: true
fetch-depth: 2

1
.gitignore vendored
View File

@@ -11,6 +11,7 @@
.nfs*
.scannerwork
.vscode
.yarn/
!config/git/local.d/.gitkeep
!config/nvim/spell/.gitkeep
!config/zed/settings.json

View File

@@ -1 +1 @@
1.25.3
1.25.5

View File

@@ -1,19 +0,0 @@
{
"extends": "@ivuorinen/markdownlint-config",
"code-block-style": {
"style": "fenced"
},
"code-fence-style": {
"style": "backtick"
},
"heading-style": {
"style": "atx"
},
"no-duplicate-heading": {
"siblings_only": true
},
"required-headings": false,
"ul-style": {
"style": "dash"
}
}

View File

@@ -16,12 +16,9 @@ SHOW_SKIPPED_LINTERS: false # Show skipped linters in MegaLinter log
TYPESCRIPT_DEFAULT_STYLE: prettier # Default style for TypeScript
DISABLE_LINTERS:
- REPOSITORY_DEVSKIM
- JAVASCRIPT_ES
- JAVASCRIPT_ES # using biome
- JAVASCRIPT_PRETTIER # using biome
YAML_YAMLLINT_CONFIG_FILE: .yamllint.yml
MARKDOWN_MARKDOWNLINT_CONFIG_FILE: .markdownlint.json
JAVASCRIPT_ES_CONFIG_FILE: .eslintrc.json
TYPESCRIPT_ES_CONFIG_FILE: .eslintrc.json
REPOSITORY_GIT_DIFF_DISABLE_ERRORS: true
FILTER_REGEX_EXCLUDE: >
(node_modules|tools|config/cheat/cheatsheets/community|config/cheat/cheatsheets/tldr|config/fzf|config/zsh|config/tmux/plugins)

2
.nvmrc
View File

@@ -1 +1 @@
24.11.0
24.12.0

View File

@@ -20,22 +20,22 @@ repos:
- id: end-of-file-fixer
- id: mixed-line-ending
args: [--fix=auto]
- id: pretty-format-json
args: [--autofix, --no-sort-keys]
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.45.0
- repo: local
hooks:
- id: markdownlint
args: [-c, .markdownlint.json, --fix]
- id: biome-check
name: Biome Check
entry: yarn biome check --write --files-ignore-unknown=true --no-errors-on-unmatched
language: system
files: \.(js|ts|jsx|tsx|json|md)$
- repo: https://github.com/adrienverge/yamllint
rev: v1.37.1
hooks:
- id: yamllint
- repo: https://github.com/koalaman/shellcheck-precommit
rev: v0.11.0
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.11.0.1
hooks:
- id: shellcheck
@@ -45,19 +45,15 @@ repos:
- id: shfmt
- repo: https://github.com/rhysd/actionlint
rev: v1.7.8
rev: v1.7.9
hooks:
- id: actionlint
- repo: https://github.com/renovatebot/pre-commit-hooks
rev: 42.2.0
hooks:
- id: renovate-config-validator
- repo: https://github.com/JohnnyMorganz/StyLua
rev: v2.3.1
hooks:
- id: stylua # or stylua-system / stylua-github
exclude: hammerspoon\.types\.lua$
- repo: https://github.com/hugoh/pre-commit-fish.git
rev: v1.2

View File

@@ -1,16 +0,0 @@
# vim: ft=gitignore
.mypy_cache/*
Brewfile.lock.json
base/plan
config/cheat/cheatsheets/community
config/cheat/cheatsheets/tldr
config/fzf/*
config/nvim/*
config/op/plugins/used_plugins/*
config/tmux/plugins/*
config/zsh/*
lazy-lock.json
local/bin/antigen.zsh
local/bin/asdf
tools/antidote/*
tools/dotbot*

View File

@@ -1,15 +0,0 @@
module.exports = {
...require('@ivuorinen/prettier-config'),
trailingComma: 'all',
// Add custom options below:
overrides: [
{
files: '*.md',
options: {
printWidth: 120,
proseWrap: 'preserve',
tabWidth: 2,
},
},
],
}

View File

@@ -1 +1 @@
3.14.0
3.14.2

View File

@@ -0,0 +1,5 @@
{
"sonarCloudOrganization": "ivuorinen",
"projectKey": "ivuorinen_dotfiles",
"region": "EU"
}

1
.yarnrc.yml Normal file
View File

@@ -0,0 +1 @@
nodeLinker: node-modules

View File

@@ -2673,7 +2673,7 @@ function canvas:delete(fadeOutTime) end
--- optionally return false to indicate that you do not wish to accept the item being dragged.
--- "exit" - the user has moved the item out of the canvas; if the previous "enter" callback returned false, this
--- message will also occur when the user finally releases the items being dragged.
--- "receive" - indicates that the user has released the dragged object while it is still within the canvas frame.
--- "receive" - indicates that the user has released the dragged object while it is still within the canvas frame.
--- When your callback receives this message, you can optionally return false to indicate to the sending application
--- that you do not want to accept the dragged item -- this may affect the animations provided by the sending
--- application.
@@ -2810,7 +2810,7 @@ function canvas:minimumTextSize(index, text) end
--- element. The message will be "mouseDown".
--- trackMouseUp - indicates that a callback should be invoked when a mouse button has been released over the canvas
--- element. The message will be "mouseUp".
--- trackMouseEnterExit - indicates that a callback should be invoked when the mouse pointer enters or exits the
--- trackMouseEnterExit - indicates that a callback should be invoked when the mouse pointer enters or exits the
--- canvas element. The message will be "mouseEnter" or "mouseExit".
--- trackMouseMove - indicates that a callback should be invoked when the mouse pointer moves within the canvas
--- element. The message will be "mouseMove".
@@ -4197,7 +4197,7 @@ hs.drawing.windowLevels = nil
--- hs.drawing
--- for text drawing objects.
---
--- Note: This method returns the default font, size, color, and paragraphStyle used by hs.drawing for text objects.
--- Note: This method returns the default font, size, color, and paragraphStyle used by hs.drawing for text objects.
--- If you modify a drawing object's defaults with hs.drawing:setColor , hs.drawing:setTextFont , or
--- hs.drawing:setTextSize , the changes will not be reflected by this function.
---@return table
@@ -4662,7 +4662,7 @@ hs.drawing.color.ansiTerminalColors = nil
---@type table
hs.drawing.color.hammerspoon = nil
--- A collection of colors representing the X11 color names as defined at
--- A collection of colors representing the X11 color names as defined at
--- https://en.wikipedia.org/wiki/Web_colors#X11_color_names (names in lowercase)
---@type any
hs.drawing.color.x11 = nil
@@ -7022,7 +7022,7 @@ function hs.http.doAsyncRequest(url, method, data, headers, callback, cachePolic
--- use the asynchronous functions.
--- If you attempt to connect to a local Hammerspoon server created with hs.httpserver , then Hammerspoon will block
--- until the connection times out (60 seconds), return a failed result due to the timeout, and then the hs.httpserver
--- callback function will be invoked (so any side effects of the function will occur, but it's results will be lost).
--- callback function will be invoked (so any side effects of the function will occur, but it's results will be lost).
--- Use hs.http.doAsyncRequest to avoid this.
--- If the Content-Type response header begins text/ then the response body return value is a UTF8 string. Any other
--- content type passes the response body, unaltered, as a stream of bytes.
@@ -7054,7 +7054,7 @@ function hs.http.encodeForQuery(string) end
--- are encouraged to use the asynchronous functions
--- If you attempt to connect to a local Hammerspoon server created with hs.httpserver , then Hammerspoon will block
--- until the connection times out (60 seconds), return a failed result due to the timeout, and then the hs.httpserver
--- callback function will be invoked (so any side effects of the function will occur, but it's results will be lost).
--- callback function will be invoked (so any side effects of the function will occur, but it's results will be lost).
--- Use hs.http.asyncGet to avoid this.
---@param url string
---@param headers table|nil
@@ -7072,7 +7072,7 @@ function hs.http.get(url, headers) end
--- are encouraged to use the asynchronous functions
--- If you attempt to connect to a local Hammerspoon server created with hs.httpserver , then Hammerspoon will block
--- until the connection times out (60 seconds), return a failed result due to the timeout, and then the hs.httpserver
--- callback function will be invoked (so any side effects of the function will occur, but it's results will be lost).
--- callback function will be invoked (so any side effects of the function will occur, but it's results will be lost).
--- Use hs.http.asyncPost to avoid this.
---@param url string
---@param data string|nil
@@ -7091,7 +7091,7 @@ function hs.http.post(url, data, headers) end
--- are encouraged to use the asynchronous functions
--- If you attempt to connect to a local Hammerspoon server created with hs.httpserver , then Hammerspoon will block
--- until the connection times out (60 seconds), return a failed result due to the timeout, and then the hs.httpserver
--- callback function will be invoked (so any side effects of the function will occur, but it's results will be lost).
--- callback function will be invoked (so any side effects of the function will occur, but it's results will be lost).
--- Use hs.http.asyncPost to avoid this.
---@param url string
---@param data string|nil
@@ -7374,7 +7374,7 @@ function hs.httpserver.hsminweb.new(documentRoot) end
--- Get or set the access-list table for the hsminweb web server
---
--- Note: The access-list feature works by comparing the request headers against a list of tests which either accept or
--- reject the request. If no access list is set (i.e. it is assigned a value of nil ), then all requests are served.
--- reject the request. If no access list is set (i.e. it is assigned a value of nil ), then all requests are served.
--- If a table is passed into this method, then any request which is not explicitly accepted by one of the tests
--- provided is rejected (i.e. there is an implicit "reject" at the end of the list).
--- The access-list table is a list of tests which are evaluated in order. The first test which matches a given
@@ -7919,7 +7919,7 @@ function hs.httpserver.hsminweb.cgilua.urlcode.insertfield(table, key, value) en
--- Parse the query string and store the key-value pairs in the provided table.
---
--- Note: The specification allows for the same key to be assigned multiple values in an encoded string, but does not
--- specify the behavior; by convention, web servers assign these multiple values to the same key in an array (table).
--- specify the behavior; by convention, web servers assign these multiple values to the same key in an array (table).
--- This function follows that convention. This is most commonly used by forms which allow selecting multiple options
--- via check boxes or in a selection list.
--- This function uses cgilua.urlcode.insertfield to build the key-value table.
@@ -10225,7 +10225,7 @@ function echorequest:seeAllUnexpectedPackets(state) end
--- Sends a single ICMP Echo Request packet.
---
--- Note: By convention, unless you are trying to test for specific network fragmentation or congestion problems, ICMP
--- Echo Requests are generally 64 bytes in length (this includes the 8 byte header, giving 56 bytes of payload data).
--- Echo Requests are generally 64 bytes in length (this includes the 8 byte header, giving 56 bytes of payload data).
--- If you do not specify a payload, a default payload which will result in a packet size of 64 bytes is constructed.
---@param payload string|nil
---@return echoRequestObject|boolean|nil
@@ -15169,7 +15169,7 @@ function watcher:stop() end
---@class hs.utf8
hs.utf8 = {}
--- A collection of UTF-8 characters already converted from codepoint and available as convenient key-value pairs.
--- A collection of UTF-8 characters already converted from codepoint and available as convenient key-value pairs.
--- UTF-8 printable versions of common Apple and OS X special keys are predefined and others can be added with
--- hs.utf8.registerCodepoint(label, codepoint)
--- for your own use.
@@ -15238,7 +15238,7 @@ function hs.utf8.hexDump(inputString, count) end
--- hs.utf8.registeredKeys[label]
--- for convenience and readability.
---
--- Note: If a codepoint label was previously registered, this will overwrite the previous value with a new one.
--- Note: If a codepoint label was previously registered, this will overwrite the previous value with a new one.
--- Because many of the special keys you may want to register have different variants, this allows you to easily modify
--- the existing predefined defaults to suite your preferences.
--- The return value is merely syntactic sugar and you do not need to save it locally; it can be safely ignored --
@@ -15585,13 +15585,13 @@ function hs.webview.newBrowser(rect, preferencesTable, userContentController) en
---@return webviewObject
function webview:allowGestures(value) end
--- Get or set whether or not the webview will respond to magnification gestures from a trackpad or magic mouse.
--- Get or set whether or not the webview will respond to magnification gestures from a trackpad or magic mouse.
--- Default is false.
---@param value any
---@return webviewObject
function webview:allowMagnificationGestures(value) end
--- Get or set whether or not the webview will respond to the navigation gestures from a trackpad or magic mouse.
--- Get or set whether or not the webview will respond to the navigation gestures from a trackpad or magic mouse.
--- Default is false.
---@param value any
---@return webviewObject
@@ -16455,7 +16455,7 @@ function usercontent:removeAllScripts() end
--- } catch(err) {
--- console.log('The controller does not exist yet');
--- }
--- Where name matches the name specified in the constructor and message-object is the object to post to the function.
--- Where name matches the name specified in the constructor and message-object is the object to post to the function.
--- This object can be a number, string, date, array, dictionary(table), or nil.
---@param fn function
---@return usercontentControllerObject
@@ -17860,4 +17860,4 @@ hs.window.tiling = {}
---@param preserveRelativeArea? any
---@param animationDuration? hs.window.animationDuration|nil
---@return any
function hs.window.tiling.tileWindows(windows, rect, desiredAspect, processInOrder, preserveRelativeArea, animationDuration) end
function hs.window.tiling.tileWindows(windows, rect, desiredAspect, processInOrder, preserveRelativeArea, animationDuration) end

View File

@@ -193,11 +193,12 @@ end)
-- Paste 1Password secret with Meh + P
f18:bind({}, 'p', function()
local output, status = hs.execute('op read "op://Svea/3hzhctmvovbwlgulv7mgy25rf4/login-input"', true)
local output, status =
hs.execute('op read "op://Svea/3hzhctmvovbwlgulv7mgy25rf4/login-input"', true)
if status then
hs.eventtap.keyStrokes(output:gsub('%s+$', '')) -- trim trailing whitespace
else
hs.alert.show('1Password CLI error')
hs.alert.show '1Password CLI error'
end
end)

103
biome.json Normal file
View File

@@ -0,0 +1,103 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.1/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true,
"defaultBranch": "main"
},
"files": {
"ignoreUnknown": true,
"includes": [
"**",
"!!**/.mypy_cache",
"!!**/Brewfile.lock.json",
"!!**/base/plan",
"!!**/config/cheat/cheatsheets/community",
"!!**/config/cheat/cheatsheets/tldr",
"!!**/config/fzf",
"!!**/config/nvim",
"!!**/config/op/plugins/used_plugins",
"!!**/config/tmux/plugins",
"!!**/config/zsh",
"!!**/config/vim",
"!!**/lazy-lock.json",
"!!**/local/bin/antigen.zsh",
"!!**/local/bin/asdf",
"!!**/tools/antidote",
"!!**/tools/dotbot",
"!!**/node_modules"
]
},
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentWidth": 2,
"lineEnding": "lf",
"lineWidth": 80
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noUnusedVariables": "warn",
"noUnusedImports": "warn"
},
"style": {
"useConst": "warn",
"useTemplate": "warn"
},
"suspicious": {
"noExplicitAny": "warn",
"noConsole": "off"
}
}
},
"javascript": {
"formatter": {
"enabled": true,
"quoteStyle": "single",
"jsxQuoteStyle": "double",
"trailingCommas": "all",
"semicolons": "asNeeded",
"arrowParentheses": "always",
"bracketSpacing": true,
"bracketSameLine": false,
"quoteProperties": "asNeeded",
"indentStyle": "space",
"indentWidth": 2
}
},
"json": {
"parser": {
"allowComments": true,
"allowTrailingCommas": false
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 80
}
},
"overrides": [
{
"includes": ["*.md", "*.mdx"],
"formatter": {
"enabled": true,
"lineWidth": 120
}
},
{
"includes": ["package.json"],
"json": {
"formatter": {
"enabled": true,
"indentWidth": 2
}
}
}
]
}

View File

@@ -6,21 +6,19 @@
*
* @param {Object} windows - All windows in the current space.
* @param {Object} screenFrame - The frame of the current screen.
* @param {Object} state - The state of the current space.
* @param {Object} extendedFrames - The frames of the windows in the current space.
* @return {Object} - The frames for the windows in the current space.
*/
function layout() {
return {
name: 'Almost Maximize',
getFrameAssignments: (windows, screenFrame, state, extendedFrames) => {
getFrameAssignments: (windows, screenFrame) => {
const width = screenFrame.width * 0.95
const height = screenFrame.height * 0.95
const x = (screenFrame.width - width) / 2
const y = (screenFrame.height - height) / 2
const windowFrames = {}
windows.forEach(window => {
windows.forEach((window) => {
windowFrames[window.id] = {
Y: screenFrame.y + y,
x: screenFrame.x + x,
@@ -33,3 +31,5 @@ function layout() {
},
}
}
module.exports = layout()

View File

@@ -1,5 +1,3 @@
#!/usr/bin/env bash
#
# This file is secret and wont be added to the git repo.
export GITLAB_API_TOKEN=""

0
config/fish/completions/docker.fish Executable file → Normal file
View File

View File

@@ -26,7 +26,7 @@ if status is-interactive
# type -q fnm; and fnm env --use-on-cd --shell fish | source
type -q load_nvm; and load_nvm >/dev/stderr
# Intialize other tools if available
# Initialize other tools if available
type -q zoxide; and zoxide init fish | source
# Start tmux if not already running and not in SSH
@@ -40,7 +40,7 @@ set -gx PATH $PATH $HOME/.lmstudio/bin
# vim: ft=fish ts=4 sw=4 et:
# opencode
fish_add_path /Users/ivuorinen/.opencode/bin
fish_add_path $HOME/.opencode/bin
# Added by OrbStack: command-line tools and integration
# This won't be added again if you remove it.

View File

@@ -1,5 +1,3 @@
#!/usr/bin/env fish
# XDG Base Directory Specification
set -q XDG_CONFIG_HOME; or set -x XDG_CONFIG_HOME "$HOME/.config"
set -q XDG_DATA_HOME; or set -x XDG_DATA_HOME "$HOME/.local/share"

View File

@@ -26,7 +26,6 @@ Options:
return 1
end
if set --query _flag_exact
set --function apps (__macos_app_find --exact $argv)
or return 1

View File

@@ -139,7 +139,6 @@ Options:
return 0
end
__macos_mac_touchid_sudo::check_supported
or return

View File

@@ -1,23 +1,25 @@
function __ssh_agent_is_started -d "check if ssh agent is already started"
if test -n "$SSH_CONNECTION"
# This is an SSH session
ssh-add -l > /dev/null 2>&1
if test $status -eq 0 -o $status -eq 1
# An SSH agent was forwarded
return 0
end
end
if test -n "$SSH_CONNECTION"
# This is an SSH session
ssh-add -l >/dev/null 2>&1
if test $status -eq 0 -o $status -eq 1
# An SSH agent was forwarded
return 0
end
end
if begin; test -f "$SSH_ENV"; and test -z "$SSH_AGENT_PID"; end
source $SSH_ENV > /dev/null
end
if begin
test -f "$SSH_ENV"; and test -z "$SSH_AGENT_PID"
end
source $SSH_ENV >/dev/null
end
if test -z "$SSH_AGENT_PID"
return 1
end
if test -z "$SSH_AGENT_PID"
return 1
end
ssh-add -l > /dev/null 2>&1
if test $status -eq 2
return 1
end
ssh-add -l >/dev/null 2>&1
if test $status -eq 2
return 1
end
end

View File

@@ -1,5 +1,5 @@
function __ssh_agent_start -d "start a new ssh agent"
ssh-agent -c | sed 's/^echo/#echo/' > $SSH_ENV
chmod 600 $SSH_ENV
source $SSH_ENV > /dev/null
ssh-agent -c | sed 's/^echo/#echo/' >$SSH_ENV
chmod 600 $SSH_ENV
source $SSH_ENV >/dev/null
end

View File

@@ -3,10 +3,8 @@ function _fzf_extract_var_info --argument-names variable_name set_show_output --
# Extract only the lines about the variable, all of which begin with either
# $variable_name: ...or... $variable_name[
string match --regex "^\\\$$variable_name(?::|\[).*" <$set_show_output |
# Strip the variable name prefix, including ": " for scope info lines
string replace --regex "^\\\$$variable_name(?:: )?" '' |
# Distill the lines of values, replacing...
# [1]: |value|
# ...with...

View File

@@ -24,7 +24,6 @@ function _fzf_search_directory --description "Search the current directory. Repl
set -f file_paths_selected ($fd_cmd 2>/dev/null | _fzf_wrapper $fzf_arguments)
end
if test $status -eq 0
commandline --current-token --replace -- (string escape -- $file_paths_selected | string join ' ')
end

View File

@@ -1,8 +1,8 @@
function _puffer_fish_expand_bang
switch (commandline -t)
case '!'
commandline -t $history[1]
case '*'
commandline -i '!'
case '!'
commandline -t $history[1]
case '*'
commandline -i '!'
end
end

View File

@@ -1,9 +1,9 @@
function _puffer_fish_expand_lastarg
switch (commandline -t)
case '!'
commandline -t ""
commandline -f history-token-search-backward
case '*'
commandline -i '$'
case '!'
commandline -t ""
commandline -f history-token-search-backward
case '*'
commandline -i '$'
end
end

View File

@@ -1,5 +1,5 @@
function _sponge_clear_state
set --erase --global _sponge_current_command
set --erase --global _sponge_current_command_exit_code
set --erase --global _sponge_current_command_previously_in_history
set --erase --global _sponge_current_command
set --erase --global _sponge_current_command_exit_code
set --erase --global _sponge_current_command_previously_in_history
end

View File

@@ -1,3 +1,3 @@
function _sponge_on_exit --on-event fish_exit
sponge_delay=0 _sponge_remove_from_history
sponge_delay=0 _sponge_remove_from_history
end

View File

@@ -1,24 +1,24 @@
function _sponge_on_postexec --on-event fish_postexec
set --global _sponge_current_command_exit_code $status
set --global _sponge_current_command_exit_code $status
# Remove command from the queue if it's been added previously
if set --local index (contains --index -- $_sponge_current_command $_sponge_queue)
set --erase _sponge_queue[$index]
end
# Ignore empty commands
if test -n $_sponge_current_command
set --local command ''
# Run filters
for filter in $sponge_filters
if $filter \
$_sponge_current_command \
$_sponge_current_command_exit_code \
$_sponge_current_command_previously_in_history
set command $_sponge_current_command
break
end
# Remove command from the queue if it's been added previously
if set --local index (contains --index -- $_sponge_current_command $_sponge_queue)
set --erase _sponge_queue[$index]
end
# Ignore empty commands
if test -n $_sponge_current_command
set --local command ''
# Run filters
for filter in $sponge_filters
if $filter \
$_sponge_current_command \
$_sponge_current_command_exit_code \
$_sponge_current_command_previously_in_history
set command $_sponge_current_command
break
end
end
set --prepend --global _sponge_queue $command
end
set --prepend --global _sponge_queue $command
end
end

View File

@@ -1,16 +1,16 @@
function _sponge_on_preexec --on-event fish_preexec \
--argument-names command
_sponge_clear_state
--argument-names command
_sponge_clear_state
set --global _sponge_current_command $command
set --global _sponge_current_command $command
builtin history search --case-sensitive --exact --max=1 --null $command \
| read --local --null found_entries
builtin history search --case-sensitive --exact --max=1 --null $command \
| read --local --null found_entries
# If a command is in the history and in the queue, ignore it, like if it wasnt in the history
if test (count $found_entries) -ne 0; and not contains $command $_sponge_queue
set --global _sponge_current_command_previously_in_history true
else
set --global _sponge_current_command_previously_in_history false
end
# If a command is in the history and in the queue, ignore it, like if it wasnt in the history
if test (count $found_entries) -ne 0; and not contains $command $_sponge_queue
set --global _sponge_current_command_previously_in_history true
else
set --global _sponge_current_command_previously_in_history false
end
end

View File

@@ -1,5 +1,5 @@
function _sponge_on_prompt --on-event fish_prompt
if test $sponge_purge_only_on_exit = false
_sponge_remove_from_history
end
if test $sponge_purge_only_on_exit = false
_sponge_remove_from_history
end
end

View File

@@ -1,9 +1,9 @@
function _sponge_remove_from_history
while test (count $_sponge_queue) -gt $sponge_delay
builtin history delete --case-sensitive --exact -- $_sponge_queue[-1]
set --erase _sponge_queue[-1]
end
while test (count $_sponge_queue) -gt $sponge_delay
builtin history delete --case-sensitive --exact -- $_sponge_queue[-1]
set --erase _sponge_queue[-1]
end
builtin history save
builtin history save
end

View File

@@ -1,29 +1,29 @@
function bass
set -l bash_args $argv
set -l bass_debug
if test "$bash_args[1]_" = '-d_'
set bass_debug true
set -e bash_args[1]
end
set -l bash_args $argv
set -l bass_debug
if test "$bash_args[1]_" = -d_
set bass_debug true
set -e bash_args[1]
end
set -l script_file (mktemp)
if command -v python3 >/dev/null 2>&1
command python3 -sS (dirname (status -f))/__bass.py $bash_args 3>$script_file
else
command python -sS (dirname (status -f))/__bass.py $bash_args 3>$script_file
end
set -l bass_status $status
if test $bass_status -ne 0
return $bass_status
end
set -l script_file (mktemp)
if command -v python3 >/dev/null 2>&1
command python3 -sS (dirname (status -f))/__bass.py $bash_args 3>$script_file
else
command python -sS (dirname (status -f))/__bass.py $bash_args 3>$script_file
end
set -l bass_status $status
if test $bass_status -ne 0
return $bass_status
end
if test -n "$bass_debug"
cat $script_file
end
source $script_file
command rm $script_file
if test -n "$bass_debug"
cat $script_file
end
source $script_file
command rm $script_file
end
function __bass_usage
echo "Usage: bass [-d] <bash-command>"
echo "Usage: bass [-d] <bash-command>"
end

View File

@@ -1,16 +1,16 @@
function load_nvm --on-variable="PWD"
set -l default_node_version (nvm version default)
set -l node_version (nvm version)
set -l nvmrc_path (nvm_find_nvmrc)
if test -n "$nvmrc_path"
set -l nvmrc_node_version (nvm version (cat $nvmrc_path))
if test "$nvmrc_node_version" = "N/A"
nvm install (cat $nvmrc_path)
else if test "$nvmrc_node_version" != "$node_version"
nvm use $nvmrc_node_version
set -l default_node_version (nvm version default)
set -l node_version (nvm version)
set -l nvmrc_path (nvm_find_nvmrc)
if test -n "$nvmrc_path"
set -l nvmrc_node_version (nvm version (cat $nvmrc_path))
if test "$nvmrc_node_version" = N/A
nvm install (cat $nvmrc_path)
else if test "$nvmrc_node_version" != "$node_version"
nvm use $nvmrc_node_version
end
else if test "$node_version" != "$default_node_version"
echo "Reverting to default Node version"
nvm use default
end
else if test "$node_version" != "$default_node_version"
echo "Reverting to default Node version"
nvm use default
end
end

View File

@@ -1,3 +1,3 @@
function nvm_find_nvmrc
bass source $NVM_DIR/nvm.sh --no-use ';' nvm_find_nvmrc
bass source $NVM_DIR/nvm.sh --no-use ';' nvm_find_nvmrc
end

View File

@@ -158,7 +158,7 @@ function paths --description "Reveal the executable matches in shell paths or fi
# check
set -l built (type --type $input 12&>/dev/null)
if test -n "$built"
and test "$built" = 'builtin'
and test "$built" = builtin
set $foundStatus 0
if not set -q _flag_c
echo -e -n "builtin\n"

View File

@@ -1,11 +1,11 @@
function sponge_filter_failed \
--argument-names command exit_code previously_in_history
--argument-names command exit_code previously_in_history
if test $previously_in_history = true -a $sponge_allow_previously_successful = true
return 1
end
if test $previously_in_history = true -a $sponge_allow_previously_successful = true
return 1
end
if contains $exit_code $sponge_successful_exit_codes
return 1
end
if contains $exit_code $sponge_successful_exit_codes
return 1
end
end

View File

@@ -1,11 +1,11 @@
function sponge_filter_matched \
--argument-names command
--argument-names command
for pattern in $sponge_regex_patterns
if string match --regex --quiet $pattern -- $command
return
for pattern in $sponge_regex_patterns
if string match --regex --quiet $pattern -- $command
return
end
end
end
return 1
return 1
end

1
config/fzf/completion.bash Executable file → Normal file
View File

@@ -1,3 +1,4 @@
# shellcheck disable=all
# ____ ____
# / __/___ / __/
# / /_/_ / / /_

1
config/fzf/completion.zsh Executable file → Normal file
View File

@@ -1,3 +1,4 @@
# shellcheck disable=all
# ____ ____
# / __/___ / __/
# / /_/_ / / /_

View File

@@ -1,3 +1,4 @@
# shellcheck shell=bash
# Everforest theme for fzf
# Generated from template - do not edit manually

0
config/fzf/fzf.bash Executable file → Normal file
View File

View File

@@ -1,3 +1,5 @@
#!/usr/bin/env zsh
# shellcheck disable=SC1071
# Setup fzf
# ---------

9
config/fzf/key-bindings.bash Executable file → Normal file
View File

@@ -20,8 +20,8 @@ __fzf_select__() {
-o -type d -print \
-o -type l -print 2> /dev/null | cut -b3-"}"
opts="--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore --reverse ${FZF_DEFAULT_OPTS-} ${FZF_CTRL_T_OPTS-} -m"
eval "$cmd" |
FZF_DEFAULT_OPTS="$opts" $(__fzfcmd) "$@" |
# shellcheck disable=SC2091 # Intentionally execute output of __fzfcmd
eval "$cmd" | FZF_DEFAULT_OPTS="$opts" $(__fzfcmd) "$@" |
while read -r item; do
printf '%q ' "$item" # escape special chars
done
@@ -35,7 +35,8 @@ if [[ $- =~ i ]]; then
}
fzf-file-widget() {
local selected="$(__fzf_select__ "$@")"
local selected
selected="$(__fzf_select__ "$@")"
READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}$selected${READLINE_LINE:$READLINE_POINT}"
READLINE_POINT=$((READLINE_POINT + ${#selected}))
}
@@ -45,6 +46,7 @@ if [[ $- =~ i ]]; then
cmd="${FZF_ALT_C_COMMAND:-"command find -L . -mindepth 1 \\( -path '*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune \
-o -type d -print 2> /dev/null | cut -b3-"}"
opts="--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore --reverse ${FZF_DEFAULT_OPTS-} ${FZF_ALT_C_OPTS-} +m"
# shellcheck disable=SC2091 # Intentionally execute output of __fzfcmd
dir=$(
set +o pipefail
eval "$cmd" | FZF_DEFAULT_OPTS="$opts" $(__fzfcmd)
@@ -55,6 +57,7 @@ if [[ $- =~ i ]]; then
local output opts script
opts="--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} -n2..,.. --scheme=history --bind=ctrl-r:toggle-sort ${FZF_CTRL_R_OPTS-} +m --read0"
script='BEGIN { getc; $/ = "\n\t"; $HISTCOUNT = $ENV{last_hist} + 1 } s/^[ *]//; print $HISTCOUNT - $. . "\t$_" if !$seen{$_}++'
# shellcheck disable=SC2091 # Intentionally execute output of __fzfcmd
output=$(
set +o pipefail
builtin fc -lnr -2147483648 |

263
config/fzf/key-bindings.fish Executable file → Normal file
View File

@@ -15,158 +15,161 @@
# ------------
function fzf_key_bindings
# Store current token in $dir as root for the 'find' command
function fzf-file-widget -d "List files and folders"
set -l commandline (__fzf_parse_commandline)
set -l dir $commandline[1]
set -l fzf_query $commandline[2]
set -l prefix $commandline[3]
# Store current token in $dir as root for the 'find' command
function fzf-file-widget -d "List files and folders"
set -l commandline (__fzf_parse_commandline)
set -l dir $commandline[1]
set -l fzf_query $commandline[2]
set -l prefix $commandline[3]
# "-path \$dir'*/\\.*'" matches hidden files/folders inside $dir but not
# $dir itself, even if hidden.
test -n "$FZF_CTRL_T_COMMAND"; or set -l FZF_CTRL_T_COMMAND "
# "-path \$dir'*/\\.*'" matches hidden files/folders inside $dir but not
# $dir itself, even if hidden.
test -n "$FZF_CTRL_T_COMMAND"; or set -l FZF_CTRL_T_COMMAND "
command find -L \$dir -mindepth 1 \\( -path \$dir'*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' \\) -prune \
-o -type f -print \
-o -type d -print \
-o -type l -print 2> /dev/null | sed 's@^\./@@'"
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
begin
set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_CTRL_T_OPTS"
eval "$FZF_CTRL_T_COMMAND | "(__fzfcmd)' -m --query "'$fzf_query'"' | while read -l r; set result $result $r; end
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
begin
set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_CTRL_T_OPTS"
eval "$FZF_CTRL_T_COMMAND | "(__fzfcmd)' -m --query "'$fzf_query'"' | while read -l r
set result $result $r
end
end
if [ -z "$result" ]
commandline -f repaint
return
else
# Remove last token from commandline.
commandline -t ""
end
for i in $result
commandline -it -- $prefix
commandline -it -- (string escape $i)
commandline -it -- ' '
end
commandline -f repaint
end
if [ -z "$result" ]
commandline -f repaint
return
else
# Remove last token from commandline.
commandline -t ""
function fzf-history-widget -d "Show command history"
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
begin
set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT $FZF_DEFAULT_OPTS --scheme=history --bind=ctrl-r:toggle-sort,ctrl-z:ignore $FZF_CTRL_R_OPTS +m"
set -l FISH_MAJOR (echo $version | cut -f1 -d.)
set -l FISH_MINOR (echo $version | cut -f2 -d.)
# history's -z flag is needed for multi-line support.
# history's -z flag was added in fish 2.4.0, so don't use it for versions
# before 2.4.0.
if [ "$FISH_MAJOR" -gt 2 -o \( "$FISH_MAJOR" -eq 2 -a "$FISH_MINOR" -ge 4 \) ]
history -z | eval (__fzfcmd) --read0 --print0 -q '(commandline)' | read -lz result
and commandline -- $result
else
history | eval (__fzfcmd) -q '(commandline)' | read -l result
and commandline -- $result
end
end
commandline -f repaint
end
for i in $result
commandline -it -- $prefix
commandline -it -- (string escape $i)
commandline -it -- ' '
end
commandline -f repaint
end
function fzf-history-widget -d "Show command history"
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
begin
set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT $FZF_DEFAULT_OPTS --scheme=history --bind=ctrl-r:toggle-sort,ctrl-z:ignore $FZF_CTRL_R_OPTS +m"
function fzf-cd-widget -d "Change directory"
set -l commandline (__fzf_parse_commandline)
set -l dir $commandline[1]
set -l fzf_query $commandline[2]
set -l prefix $commandline[3]
set -l FISH_MAJOR (echo $version | cut -f1 -d.)
set -l FISH_MINOR (echo $version | cut -f2 -d.)
# history's -z flag is needed for multi-line support.
# history's -z flag was added in fish 2.4.0, so don't use it for versions
# before 2.4.0.
if [ "$FISH_MAJOR" -gt 2 -o \( "$FISH_MAJOR" -eq 2 -a "$FISH_MINOR" -ge 4 \) ];
history -z | eval (__fzfcmd) --read0 --print0 -q '(commandline)' | read -lz result
and commandline -- $result
else
history | eval (__fzfcmd) -q '(commandline)' | read -l result
and commandline -- $result
end
end
commandline -f repaint
end
function fzf-cd-widget -d "Change directory"
set -l commandline (__fzf_parse_commandline)
set -l dir $commandline[1]
set -l fzf_query $commandline[2]
set -l prefix $commandline[3]
test -n "$FZF_ALT_C_COMMAND"; or set -l FZF_ALT_C_COMMAND "
test -n "$FZF_ALT_C_COMMAND"; or set -l FZF_ALT_C_COMMAND "
command find -L \$dir -mindepth 1 \\( -path \$dir'*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' \\) -prune \
-o -type d -print 2> /dev/null | sed 's@^\./@@'"
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
begin
set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_ALT_C_OPTS"
eval "$FZF_ALT_C_COMMAND | "(__fzfcmd)' +m --query "'$fzf_query'"' | read -l result
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
begin
set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_ALT_C_OPTS"
eval "$FZF_ALT_C_COMMAND | "(__fzfcmd)' +m --query "'$fzf_query'"' | read -l result
if [ -n "$result" ]
cd -- $result
if [ -n "$result" ]
cd -- $result
# Remove last token from commandline.
commandline -t ""
commandline -it -- $prefix
end
# Remove last token from commandline.
commandline -t ""
commandline -it -- $prefix
end
end
commandline -f repaint
end
commandline -f repaint
end
function __fzfcmd
test -n "$FZF_TMUX"; or set FZF_TMUX 0
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
if [ -n "$FZF_TMUX_OPTS" ]
echo "fzf-tmux $FZF_TMUX_OPTS -- "
else if [ $FZF_TMUX -eq 1 ]
echo "fzf-tmux -d$FZF_TMUX_HEIGHT -- "
else
echo "fzf"
end
end
bind \ct fzf-file-widget
bind \cr fzf-history-widget
bind \ec fzf-cd-widget
if bind -M insert > /dev/null 2>&1
bind -M insert \ct fzf-file-widget
bind -M insert \cr fzf-history-widget
bind -M insert \ec fzf-cd-widget
end
function __fzf_parse_commandline -d 'Parse the current command line token and return split of existing filepath, fzf query, and optional -option= prefix'
set -l commandline (commandline -t)
# strip -option= from token if present
set -l prefix (string match -r -- '^-[^\s=]+=' $commandline)
set commandline (string replace -- "$prefix" '' $commandline)
# eval is used to do shell expansion on paths
eval set commandline $commandline
if [ -z $commandline ]
# Default to current directory with no --query
set dir '.'
set fzf_query ''
else
set dir (__fzf_get_dir $commandline)
if [ "$dir" = "." -a (string sub -l 1 -- $commandline) != '.' ]
# if $dir is "." but commandline is not a relative path, this means no file path found
set fzf_query $commandline
else
# Also remove trailing slash after dir, to "split" input properly
set fzf_query (string replace -r "^$dir/?" -- '' "$commandline")
end
function __fzfcmd
test -n "$FZF_TMUX"; or set FZF_TMUX 0
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
if [ -n "$FZF_TMUX_OPTS" ]
echo "fzf-tmux $FZF_TMUX_OPTS -- "
else if [ $FZF_TMUX -eq 1 ]
echo "fzf-tmux -d$FZF_TMUX_HEIGHT -- "
else
echo fzf
end
end
echo $dir
echo $fzf_query
echo $prefix
end
bind \ct fzf-file-widget
bind \cr fzf-history-widget
bind \ec fzf-cd-widget
function __fzf_get_dir -d 'Find the longest existing filepath from input string'
set dir $argv
# Strip all trailing slashes. Ignore if $dir is root dir (/)
if [ (string length -- $dir) -gt 1 ]
set dir (string replace -r '/*$' -- '' $dir)
if bind -M insert >/dev/null 2>&1
bind -M insert \ct fzf-file-widget
bind -M insert \cr fzf-history-widget
bind -M insert \ec fzf-cd-widget
end
# Iteratively check if dir exists and strip tail end of path
while [ ! -d "$dir" ]
# If path is absolute, this can keep going until ends up at /
# If path is relative, this can keep going until entire input is consumed, dirname returns "."
set dir (dirname -- "$dir")
function __fzf_parse_commandline -d 'Parse the current command line token and return split of existing filepath, fzf query, and optional -option= prefix'
set -l commandline (commandline -t)
# strip -option= from token if present
set -l prefix (string match -r -- '^-[^\s=]+=' $commandline)
set commandline (string replace -- "$prefix" '' $commandline)
# eval is used to do shell expansion on paths
eval set commandline $commandline
if [ -z $commandline ]
# Default to current directory with no --query
set dir '.'
set fzf_query ''
else
set dir (__fzf_get_dir $commandline)
if [ "$dir" = "." -a (string sub -l 1 -- $commandline) != '.' ]
# if $dir is "." but commandline is not a relative path, this means no file path found
set fzf_query $commandline
else
# Also remove trailing slash after dir, to "split" input properly
set fzf_query (string replace -r "^$dir/?" -- '' "$commandline")
end
end
echo $dir
echo $fzf_query
echo $prefix
end
echo $dir
end
function __fzf_get_dir -d 'Find the longest existing filepath from input string'
set dir $argv
# Strip all trailing slashes. Ignore if $dir is root dir (/)
if [ (string length -- $dir) -gt 1 ]
set dir (string replace -r '/*$' -- '' $dir)
end
# Iteratively check if dir exists and strip tail end of path
while [ ! -d "$dir" ]
# If path is absolute, this can keep going until ends up at /
# If path is relative, this can keep going until entire input is consumed, dirname returns "."
set dir (dirname -- "$dir")
end
echo $dir
end
end

1
config/fzf/key-bindings.zsh Executable file → Normal file
View File

@@ -1,3 +1,4 @@
# shellcheck disable=all
# ____ ____
# / __/___ / __/
# / /_/_ / / /_

View File

@@ -1,68 +1,68 @@
{
"profiles": [
"profiles": [
{
"complex_modifications": {
"rules": [
{
"description": "Change right_command+hjkl to arrow keys",
"manipulators": [
{
"from": {
"key_code": "h",
"modifiers": {
"mandatory": ["right_command"],
"optional": ["any"]
}
},
"to": [{ "key_code": "left_arrow" }],
"type": "basic"
},
{
"from": {
"key_code": "j",
"modifiers": {
"mandatory": ["right_command"],
"optional": ["any"]
}
},
"to": [{ "key_code": "down_arrow" }],
"type": "basic"
},
{
"from": {
"key_code": "k",
"modifiers": {
"mandatory": ["right_command"],
"optional": ["any"]
}
},
"to": [{ "key_code": "up_arrow" }],
"type": "basic"
},
{
"from": {
"key_code": "l",
"modifiers": {
"mandatory": ["right_command"],
"optional": ["any"]
}
},
"to": [{ "key_code": "right_arrow" }],
"type": "basic"
}
]
}
]
},
"name": "Default profile",
"selected": true,
"simple_modifications": [
{
"complex_modifications": {
"rules": [
{
"description": "Change right_command+hjkl to arrow keys",
"manipulators": [
{
"from": {
"key_code": "h",
"modifiers": {
"mandatory": ["right_command"],
"optional": ["any"]
}
},
"to": [{ "key_code": "left_arrow" }],
"type": "basic"
},
{
"from": {
"key_code": "j",
"modifiers": {
"mandatory": ["right_command"],
"optional": ["any"]
}
},
"to": [{ "key_code": "down_arrow" }],
"type": "basic"
},
{
"from": {
"key_code": "k",
"modifiers": {
"mandatory": ["right_command"],
"optional": ["any"]
}
},
"to": [{ "key_code": "up_arrow" }],
"type": "basic"
},
{
"from": {
"key_code": "l",
"modifiers": {
"mandatory": ["right_command"],
"optional": ["any"]
}
},
"to": [{ "key_code": "right_arrow" }],
"type": "basic"
}
]
}
]
},
"name": "Default profile",
"selected": true,
"simple_modifications": [
{
"from": { "key_code": "caps_lock" },
"to": [{ "key_code": "f18" }]
}
],
"virtual_hid_keyboard": { "keyboard_type_v2": "iso" }
"from": { "key_code": "caps_lock" },
"to": [{ "key_code": "f18" }]
}
]
}
],
"virtual_hid_keyboard": { "keyboard_type_v2": "iso" }
}
]
}

View File

@@ -55,7 +55,8 @@ return {
{
event = 'file_opened',
handler = function(_)
require('neo-tree.command').execute { action = 'close' }
local c = require 'neo-tree.command'
c.execute { action = 'close' }
end,
},
},

View File

@@ -56,4 +56,3 @@ disable_startup_command = true
name = "Downloads"
path = "~/Downloads"
startup_command = "lsa"

View File

@@ -1,3 +1 @@
set -g @catppuccin_flavor "mocha"
set -g @catppuccin_window_status_style "basic"

View File

@@ -1,2 +1 @@
set -g @catppuccin_flavor "latte"
set -g @catppuccin_window_status_style "basic"

View File

@@ -29,7 +29,6 @@ set -g mouse on # Mouse support
set -g set-titles on # Allow tmux to set the terminal title
set -g status on # Setting status on
set -g status-keys vi # vi keys to move between panes
set -g history-limit 3000 # Scrollback history limit
# Activity Monitoring (for when something happens in another pain)
set -g monitor-activity on
@@ -47,9 +46,6 @@ set -g base-index 1
set -g pane-base-index 1
set -g renumber-windows on
# Activate with `DEBUG=1 tmux -vv`
if-shell '[ "$DEBUG" = "1" ]' 'set -g debug-file ~/.cache/tmux-debug.log'
# ╭──────────────────────────────────────────────────────────╮
# │ Theme │
# ╰──────────────────────────────────────────────────────────╯
@@ -58,13 +54,15 @@ set -g status-justify "left"
set -g status-left ''
set -g status-left-length "0"
set -g status-position "bottom"
set -g status-right "#S@#h #{tmux_mode_indicator}"
#set -g status-right "#S@#h #{tmux_mode_indicator}"
set -g status-right-length "50"
set -g window-status-current-format ' #I:#W#{?window_zoomed_flag, ◈ ,} '
set -g window-status-format ' #I:#W '
#set -g window-status-current-format ' #I:#W#{?window_zoomed_flag, ◈ ,} '
#set -g window-status-format ' #I:#W '
set -g @catppuccin_status_background 'none'
set -g @catppuccin_window_flags 'icon'
set -g @catppuccin_status_connect_separator 'no'
set -g @catppuccin_window_text "#T"
set -g @catppuccin_window_current_text "#T"
# ╭──────────────────────────────────────────────────────────╮
# │ Bindings │
@@ -86,11 +84,6 @@ bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D
# Easier switching between window
bind C-n next-window
bind C-p previous-window
bind C-a last-window
# Reload tmux config with <prefix> + r
unbind r
bind r "source-file ~/.dotfiles/config/tmux/tmux.conf; display 'tmux cfg reloaded!'"
@@ -103,14 +96,7 @@ bind Escape copy-mode
unbind p
bind p paste-buffer
# tms bindings
bind -N "tms" T display-popup -E "tms"
bind -N "tms windows" C-w display-popup -E "tms windows"
bind -N "tms switch" C-s display-popup -E "tms switch"
bind -N "tms refresh" C-r display-popup -E "tms refresh"
# global sessions
# bind-key "K" display-popup -h 90% -w 50% -E "sesh ui"
bind -N "sesh selection" t run-shell "$HOME/.dotfiles/config/tmux/sesh-tmux.fish"
bind -N "last-session (via sesh) " L run-shell "sesh last"
bind -N "sesh ui" N display-popup -E "sesh ui"

View File

@@ -1,4 +1,4 @@
# shellcheck shell=zsh
# shellcheck disable=SC1071,SC1103,SC2148
# Source: https://github.com/nvm-sh/nvm#zsh
# place this after nvm initialization!
autoload -U add-zsh-hook

52
cspell.config.yaml Normal file
View File

@@ -0,0 +1,52 @@
version: "0.2"
ignorePaths: []
dictionaryDefinitions: []
dictionaries: []
words:
- aquasec
- cdgr
- cheatsheets
- CODEQUALITY
- DEVSKIM
- dscacheutil
- emptytrash
- flushcache
- getifaddr
- goenv
- irssi
- Ismo
- isodate
- KEYSFILE
- KEYSSOURCE
- killall
- lakka
- libexec
- Licence
- lmstudio
- localip
- locatedb
- LOGFILE
- luarocks
- mvdan
- myip
- onnimonni
- opencode
- optstring
- orbstack
- osascript
- phpenv
- psub
- pyenv
- SARIF
- shellcheck
- shfmt
- shivammathur
- spelllang
- updatedb
- vendordirs
- vimrc
- virtualenv
- Vuorinen
- zedit
ignoreWords: []
import: []

View File

@@ -1,425 +0,0 @@
# Chezmoi Migration Summary
## What Was Done
Your dotfiles repository has been prepared for migration from dotbot to chezmoi. Here's what was created:
### 1. Updated Install Script
- **File**: `install`
- **Change**: Now uses chezmoi's one-line installer
- **Command**: `sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen`
### 2. Chezmoi Configuration Files
#### `.chezmoi.yaml.tmpl`
Main configuration file that includes:
- Source directory configuration
- Host detection (air, lakka, tunkki, s)
- OS detection (macOS, Linux)
- Custom data variables for templates
- Merge and diff settings
- Git configuration
- Pre-read hook for submodule updates
#### `.chezmoiignore`
Specifies what files should NOT be managed by chezmoi:
- Git and GitHub files
- Documentation (*.md files)
- Development tools (.vscode, node_modules, etc.)
- Old dotbot configuration
- Host-specific files (via templates)
- Repository management files
### 3. Run Scripts (Automated Setup)
#### `run_once_before_install-prerequisites.sh.tmpl`
Runs **once before** applying dotfiles:
- Installs Homebrew (macOS)
- Installs Xcode CLI tools (macOS)
- Updates package manager (Linux)
#### `run_once_after_install-packages.sh.tmpl`
Runs **once after** applying dotfiles:
- Installs Homebrew packages (Brewfile)
- Sets macOS defaults
- Installs apt packages (Linux)
- Installs pipx packages
#### `run_once_after_setup-languages.sh.tmpl`
Runs **once after** applying dotfiles:
- Installs fonts
- Installs Cargo packages (Rust)
- Installs Go packages
- Installs Composer (PHP)
- Installs NVM and latest Node LTS
- Installs NPM packages
- Installs GitHub CLI extensions
- Installs z (directory jumper)
- Installs cheat databases
#### `run_once_after_create-directories.sh.tmpl`
Runs **once after** applying dotfiles:
- Creates required directories in `$HOME`
- Sets proper permissions (e.g., `.ssh` → 0700)
### 4. Hooks
#### `.chezmoihooks/pre-read-source-state.sh`
Runs before chezmoi reads the source state:
- Updates git submodules automatically
### 5. Documentation
#### `MIGRATION-DOTBOT-TO-CHEZMOI.md` (66KB)
Comprehensive migration guide including:
- Why migrate to chezmoi
- Key differences between dotbot and chezmoi
- Complete dotbot → chezmoi mapping
- File structure comparison
- Step-by-step migration instructions
- Usage guide with examples
- Troubleshooting section
- Migration checklist
#### `CHEZMOI-QUICK-REFERENCE.md` (11KB)
Quick reference guide for daily use:
- Common commands
- File naming conventions
- Template syntax examples
- Host-specific configuration patterns
- Troubleshooting tips
- Useful aliases
#### `HOST-SPECIFIC-MIGRATION.md` (9KB)
Detailed guide for migrating host-specific configurations:
- Three migration approaches explained
- Examples from your current hosts
- Step-by-step host config migration
- Testing strategies
- Best practices
### 6. Migration Helper Script
#### `migrate-to-chezmoi.sh`
Automated script to restructure your files:
- Creates backup branch automatically
- Creates migration branch
- Renames files to chezmoi conventions
- `base/*``dot_*`
- `config/*``dot_config/*`
- `local/bin/*``executable_dot_local/bin/*`
- `ssh/*``private_dot_ssh/*`
- Cleans up empty directories
- Generates migration notes
## What Needs To Be Done
### Immediate Next Steps
1. **Review Changes**
```bash
cd ~/.dotfiles
git status
git diff
```
2. **Read Documentation**
- Start with: `MIGRATION-DOTBOT-TO-CHEZMOI.md`
- Quick reference: `CHEZMOI-QUICK-REFERENCE.md`
- Host configs: `HOST-SPECIFIC-MIGRATION.md`
3. **Commit Current State**
```bash
git add install .chezmoi.yaml.tmpl .chezmoiignore
git add run_once_*.sh.tmpl .chezmoihooks/
git add migrate-to-chezmoi.sh
git add *.md
git commit -m "Add chezmoi configuration and migration tools"
```
### File Restructuring
You have two options:
#### Option A: Automated (Recommended for First Pass)
```bash
# Run the migration script
./migrate-to-chezmoi.sh
# This will:
# - Create backup branch
# - Create migration branch
# - Rename all files to chezmoi conventions
# - Show you what was done
```
#### Option B: Manual (More Control)
Manually rename files following chezmoi conventions:
```bash
# Base files become dot_ files
git mv base/bashrc dot_bashrc
git mv base/zshrc dot_zshrc
git mv base/tmux.conf dot_tmux.conf
# Config files
mkdir -p dot_config
git mv config/fish dot_config/fish
git mv config/nvim dot_config/nvim
# ... etc
# Local bin (make executable)
mkdir -p executable_dot_local/bin
for file in local/bin/*; do
git mv "$file" "executable_dot_local/bin/$(basename $file)"
done
# SSH files (private)
mkdir -p private_dot_ssh
git mv ssh/* private_dot_ssh/
# See full examples in MIGRATION-DOTBOT-TO-CHEZMOI.md
```
### Host-Specific Configurations
Your hosts need special attention:
```bash
hosts/
├── air/
├── lakka/
├── tunkki/
└── s/
```
**Read**: `HOST-SPECIFIC-MIGRATION.md` for detailed strategies.
**Quick decision guide**:
- **Few differences per file** → Use templates with `{{ if .is_air }}`
- **Complete replacement** → Use `filename__hostname` suffix
- **Host-specific directories** → Use `.chezmoiignore` with templates
### Testing Before Commit
```bash
# After restructuring files, test with chezmoi
cd ~/.dotfiles
# Initialize chezmoi with current directory as source
chezmoi init --source $(pwd)
# See what would happen (dry run)
chezmoi apply --dry-run --verbose
# See what a specific file would look like
chezmoi cat ~/.bashrc
# Check for errors
chezmoi verify
```
### Final Steps
1. **Commit Migration**
```bash
git add -A
git commit -m "Migrate from dotbot to chezmoi"
git push
```
2. **Test on Current Machine**
```bash
# Apply dotfiles
chezmoi apply -v
# Verify everything works
# Open new terminal
# Check configs
```
3. **Test on Another Machine** (if available)
```bash
# On another machine
sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen
# Verify host-specific configs applied correctly
```
4. **Clean Up** (after confirming everything works)
```bash
cd $(chezmoi source-path)
# Remove old dotbot files
rm -rf tools/dotbot tools/dotbot-*
rm install.conf.yaml
rm tools/dotbot-defaults.yaml
# Optionally remove hosts/ if fully migrated to templates
# rm -rf hosts/
git add -A
git commit -m "Clean up old dotbot files"
git push
```
## Key Differences to Remember
### Installation
**Before**: `./install` (ran dotbot)
**After**: `sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen`
### Making Changes
**Before**:
```bash
cd ~/.dotfiles
vim base/bashrc
./install # Re-run to create symlinks
```
**After**:
```bash
chezmoi edit ~/.bashrc
# Or: vim ~/.bashrc && chezmoi add ~/.bashrc
chezmoi apply
```
### Syncing Across Machines
**Before**:
```bash
cd ~/.dotfiles
git pull
./install
```
**After**:
```bash
chezmoi update
# Equivalent to: cd $(chezmoi source-path) && git pull && chezmoi apply
```
### Host-Specific Configs
**Before**: Separate files in `hosts/hostname/`
**After**: Templates with `{{ if eq .chezmoi.hostname "air" }}` or `filename__hostname`
## File Mapping Reference
| Old Location | New Location | Notes |
|--------------|--------------|-------|
| `base/bashrc` | `dot_bashrc` | Becomes `~/.bashrc` |
| `config/fish/` | `dot_config/fish/` | Becomes `~/.config/fish/` |
| `local/bin/script` | `executable_dot_local/bin/script` | Executable `~/.local/bin/script` |
| `ssh/config` | `private_dot_ssh/config` | Private (0600) `~/.ssh/config` |
| `install.conf.yaml` | `run_once_*.sh.tmpl` | Setup tasks |
| `hosts/air/config/` | `dot_config/*.tmpl` or `*__air` | Host-specific |
## Troubleshooting Quick Tips
### "Entry not in source state"
```bash
# File not added to chezmoi
chezmoi add <file>
```
### "File modified since chezmoi last wrote it"
```bash
# See changes
chezmoi diff
# Re-add
chezmoi add <file>
```
### "Template undefined variable"
```bash
# Check available data
chezmoi data
# Test template
chezmoi execute-template "{{ .chezmoi.hostname }}"
```
### Scripts not running
```bash
# Check permissions
chmod +x run_once_*.sh.tmpl
# Force re-run
chezmoi apply --force
```
## Additional Resources
### Created Documentation
- `MIGRATION-DOTBOT-TO-CHEZMOI.md` - Complete migration guide
- `CHEZMOI-QUICK-REFERENCE.md` - Daily usage reference
- `HOST-SPECIFIC-MIGRATION.md` - Host configuration guide
- `MIGRATION-NOTES.md` - Generated after running migration script
### External Resources
- [Chezmoi Official Docs](https://www.chezmoi.io/)
- [Chezmoi Quick Start](https://www.chezmoi.io/quick-start/)
- [Chezmoi User Guide](https://www.chezmoi.io/user-guide/)
- [Chezmoi Templates](https://www.chezmoi.io/reference/templates/)
## Summary Checklist
- [x] Install script updated
- [x] Chezmoi configuration created (`.chezmoi.yaml.tmpl`)
- [x] Ignore file created (`.chezmoiignore`)
- [x] Run scripts created (4 scripts)
- [x] Hooks created (pre-read-source-state)
- [x] Migration script created (`migrate-to-chezmoi.sh`)
- [x] Documentation created (3 guides)
- [ ] **Review and commit configuration files**
- [ ] **Run migration script** or manually restructure
- [ ] **Migrate host-specific configs**
- [ ] **Test with chezmoi**
- [ ] **Commit migration**
- [ ] **Test on current machine**
- [ ] **Test on other machines**
- [ ] **Clean up old dotbot files**
- [ ] **Update README.md** (document chezmoi usage)
## Questions?
If you have questions during migration:
1. Check the relevant guide:
- General questions → `MIGRATION-DOTBOT-TO-CHEZMOI.md`
- Usage questions → `CHEZMOI-QUICK-REFERENCE.md`
- Host configs → `HOST-SPECIFIC-MIGRATION.md`
2. Use chezmoi's help:
```bash
chezmoi help
chezmoi help <command>
chezmoi doctor
```
3. Check official docs:
- https://www.chezmoi.io/
## What Makes This Migration Special
Your dotfiles have:
- ✅ Custom `dfm` script → Wrapped in run_once scripts
- ✅ Multiple dotbot plugins → Equivalent run_once scripts
- ✅ Host-specific configs → Template support added
- ✅ Complex installation → Automated in run scripts
- ✅ Git submodules → Pre-read hook handles this
- ✅ Multiple hosts (air, lakka, tunkki, s) → Detected and flagged
Everything from your dotbot setup has been accounted for in the chezmoi migration!
## Final Notes
- **Take your time**: This is a significant migration
- **Test thoroughly**: Use `--dry-run` extensively
- **Backup everything**: The migration script creates backups
- **Iterate**: You can always refine the migration later
- **Have fun**: Chezmoi offers powerful features to explore!
Good luck with your migration! 🚀

View File

@@ -1,432 +0,0 @@
# Chezmoi Quick Reference
Quick reference guide for common chezmoi operations with your dotfiles.
## Installation
```bash
# Fresh install on a new machine
sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen
# Or if chezmoi is already installed
chezmoi init --apply ivuorinen
```
## Daily Workflow
### Making Changes
```bash
# Edit a dotfile (opens in $EDITOR)
chezmoi edit ~/.bashrc
# Or edit directly and add to chezmoi
vim ~/.bashrc
chezmoi add ~/.bashrc
# See what would change
chezmoi diff
# Apply changes
chezmoi apply
```
### Syncing Across Machines
```bash
# On machine A: commit and push changes
cd $(chezmoi source-path)
git add -A
git commit -m "Update configuration"
git push
# On machine B: pull and apply changes
chezmoi update
# This is equivalent to:
# cd $(chezmoi source-path) && git pull && chezmoi apply
```
## Common Commands
### Viewing and Inspecting
```bash
# See what chezmoi would do
chezmoi diff
# List all managed files
chezmoi managed
# List unmanaged files
chezmoi unmanaged
# Show the source path
chezmoi source-path
# Show what a file would look like after templating
chezmoi cat ~/.bashrc
# Show available template data
chezmoi data
```
### Adding and Removing Files
```bash
# Add a file
chezmoi add ~/.newfile
# Add a file as a template
chezmoi add --template ~/.newfile
# Add a directory recursively
chezmoi add --recursive ~/.config/newapp
# Add with autodetection (templates, scripts, etc.)
chezmoi add --autotemplate ~/.newfile
# Stop managing a file (removes from chezmoi)
chezmoi forget ~/.oldfile
# Remove a file from both chezmoi and home directory
chezmoi remove ~/.oldfile
```
### Working with Templates
```bash
# Execute a template expression
chezmoi execute-template "{{ .chezmoi.hostname }}"
# Edit template data
chezmoi edit-config
# Verify templates
chezmoi verify
```
### Applying Changes
```bash
# Apply all changes
chezmoi apply
# Apply with verbose output
chezmoi apply -v
# Dry run (show what would happen)
chezmoi apply --dry-run -v
# Force apply (re-runs scripts)
chezmoi apply --force
# Apply only specific files
chezmoi apply ~/.bashrc ~/.zshrc
```
### Updating from Repository
```bash
# Update dotfiles from repository
chezmoi update
# Update but don't apply
cd $(chezmoi source-path) && git pull
# Update with interactive merge
chezmoi update --interactive
```
## File Naming Conventions
### Basic Prefixes
| Source File | Destination | Description |
|------------|-------------|-------------|
| `dot_bashrc` | `~/.bashrc` | Dot file |
| `dot_config/` | `~/.config/` | Dot directory |
| `private_dot_ssh/` | `~/.ssh/` | Private directory (0700) |
| `executable_dot_local/bin/script` | `~/.local/bin/script` | Executable |
| `symlink_dot_vim` | `~/.vim` | Symlink |
| `readonly_dot_file` | `~/.file` | Read-only |
### Template Files
| Source File | Description |
|------------|-------------|
| `dot_bashrc.tmpl` | Template file |
| `dot_config/fish/config.fish.tmpl` | Nested template |
### Scripts
| Script Name | When It Runs |
|------------|--------------|
| `run_once_before_*.sh` | Once before applying |
| `run_once_after_*.sh` | Once after applying |
| `run_before_*.sh` | Every time before applying |
| `run_after_*.sh` | Every time after applying |
| `run_onchange_*.sh` | When script content changes |
## Template Syntax
### Basic Variables
```go
// Hostname
{{ .chezmoi.hostname }}
// Username
{{ .chezmoi.username }}
// Operating system
{{ .chezmoi.os }}
// Home directory
{{ .chezmoi.homeDir }}
// Source directory
{{ .chezmoi.sourceDir }}
// Custom data from .chezmoi.yaml
{{ .is_macos }}
{{ .is_linux }}
```
### Conditionals
```go
{{ if eq .chezmoi.hostname "air" }}
# Configuration for air
{{ else if eq .chezmoi.hostname "lakka" }}
# Configuration for lakka
{{ else }}
# Default configuration
{{ end }}
{{ if .is_macos }}
# macOS-specific
{{ end }}
{{ if and .is_macos (eq .chezmoi.hostname "air") }}
# macOS on air
{{ end }}
```
### Loops
```go
{{ range $key, $value := .data }}
{{ $key }}: {{ $value }}
{{ end }}
```
### Including Files
```go
{{ include "template-file.txt" }}
{{ includeTemplate "template-file.tmpl" }}
```
## Host-Specific Configuration
### Method 1: Template Conditionals
In `dot_bashrc.tmpl`:
```bash
# Common configuration
export PATH="$HOME/.local/bin:$PATH"
{{ if eq .chezmoi.hostname "air" }}
# air-specific configuration
export WORK_DIR="$HOME/Work"
{{ end }}
{{ if eq .chezmoi.hostname "lakka" }}
# lakka-specific configuration
export WORK_DIR="$HOME/Projects"
{{ end }}
```
### Method 2: Separate Files with Symlinks
Use `.chezmoiignore` to exclude files for specific hosts:
```
{{ if ne .chezmoi.hostname "air" }}
dot_config/air-specific-app/
{{ end }}
{{ if ne .chezmoi.hostname "lakka" }}
dot_config/lakka-specific-app/
{{ end }}
```
## Working with Secrets
### Environment Variables
```go
{{ .Env.MY_SECRET }}
```
### 1Password
```go
{{ (onepasswordDocument "my-secret").content }}
{{ (onepasswordItemFields "my-item").password.value }}
```
### External Commands
```go
{{ output "op" "read" "op://vault/item/field" }}
```
## Troubleshooting
### Check Configuration
```bash
# Verify chezmoi is working correctly
chezmoi doctor
# Check state
chezmoi verify
# See detailed info
chezmoi data
```
### Debug Templates
```bash
# See what a template would produce
chezmoi cat ~/.bashrc
# Execute a template
chezmoi execute-template "{{ .chezmoi.hostname }}"
# Verbose output
chezmoi apply -v
```
### Fix Issues
```bash
# Re-apply everything
chezmoi apply --force
# Reset state (dangerous!)
chezmoi state reset
# Clear cache
rm -rf $(chezmoi source-path)/.git/chezmoi-*
```
### Common Errors
**Error: template: ... undefined variable**
- Check template syntax
- Verify data with `chezmoi data`
**Error: entry ... is not in source state**
- File not added to chezmoi: `chezmoi add <file>`
**Error: ... has been modified since chezmoi last wrote it**
- See changes: `chezmoi diff`
- Re-add: `chezmoi add <file>`
- Or force apply: `chezmoi apply --force`
## Useful Aliases
Add these to your shell configuration:
```bash
# Chezmoi shortcuts
alias cm='chezmoi'
alias cma='chezmoi apply'
alias cmd='chezmoi diff'
alias cme='chezmoi edit'
alias cmu='chezmoi update'
alias cmcd='cd $(chezmoi source-path)'
# Common workflows
alias cmup='chezmoi git pull && chezmoi apply'
alias cmpush='cd $(chezmoi source-path) && git add -A && git commit && git push'
```
## Environment Variables
```bash
# Change source directory (default: ~/.local/share/chezmoi)
export CHEZMOI_SOURCE_DIR="$HOME/.dotfiles"
# Change config file location
export CHEZMOI_CONFIG_FILE="$HOME/.config/chezmoi/chezmoi.yaml"
# Use different editor
export EDITOR="vim"
```
## Advanced Usage
### Using chezmoi as a dotfiles manager
```bash
# Initialize with local directory
chezmoi init --source ~/.dotfiles
# Use current directory as source
chezmoi init --source $(pwd)
```
### Managing Multiple Machines
Use data in `.chezmoi.yaml.tmpl`:
```yaml
data:
is_work_machine: {{ or (eq .chezmoi.hostname "work-laptop") (eq .chezmoi.hostname "work-desktop") }}
is_personal: {{ eq .chezmoi.hostname "personal-laptop" }}
```
Then in templates:
```go
{{ if .is_work_machine }}
# Work configuration
{{ end }}
```
### External Files
```yaml
# .chezmoiexternal.yaml
".config/nvim/lua/plugins":
type: "archive"
url: "https://github.com/user/nvim-config/archive/main.tar.gz"
stripComponents: 1
refreshPeriod: "168h"
```
## Resources
- [Official Documentation](https://www.chezmoi.io/)
- [User Guide](https://www.chezmoi.io/user-guide/)
- [Template Reference](https://www.chezmoi.io/reference/templates/)
- [Command Reference](https://www.chezmoi.io/reference/commands/)
- [FAQ](https://www.chezmoi.io/faq/)
## Help
```bash
# General help
chezmoi help
# Command-specific help
chezmoi help apply
chezmoi help add
# Show version
chezmoi --version
```

View File

@@ -1,462 +0,0 @@
# Host-Specific Configuration Migration
Guide for migrating host-specific configurations from dotbot to chezmoi.
## Current Dotbot Structure
You currently have host-specific configurations in:
```
hosts/
├── air/
│ ├── base/
│ ├── config/
│ └── install.conf.yaml
├── lakka/
│ ├── base/
│ ├── config/
│ └── install.conf.yaml
├── tunkki/
│ └── install.conf.yaml
└── s/
└── install.conf.yaml
```
## Chezmoi Approaches
There are three main approaches to handle host-specific configurations in chezmoi:
### 1. Template Conditionals (Recommended)
Use if/else conditions in template files.
**Pros:**
- Single source file for all hosts
- Easy to see all variations
- Less file duplication
**Cons:**
- Files can get complex with many hosts
- Need `.tmpl` extension
**Example:**
Create `dot_bashrc.tmpl`:
```bash
# Common configuration for all hosts
export PATH="$HOME/.local/bin:$PATH"
{{ if eq .chezmoi.hostname "air" }}
# air-specific
export WORK_DIR="$HOME/Work"
alias air-specific="echo air"
{{ end }}
{{ if eq .chezmoi.hostname "lakka" }}
# lakka-specific
export WORK_DIR="$HOME/Projects"
alias lakka-specific="echo lakka"
{{ end }}
# More common configuration
```
### 2. Separate Files with .chezmoiignore (Simple)
Keep separate files per host and ignore the ones that don't apply.
**Pros:**
- Clean separation
- No template syntax needed
- Easy to maintain
**Cons:**
- More files to manage
- Some duplication
**Example:**
Create multiple version files:
```
dot_bashrc__air
dot_bashrc__lakka
dot_bashrc__tunkki
```
These automatically apply based on hostname. No `.chezmoiignore` needed!
Or use directories:
```
dot_config/
├── app/
│ ├── config.yaml__air
│ ├── config.yaml__lakka
│ └── config.yaml__default
```
### 3. Hybrid Approach (Most Flexible)
Combine both methods:
- Use templates for files with minor differences
- Use separate files for completely different configs
## Migration Steps for Your Hosts
### Step 1: Analyze Each Host
Review what's different per host:
```bash
# See what's in each host directory
ls -la hosts/air/
ls -la hosts/lakka/
ls -la hosts/tunkki/
ls -la hosts/s/
# Compare configs
diff hosts/air/config/some-app/config hosts/lakka/config/some-app/config
```
### Step 2: Choose Strategy Per File
For each file that differs:
**Small differences** (few lines):
→ Use templates with conditionals
**Complete replacement**:
→ Use `filename__hostname` suffix
**Shared base + host additions**:
→ Use templates with includes or blocks
### Step 3: Migrate Host Configurations
#### Example: Fish Configuration
Your `hosts/air/config/fish/config.fish` differences:
**Current dotbot way:**
```yaml
# hosts/air/install.conf.yaml
- link:
~/.config/:
path: hosts/air/config/**
```
**New chezmoi way - Option A (Templates):**
Create `dot_config/fish/config.fish.tmpl`:
```fish
# Common fish configuration
set -gx EDITOR nvim
{{ if eq .chezmoi.hostname "air" }}
# air-specific config
set -gx WORK_DIR ~/Work
{{ else if eq .chezmoi.hostname "lakka" }}
# lakka-specific config
set -gx WORK_DIR ~/Projects
{{ end }}
# More common configuration
```
**New chezmoi way - Option B (Separate files):**
Create multiple files:
```
dot_config/fish/config.fish__air
dot_config/fish/config.fish__lakka
```
Chezmoi will automatically use the correct file based on hostname.
### Step 4: Update .chezmoi.yaml.tmpl
Add host flags for easier conditionals:
```yaml
{{- $hostname := .chezmoi.hostname -}}
data:
hostname: {{ $hostname | quote }}
# Host-specific flags
is_air: {{ eq $hostname "air" }}
is_lakka: {{ eq $hostname "lakka" }}
is_tunkki: {{ eq $hostname "tunkki" }}
is_s: {{ eq $hostname "s" }}
# Group flags
is_work: {{ or (eq $hostname "air") (eq $hostname "tunkki") }}
is_personal: {{ or (eq $hostname "lakka") (eq $hostname "s") }}
```
Then use simpler conditionals:
```go
{{ if .is_air }}
# air config
{{ end }}
{{ if .is_work }}
# All work machines
{{ end }}
```
## Specific Migration Examples
### Example 1: Simple Host-Specific Line
**Before (dotbot):**
```yaml
# hosts/air/config/app/config
setting=value_for_air
# hosts/lakka/config/app/config
setting=value_for_lakka
```
**After (chezmoi) - Option A:**
```
# dot_config/app/config.tmpl
{{ if .is_air -}}
setting=value_for_air
{{- else if .is_lakka -}}
setting=value_for_lakka
{{- end }}
```
**After (chezmoi) - Option B:**
```
# dot_config/app/config__air
setting=value_for_air
# dot_config/app/config__lakka
setting=value_for_lakka
```
### Example 2: Mostly Shared with Few Differences
**Before:**
100 lines shared, 5 lines different per host
**After (recommended - templates):**
```bash
# dot_config/app/config.tmpl
# ... 50 lines of shared config ...
{{ if .is_air }}
air_specific_setting=true
{{ else if .is_lakka }}
lakka_specific_setting=true
{{ end }}
# ... 50 more lines of shared config ...
```
### Example 3: Completely Different Configs
**Before:**
Two totally different config files
**After (recommended - separate files):**
```
dot_config/app/config__air
dot_config/app/config__lakka
```
### Example 4: Host-Specific Directories
**Before:**
```
hosts/air/config/air-only-app/
hosts/lakka/config/lakka-only-app/
```
**After - Use .chezmoiignore:**
```
# .chezmoiignore
{{ if ne .chezmoi.hostname "air" }}
dot_config/air-only-app/
{{ end }}
{{ if ne .chezmoi.hostname "lakka" }}
dot_config/lakka-only-app/
{{ end }}
```
Then create:
```
dot_config/air-only-app/ # Only applied on air
dot_config/lakka-only-app/ # Only applied on lakka
```
## Testing Host-Specific Configs
### Before Applying
```bash
# See what would be applied on this host
chezmoi diff
# See what a specific file would look like
chezmoi cat ~/.config/fish/config.fish
# Check template data
chezmoi data | grep hostname
```
### Simulating Other Hosts
```bash
# Test what would be applied on another host
chezmoi execute-template --init --promptString hostname=air "{{ .chezmoi.hostname }}"
# See what a file would look like on another host
# (This requires manual variable setting in templates)
```
### On Another Machine
```bash
# Initialize and test without applying
chezmoi init --dry-run --verbose ivuorinen
# Apply with dry-run
chezmoi apply --dry-run -v
```
## Migration Script Adjustments
Add to `migrate-to-chezmoi.sh`:
```bash
# Migrate host-specific configs
log_info "Processing host-specific configurations..."
CURRENT_HOST=$(hostname -s)
log_info "Current hostname: $CURRENT_HOST"
# Prompt for migration strategy
echo ""
log_warning "How do you want to handle host-specific configs?"
echo " 1) Merge into templates (recommended for small differences)"
echo " 2) Keep separate files per host (recommended for large differences)"
echo " 3) Manual (skip automatic migration)"
read -p "Choose (1/2/3): " -r STRATEGY
if [ "$STRATEGY" = "1" ]; then
log_info "Will merge into templates (requires manual editing after)"
# Create template files
# ... migration logic ...
elif [ "$STRATEGY" = "2" ]; then
log_info "Creating separate host-specific files..."
for host in air lakka tunkki s; do
if [ -d "hosts/$host" ]; then
log_info "Processing host: $host"
# Process host-specific base files
if [ -d "hosts/$host/base" ]; then
for file in hosts/$host/base/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
move_dotfiles "$file" "dot_${filename}__${host}" ""
fi
done
fi
# Process host-specific config files
if [ -d "hosts/$host/config" ]; then
for file in hosts/$host/config/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
dest="dot_config/$(dirname $file)__${host}"
move_dotfiles "$file" "$dest/$(basename $file)" ""
fi
done
fi
fi
done
else
log_info "Skipping automatic host-specific migration"
log_info "You'll need to manually migrate hosts/ directory"
fi
```
## Best Practices
1. **Start Simple**: Use separate files first, move to templates as you see patterns
2. **Don't Over-Template**: If a file is completely different per host, use separate files
3. **Document Hosts**: Add comments in `.chezmoi.yaml.tmpl` explaining each host
4. **Test Thoroughly**: Test on each host before committing
5. **Use Host Groups**: Group hosts (work/personal, laptop/desktop) for easier conditionals
## Checklist
- [ ] Identify all host-specific files
- [ ] Choose strategy per file (templates vs separate)
- [ ] Update `.chezmoi.yaml.tmpl` with host flags
- [ ] Migrate host-specific base files
- [ ] Migrate host-specific config files
- [ ] Update `.chezmoiignore` for host-specific directories
- [ ] Test on current host
- [ ] Test on other hosts
- [ ] Document which approach was used where
- [ ] Clean up old hosts/ directory
## Examples from Your Hosts
Based on your current structure:
### hosts/air/install.conf.yaml
```yaml
- link:
~/.config/:
path: hosts/air/config/**
```
**Migration approach:**
- Check what's in `hosts/air/config/`
- If it's app configs, use separate files: `dot_config/app/config__air`
- If it's just a few lines different, merge into templates
### Common Pattern
For configurations that need host-specific values but share structure:
```yaml
# dot_config/app/config.tmpl
# Common settings
port=8080
# Host-specific
{{ if .is_air -}}
workspace=/Users/yourname/Work
{{- else if .is_lakka -}}
workspace=/Users/yourname/Projects
{{- end }}
# More common settings
debug=false
```
## Need Help?
If you're unsure about a specific file:
1. Check the diff: `diff hosts/air/file hosts/lakka/file`
2. Count different lines
3. If < 20% different use templates
4. If > 20% different → use separate files
Remember: You can always refactor later!

View File

@@ -1,523 +0,0 @@
# Migration Guide: Dotbot to Chezmoi
This guide documents the migration from dotbot to chezmoi for managing dotfiles.
## Table of Contents
1. [Why Migrate to Chezmoi?](#why-migrate-to-chezmoi)
2. [Key Differences](#key-differences)
3. [Dotbot to Chezmoi Mapping](#dotbot-to-chezmoi-mapping)
4. [New File Structure](#new-file-structure)
5. [Migration Steps](#migration-steps)
6. [Usage Guide](#usage-guide)
7. [Troubleshooting](#troubleshooting)
## Why Migrate to Chezmoi?
Chezmoi offers several advantages over dotbot:
- **Built-in templating**: Use Go templates for dynamic configuration
- **Secret management**: Native support for password managers (1Password, LastPass, etc.)
- **Cross-platform**: Better support for managing dotfiles across different OS and machines
- **State tracking**: Chezmoi tracks what it manages more precisely
- **Active development**: Regular updates and large community
- **No dependencies**: Single binary, no Python required
## Key Differences
### Philosophy
**Dotbot**:
- Configuration-driven (YAML files)
- Manages symlinks from a source directory
- Plugins extend functionality
**Chezmoi**:
- Source-state driven
- Copies files to home directory (can also use symlinks)
- Built-in templating for dynamic content
- Manages the entire lifecycle of dotfiles
### Directory Structure
**Dotbot**:
```
~/.dotfiles/
├── base/ # Files symlinked to ~/.*
├── config/ # Files symlinked to ~/.config/
├── local/ # Scripts and local files
├── install # Installation script
└── install.conf.yaml # Configuration
```
**Chezmoi**:
```
~/.local/share/chezmoi/ # Source directory
├── .chezmoi.yaml.tmpl # Configuration template
├── .chezmoiignore # Files to ignore
├── run_once_*.sh.tmpl # One-time setup scripts
├── run_*.sh.tmpl # Scripts that run on every apply
├── dot_bashrc # Becomes ~/.bashrc
├── dot_config/ # Becomes ~/.config/
└── private_dot_ssh/ # Becomes ~/.ssh/ with 0700
```
## Dotbot to Chezmoi Mapping
### 1. Link Directives
**Dotbot** (install.conf.yaml):
```yaml
- link:
~/.bashrc: base/bashrc
~/.config/fish: config/fish
```
**Chezmoi**:
- Files are automatically managed based on their names in the source directory
- `dot_bashrc``~/.bashrc`
- `dot_config/fish/``~/.config/fish/`
- Use `symlink_` prefix for symlinks: `symlink_dot_vim` → symlinked `~/.vim`
### 2. Create Directives
**Dotbot**:
```yaml
- create:
~/.ssh:
mode: 0700
~/.local/bin:
```
**Chezmoi**:
- Create a `run_once_after_create-directories.sh.tmpl` script
- Or use `.chezmoitemplates` for reusable directory creation
- Chezmoi automatically creates parent directories
### 3. Shell Commands
**Dotbot**:
```yaml
- shell:
- git submodule update --init --recursive
- bash local/bin/dfm install all
```
**Chezmoi**:
- Use `run_once_*.sh.tmpl` for one-time setup scripts
- Use `run_*.sh.tmpl` for scripts that run every time
- Use `run_before_*.sh` for scripts that run before applying
- Use `run_after_*.sh` for scripts that run after applying
### 4. Clean Directives
**Dotbot**:
```yaml
- clean:
~/:
~/.config:
recursive: true
```
**Chezmoi**:
- Chezmoi doesn't automatically remove files
- Use `chezmoi unmanaged` to see unmanaged files
- Manually remove or add to `.chezmoiignore`
### 5. Host-Specific Configuration
**Dotbot**:
```yaml
# hosts/air/install.conf.yaml
- link:
~/.config/:
path: hosts/air/config/**
```
**Chezmoi**:
- Use templates with conditionals:
```
{{ if eq .chezmoi.hostname "air" }}
# air-specific content
{{ end }}
```
- Or use separate files: `dot_config/file.tmpl` with hostname checks
### 6. Dotbot Plugins
**dotbot-brew**:
- Replace with `run_once_after_install-packages.sh.tmpl`
- Use `brew bundle install`
**dotbot-asdf**:
- Chezmoi doesn't have built-in asdf support
- Use `run_once_after_*.sh` scripts to install asdf plugins
**dotbot-pip/pipx**:
- Use `run_once_after_*.sh` scripts
- Or use chezmoi's external management
## New File Structure
### Configuration Files
#### `.chezmoi.yaml.tmpl`
Main configuration file with template support. Defines:
- Source directory
- Data variables (hostname, OS, custom flags)
- Merge strategy
- Template options
- Git options
#### `.chezmoiignore`
Files and patterns to ignore when applying dotfiles. Includes:
- Repository management files (.git, .github, etc.)
- Documentation
- Development tools
- Old dotbot configuration
### Run Scripts
Scripts follow a naming convention:
- `run_once_before_*.sh.tmpl`: Runs once before applying (prerequisites)
- `run_once_after_*.sh.tmpl`: Runs once after applying (installation)
- `run_before_*.sh.tmpl`: Runs every time before applying
- `run_after_*.sh.tmpl`: Runs every time after applying
- `run_onchange_*.sh.tmpl`: Runs when file content changes
### File Naming
Chezmoi uses special prefixes:
- `dot_`: Becomes a dot file (`.`)
- `private_`: Sets permissions to 0600
- `executable_`: Makes file executable
- `symlink_`: Creates a symlink
- `readonly_`: Makes file read-only
Examples:
- `dot_bashrc``~/.bashrc`
- `private_dot_ssh/``~/.ssh/` (mode 0700)
- `executable_dot_local/bin/script``~/.local/bin/script` (executable)
## Migration Steps
### 1. Backup Current Setup
```bash
# Backup your current dotfiles
cd ~/.dotfiles
git add -A
git commit -m "Backup before chezmoi migration"
git push
```
### 2. Install Chezmoi
```bash
# The new install script will do this automatically
sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen
```
### 3. Initialize Chezmoi with Existing Dotfiles
```bash
# If you want to test before full migration
chezmoi init --apply ivuorinen
# Or initialize without applying
chezmoi init ivuorinen
```
### 4. Restructure Files (Manual Step)
You'll need to rename files to follow chezmoi conventions:
```bash
cd ~/.local/share/chezmoi
# Rename base files
mv base/bashrc dot_bashrc
mv base/zshrc dot_zshrc
mv base/tmux.conf dot_tmux.conf
# Move config files
mkdir -p dot_config
mv config/* dot_config/
# Move local/bin files
mkdir -p dot_local/bin
for file in local/bin/*; do
mv "$file" "executable_dot_local/bin/$(basename "$file")"
done
# Move SSH files with proper permissions
mkdir -p private_dot_ssh
mv ssh/* private_dot_ssh/
```
### 5. Convert Host-Specific Configurations
For files that differ between hosts, use templates:
```bash
# Instead of hosts/air/config/fish/config.fish
# Create: dot_config/fish/config.fish.tmpl
{{ if eq .chezmoi.hostname "air" }}
# air-specific configuration
{{ else if eq .chezmoi.hostname "lakka" }}
# lakka-specific configuration
{{ end }}
```
### 6. Test the Migration
```bash
# See what changes chezmoi would make
chezmoi diff
# Apply changes
chezmoi apply
# Verify everything works
chezmoi verify
```
### 7. Clean Up Old Files
```bash
# Remove dotbot directories (after confirming everything works)
cd ~/.local/share/chezmoi
rm -rf tools/dotbot tools/dotbot-*
rm install.conf.yaml
rm -rf hosts/ # If fully migrated to templates
```
## Usage Guide
### Basic Commands
```bash
# Initialize chezmoi with your dotfiles
chezmoi init ivuorinen
# See what changes would be made
chezmoi diff
# Apply dotfiles
chezmoi apply
# Apply with verbose output
chezmoi apply -v
# Edit a file managed by chezmoi
chezmoi edit ~/.bashrc
# Add a new file to chezmoi
chezmoi add ~/.newfile
# Update dotfiles from source
chezmoi update
# See what files are managed
chezmoi managed
# See what files are unmanaged
chezmoi unmanaged
# Re-run scripts
chezmoi apply --force
# Check for issues
chezmoi doctor
```
### Working with Templates
```bash
# Execute a template
chezmoi execute-template "{{ .chezmoi.hostname }}"
# See the data available in templates
chezmoi data
# Edit template data
chezmoi edit-config
```
### Managing Secrets
```bash
# Use with 1Password
chezmoi secret keychain
# Template with 1Password
{{ (index (onepasswordDocument "my-secret") 0).content }}
# Use with environment variables
{{ .Env.MY_SECRET }}
```
### Updating Dotfiles
```bash
# Edit source file
chezmoi edit ~/.bashrc
# Or edit directly and add
vi ~/.bashrc
chezmoi add ~/.bashrc
# Commit changes
cd $(chezmoi source-path)
git add -A
git commit -m "Update bashrc"
git push
# On another machine
chezmoi update
```
## Troubleshooting
### Common Issues
#### 1. File Permissions
**Problem**: Files have wrong permissions after applying.
**Solution**: Use prefixes:
```bash
# For 0600 permissions
chezmoi add --template private_dot_ssh/config
# For 0700 directories
mkdir -p private_dot_ssh
```
#### 2. Symlinks Not Working
**Problem**: Chezmoi copies files instead of symlinking.
**Solution**: Use `symlink_` prefix:
```bash
chezmoi add --symlink ~/.vim
# This creates symlink_dot_vim in the source directory
```
#### 3. Templates Not Rendering
**Problem**: Template syntax is showing literally in files.
**Solution**:
- Ensure file has `.tmpl` extension
- Check template syntax
- Verify data with `chezmoi data`
#### 4. Scripts Not Running
**Problem**: `run_once_` scripts not executing.
**Solution**:
- Check script permissions: `chmod +x run_once_*.sh.tmpl`
- Run with force: `chezmoi apply --force`
- Check script order (before/after)
#### 5. Host-Specific Files Not Applying
**Problem**: Wrong host configuration applied.
**Solution**:
- Check hostname: `chezmoi data | grep hostname`
- Verify template conditionals
- Use `.chezmoiignore` for host-specific exclusions
### Debugging
```bash
# Verbose output
chezmoi apply -v
# Very verbose output
chezmoi apply -vv
# Dry run to see what would happen
chezmoi apply --dry-run -v
# Check configuration
chezmoi doctor
# Verify state
chezmoi verify
# See source directory
chezmoi source-path
# See what would be applied to a specific file
chezmoi cat ~/.bashrc
```
### Migration Checklist
- [ ] Backup current dotfiles
- [ ] Install chezmoi
- [ ] Create `.chezmoi.yaml.tmpl`
- [ ] Create `.chezmoiignore`
- [ ] Rename files with proper prefixes
- [ ] Convert host-specific configs to templates
- [ ] Create `run_once_before` scripts
- [ ] Create `run_once_after` scripts
- [ ] Test with `chezmoi diff`
- [ ] Apply with `chezmoi apply`
- [ ] Verify everything works
- [ ] Update documentation
- [ ] Clean up old dotbot files
- [ ] Update README.md
- [ ] Test on another machine
## Additional Resources
- [Chezmoi Documentation](https://www.chezmoi.io/)
- [Chezmoi Quick Start](https://www.chezmoi.io/quick-start/)
- [Chezmoi User Guide](https://www.chezmoi.io/user-guide/)
- [Chezmoi Template Reference](https://www.chezmoi.io/reference/templates/)
- [Example Dotfiles Using Chezmoi](https://github.com/topics/chezmoi)
## Notes
### What Stays the Same
- Your actual dotfile contents
- Directory structure in home directory
- Git workflow for managing dotfiles
- The `dfm` script functionality (wrapped in run_once scripts)
### What Changes
- Installation method (new `install` script)
- Source directory location (`~/.local/share/chezmoi` by default)
- Configuration method (templates instead of YAML)
- File naming (special prefixes)
- No more symlinks by default (unless specified)
### Benefits of Migration
1. **Simplicity**: Single binary, no dependencies
2. **Templating**: Dynamic content based on hostname, OS, etc.
3. **Secrets**: Built-in support for password managers
4. **State Management**: Better tracking of what's managed
5. **Cross-platform**: Excellent support for different OSes
6. **Documentation**: Extensive docs and examples
7. **Community**: Active development and support
## Post-Migration
After successful migration:
1. Update your README to reflect chezmoi usage
2. Archive dotbot configuration for reference
3. Document any custom scripts or workflows
4. Test on all your machines
5. Share your experience!

View File

@@ -33,7 +33,7 @@ Leader: `<ctrl><space>`
? List key bindings
D Choose and detach a client from a list
E Spread panes out evenly
L last-session (via sesh)
L last-session (via sesh)
M Clear the marked pane
N sesh ui
T tms
@@ -87,4 +87,3 @@ Leader: `<ctrl><space>`
S-Left Move the visible part of the window left
S-Right Move the visible part of the window right
```

37
install
View File

@@ -1,5 +1,38 @@
#!/usr/bin/env bash
set -e
# Install and apply chezmoi
sh -c "$(curl -fsLS get.chezmoi.io/lb)" -- init --apply ivuorinen
CONFIG="install.conf.yaml"
DOTBOT_DIR="tools/dotbot"
DOTBOT_BIN="bin/dotbot"
BASEDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOTBOT_BIN_PATH="${BASEDIR}/${DOTBOT_DIR}/${DOTBOT_BIN}"
DOTBOT_HOST="$(hostname -s)"
cd "${BASEDIR}"
git -C "${DOTBOT_DIR}" submodule sync --quiet --recursive
git submodule update --init --recursive "${DOTBOT_DIR}"
"${DOTBOT_BIN_PATH}" \
-d "${BASEDIR}" \
--plugin-dir=tools/dotbot-asdf \
--plugin-dir=tools/dotbot-brew \
--plugin-dir=tools/dotbot-include \
--plugin-dir=tools/dotbot-pip \
-c "${CONFIG}" \
"${@}"
if [ "${DOTBOT_HOST}" != "" ]; then
DOTBOT_HOST_CONFIG="${BASEDIR}/hosts/${DOTBOT_HOST}/${CONFIG}"
echo "-> Trying if host config can be found: ${DOTBOT_HOST_CONFIG}"
[ -r "$DOTBOT_HOST_CONFIG" ] && [ -f "$DOTBOT_HOST_CONFIG" ] &&
echo "(!) Found $DOTBOT_HOST_CONFIG" &&
"$DOTBOT_BIN_PATH" \
-d "$BASEDIR" \
--plugin-dir=tools/dotbot-asdf \
--plugin-dir=tools/dotbot-brew \
--plugin-dir=tools/dotbot-include \
--plugin-dir=tools/dotbot-pip \
-c "$DOTBOT_HOST_CONFIG" \
"${@}"
fi

View File

@@ -103,9 +103,9 @@ fetch_keys_if_missing()
if [[ ! -f "$KEYS_FILE" ]]; then
log_message "Keys file '$KEYS_FILE' not found. Attempting to fetch from $KEYS_SOURCE..."
mkdir -p "$(dirname "$KEYS_FILE")"
curl -s "$KEYS_SOURCE" -o "$KEYS_FILE"
if [[ $? -ne 0 || ! -s "$KEYS_FILE" ]]; then
if ! curl -s "$KEYS_SOURCE" -o "$KEYS_FILE" || [[ ! -s "$KEYS_FILE" ]]; then
rm -f "$KEYS_FILE" 2> /dev/null || true
log_message "Error: Failed to fetch keys from $KEYS_SOURCE"
exit 1
fi
@@ -126,10 +126,12 @@ encrypt_file_or_directory()
elif [[ -f "$file" ]]; then
fetch_keys_if_missing
local output_file="${file}.age"
age -R "$KEYS_FILE" "$file" > "$output_file"
if [[ $? -eq 0 ]]; then
local temp_file
temp_file="$(mktemp -p "$(dirname "$file")")"
if age -R "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
log_message "File encrypted successfully: $output_file"
else
rm -f "$temp_file"
log_message "Error: Failed to encrypt file '$file'."
exit 1
fi
@@ -147,10 +149,12 @@ decrypt_file_or_directory()
elif [[ -f "$file" ]]; then
fetch_keys_if_missing
local output_file="${file%.age}"
age -d -i "$KEYS_FILE" "$file" > "$output_file"
if [[ $? -eq 0 ]]; then
local temp_file
temp_file="$(mktemp -p "$(dirname "$file")")"
if age -d -i "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
log_message "File decrypted successfully: $output_file"
else
rm -f "$temp_file"
log_message "Error: Failed to decrypt file '$file'."
exit 1
fi

View File

@@ -36,9 +36,8 @@ if [[ ! -f "$KEYS_FILE" ]]; then
mkdir -p "$(dirname "$KEYS_FILE")"
# Fetch the keys and save to the file
curl -s "$KEYS_SOURCE" -o "$KEYS_FILE"
if [[ $? -ne 0 || ! -s "$KEYS_FILE" ]]; then
if ! curl -s "$KEYS_SOURCE" -o "$KEYS_FILE" || [[ ! -s "$KEYS_FILE" ]]; then
rm -f "$KEYS_FILE" 2> /dev/null || true
echo "Error: Failed to fetch keys from $KEYS_SOURCE"
exit 1
fi
@@ -50,11 +49,11 @@ fi
# Decrypt the file
OUTPUT_FILE="${FILE%.age}"
age -d -i "$KEYS_FILE" "$FILE" > "$OUTPUT_FILE"
if [[ $? -eq 0 ]]; then
TEMP_FILE="$(mktemp -p "$(dirname "$OUTPUT_FILE")")"
if age -d -i "$KEYS_FILE" "$FILE" > "$TEMP_FILE" && mv "$TEMP_FILE" "$OUTPUT_FILE"; then
echo "File decrypted successfully: $OUTPUT_FILE"
else
rm -f "$TEMP_FILE"
echo "Error: Failed to decrypt file."
exit 1
fi

View File

@@ -37,9 +37,7 @@ if [[ ! -f "$KEYS_FILE" ]]; then
mkdir -p "$(dirname "$KEYS_FILE")"
# Fetch the keys and save to the file
curl -s "$KEYS_SOURCE" -o "$KEYS_FILE"
if [[ $? -ne 0 || ! -s "$KEYS_FILE" ]]; then
if ! curl -s "$KEYS_SOURCE" -o "$KEYS_FILE" || [[ ! -s "$KEYS_FILE" ]]; then
echo "Error: Failed to fetch keys from $KEYS_SOURCE"
exit 1
fi
@@ -51,9 +49,7 @@ fi
# Encrypt the file
OUTPUT_FILE="${FILE}.age"
age -R "$KEYS_FILE" "$FILE" > "$OUTPUT_FILE"
if [[ $? -eq 0 ]]; then
if age -R "$KEYS_FILE" "$FILE" > "$OUTPUT_FILE"; then
echo "File encrypted successfully: $OUTPUT_FILE"
else
echo "Error: Failed to encrypt file."

View File

@@ -25,6 +25,7 @@ source_file()
case "$CURRENT_SHELL" in
fish)
if [[ -f "$file.fish" ]]; then
# shellcheck disable=SC1090
source "$file.fish"
else
echo "Fish shell file not found: $file.fish"
@@ -32,6 +33,7 @@ source_file()
fi
;;
sh | bash | zsh)
# shellcheck disable=SC1090
source "$file"
;;
*)

View File

@@ -142,7 +142,7 @@ if [[ ! "$opt" =~ "-E" ]] && tmux list-panes -F '#F' | grep -q Z; then
zoomed_without_popup=1
original_window=$(tmux display-message -p "#{window_id}")
tmp_window=$(tmux new-window -d -P -F "#{window_id}" "bash -c 'while :; do for c in \\| / - '\\;' do sleep 0.2; printf \"\\r\$c fzf-tmux is running\\r\"; done; done'")
tmux swap-pane -t $tmp_window \; select-window -t $tmp_window
tmux swap-pane -t "$tmp_window" \; select-window -t "$tmp_window"
fi
set -e
@@ -154,15 +154,16 @@ fifo1="${TMPDIR:-/tmp}/fzf-fifo1-$id"
fifo2="${TMPDIR:-/tmp}/fzf-fifo2-$id"
fifo3="${TMPDIR:-/tmp}/fzf-fifo3-$id"
if tmux_win_opts=$(tmux show-options -p remain-on-exit \; show-options -p synchronize-panes 2> /dev/null); then
tmux_win_opts=($(sed '/ off/d; s/synchronize-panes/set-option -p synchronize-panes/; s/remain-on-exit/set-option -p remain-on-exit/; s/$/ \\;/' <<< "$tmux_win_opts"))
mapfile -t tmux_win_opts < <(sed '/ off/d; s/synchronize-panes/set-option -p synchronize-panes/; s/remain-on-exit/set-option -p remain-on-exit/; s/$/ \\;/' <<< "$tmux_win_opts")
tmux_off_opts='; set-option -p synchronize-panes off ; set-option -p remain-on-exit off'
else
tmux_win_opts=($(tmux show-window-options remain-on-exit \; show-window-options synchronize-panes | sed '/ off/d; s/^/set-window-option /; s/$/ \\;/'))
mapfile -t tmux_win_opts < <(tmux show-window-options remain-on-exit \; show-window-options synchronize-panes | sed '/ off/d; s/^/set-window-option /; s/$/ \\;/')
tmux_off_opts='; set-window-option synchronize-panes off ; set-window-option remain-on-exit off'
fi
# shellcheck disable=SC2329
cleanup()
{
\rm -f $argsf $fifo1 $fifo2 $fifo3
\rm -f "$argsf" "$fifo1" "$fifo2" "$fifo3"
# Restore tmux window options
if [[ "${#tmux_win_opts[@]}" -gt 0 ]]; then
@@ -172,9 +173,9 @@ cleanup()
# Remove temp window if we were zoomed without popup options
if [[ -n "$zoomed_without_popup" ]]; then
tmux display-message -p "#{window_id}" > /dev/null
tmux swap-pane -t $original_window \; \
select-window -t $original_window \; \
kill-window -t $tmp_window \; \
tmux swap-pane -t "$original_window" \; \
select-window -t "$original_window" \; \
kill-window -t "$tmp_window" \; \
resize-pane -Z
fi
@@ -209,39 +210,40 @@ echo "$envs;" > "$argsf"
opts=$(printf "%q " "${args[@]}")
pppid=$$
echo -n "trap 'kill -SIGUSR1 -$pppid' EXIT SIGINT SIGTERM;" >> $argsf
echo -n "trap 'kill -SIGUSR1 -$pppid' EXIT SIGINT SIGTERM;" >> "$argsf"
close="; trap - EXIT SIGINT SIGTERM $close"
export TMUX=$(cut -d , -f 1,2 <<< "$TMUX")
mkfifo -m o+w $fifo2
export TMUX
TMUX=$(cut -d , -f 1,2 <<< "$TMUX")
mkfifo -m o+w "$fifo2"
if [[ "$opt" =~ "-E" ]]; then
cat $fifo2 &
cat "$fifo2" &
if [[ -n "$term" ]] || [[ -t 0 ]]; then
cat <<< "\"$fzf\" $opts > $fifo2; out=\$? $close; exit \$out" >> $argsf
cat <<< "\"$fzf\" $opts > $fifo2; out=\$? $close; exit \$out" >> "$argsf"
else
mkfifo $fifo1
cat <<< "\"$fzf\" $opts < $fifo1 > $fifo2; out=\$? $close; exit \$out" >> $argsf
cat <&0 > $fifo1 &
mkfifo "$fifo1"
cat <<< "\"$fzf\" $opts < $fifo1 > $fifo2; out=\$? $close; exit \$out" >> "$argsf"
cat <&0 > "$fifo1" &
fi
tmux popup -d "$PWD" $opt "bash $argsf" > /dev/null 2>&1
tmux popup -d "$PWD" "$opt" "bash $argsf" > /dev/null 2>&1
exit $?
fi
mkfifo -m o+w $fifo3
mkfifo -m o+w "$fifo3"
if [[ -n "$term" ]] || [[ -t 0 ]]; then
cat <<< "\"$fzf\" $opts > $fifo2; echo \$? > $fifo3 $close" >> $argsf
cat <<< "\"$fzf\" $opts > $fifo2; echo \$? > $fifo3 $close" >> "$argsf"
else
mkfifo $fifo1
cat <<< "\"$fzf\" $opts < $fifo1 > $fifo2; echo \$? > $fifo3 $close" >> $argsf
cat <&0 > $fifo1 &
mkfifo "$fifo1"
cat <<< "\"$fzf\" $opts < $fifo1 > $fifo2; echo \$? > $fifo3 $close" >> "$argsf"
cat <&0 > "$fifo1" &
fi
tmux \
split-window -c "$PWD" $opt "bash -c 'exec -a fzf bash $argsf'" $swap \
$tmux_off_opts \
split-window -c "$PWD" "$opt" "bash -c 'exec -a fzf bash $argsf'" "$swap" \
"$tmux_off_opts" \
> /dev/null 2>&1 || {
"$fzf" "${args[@]}"
exit $?
}
cat $fifo2
exit "$(cat $fifo3)"
cat "$fifo2"
exit "$(cat "$fifo3")"

View File

@@ -25,27 +25,27 @@ fi
# Output functions
msg_err()
{
echo -e "\e[31m$@\e[0m" >&2
echo -e "\e[31m$*\e[0m" >&2
}
msg_success()
{
echo -e "\e[32m$@\e[0m"
echo -e "\e[32m$*\e[0m"
}
msg_warn()
{
echo -e "\e[33m$@\e[0m" >&2
echo -e "\e[33m$*\e[0m" >&2
}
msg_info()
{
echo -e "\e[36m$@\e[0m"
echo -e "\e[36m$*\e[0m"
}
msg_debug()
{
[[ $VERBOSE -eq 1 ]] && echo -e "\e[35m$@\e[0m"
[[ $VERBOSE -eq 1 ]] && echo -e "\e[35m$*\e[0m"
}
show_help()
@@ -180,7 +180,8 @@ format_rule()
get_file_extension()
{
local file="$1"
local basename=$(basename "$file")
local basename
basename=$(basename "$file")
local extension=""
# Check if file has no extension or is a dotfile
@@ -231,8 +232,8 @@ suggest_rule()
# If file path contains .d/ pattern, we need special handling
if [[ "$file" =~ \.d/ ]]; then
# Extract the pattern part that includes the .d/ directory
local dir_part=$(dirname "$file")
local base_name=$(basename "$file")
local dir_part
dir_part=$(dirname "$file")
# Check if it's a config directory pattern worth capturing
if [[ "$dir_part" =~ /(\.d|[^/]+\.d)$ ]]; then
@@ -430,7 +431,8 @@ detect_shell_scripts()
fi
# Skip if file extension already covered
local extension=$(get_file_extension "$rel_path")
local extension
extension=$(get_file_extension "$rel_path")
if [[ "$extension" != "$rel_path" ]] && grep -q "^\*\.$extension " <<< "$existing_rules"; then
msg_debug "Script covered by extension rule: $rel_path (*.$extension)"
continue
@@ -458,7 +460,8 @@ detect_shell_scripts()
fi
# Group by directory
local dir=$(dirname "$rel_path")
local dir
dir=$(dirname "$rel_path")
if [[ "$dir" == "." ]]; then
dir="root"
fi
@@ -480,7 +483,8 @@ detect_shell_scripts()
# Check if we can use directory-based rules instead of individual files
for dir in "${!scripts_by_dir[@]}"; do
local files_in_dir=$(echo -e "${scripts_by_dir[$dir]}" | wc -l)
local files_in_dir
files_in_dir=$(echo -e "${scripts_by_dir[$dir]}" | wc -l)
local dir_path="$dir"
if [[ "$dir" == "root" ]]; then
@@ -575,7 +579,8 @@ suggest_gitattributes()
declare -A seen_patterns=()
while IFS= read -r file; do
local suggestion=$(suggest_rule "$file")
local suggestion
suggestion=$(suggest_rule "$file")
if [[ -n "$suggestion" ]]; then
IFS=':' read -r pattern attributes <<< "$suggestion"
@@ -639,7 +644,8 @@ suggest_gitattributes()
formatted_suggestions+="$pattern\n"
echo "$pattern"
else
local formatted_rule=$(printf "%-${format_width}s %s\n" "$pattern" "$attributes")
local formatted_rule
formatted_rule=$(printf "%-${format_width}s %s\n" "$pattern" "$attributes")
formatted_suggestions+="$formatted_rule\n"
echo "$formatted_rule"
fi

1
local/bin/iterm2_shell_integration.zsh Executable file → Normal file
View File

@@ -1,3 +1,4 @@
# shellcheck disable=all
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2

View File

@@ -142,7 +142,7 @@ if [ ! -x "${CURL}" ]; then
exit 1
fi
devices="$(printf "${devices}" | xargs -n1 | sort -u | uniq)\n"
devices="$(printf "%s" "${devices}" | xargs -n1 | sort -u)"
if [ -z "${devices}" ]; then
__pushover_send_message

View File

@@ -126,11 +126,11 @@ if [[ -f "$CONFIG_FILE" ]]; then
PROTECTED_KEYS+=("$key")
done <<< "$CUSTOM_KEYS"
SKIPPED+=("$(yq '.skipped_keys[]' "$CONFIG_FILE")")
while IFS= read -r key; do
mapfile -t SKIPPED < <(yq '.skipped_keys[]' "$CONFIG_FILE")
for key in "${SKIPPED[@]}"; do
# Add to default_skipped_keys
SKIPPED_KEYS+=("$key")
done <<< "$SKIPPED"
done
CUSTOM_GROUPS=$(yq '.custom_grouping[]' "$CONFIG_FILE")
while IFS= read -r group; do
@@ -159,6 +159,7 @@ is_protected()
return 0
fi
# Wildcard match (protected_key contains '*')
# shellcheck disable=SC2053 # Intentional glob matching - protected_key contains wildcard patterns
if [[ "$protected_key" == *"*"* ]] && [[ "$key" == $protected_key ]]; then
return 0
fi
@@ -198,6 +199,7 @@ is_skipped()
return 0
fi
# Wildcard match (skipped_key contains '*')
# shellcheck disable=SC2053 # Intentional glob matching - skipped_key contains wildcard patterns
if [[ "$skipped_key" == *"*"* ]] && [[ "$key" == $skipped_key ]]; then
return 0
fi
@@ -244,8 +246,15 @@ while IFS='=' read -r key value; do
value="[protected value]"
fi
# Update group data
if [[ ! " ${all_groups[*]} " =~ " $group " ]]; then
# Update group data - check if group already exists
group_exists=false
for existing_group in "${all_groups[@]}"; do
if [[ "$existing_group" == "$group" ]]; then
group_exists=true
break
fi
done
if [[ "$group_exists" == false ]]; then
all_groups+=("$group")
fi

View File

@@ -30,10 +30,9 @@ config_msg()
{
# if $1 is empty, return
[ -z "$1" ] && return
[ -z "$2" ] && $2=""
local msg_type="$1"
local msg_content="$2"
local msg_content="${2:-}"
[[ "$VERBOSE" -eq 1 ]] && printf 'x-load-configs: %s %s\n' "$msg_type" "$msg_content"
return 0
}
@@ -50,7 +49,8 @@ source_config()
{
local config_file=$1
if [ -f "$config_file" ]; then
eval "$config_file"
# shellcheck disable=SC1090
source "$config_file"
config_msg "Sourced" "$config_file"
else
msg "Config file $config_file not found"

View File

@@ -60,7 +60,7 @@ log_debug()
filter_coderabbit_addressed_comments()
{
local input_data="$1"
local is_wrapped="$2" # true for {comments: [...]}, false for [...]
local is_wrapped="$2" # true for {comments: [...]}, false for [...]
local jq_filter='select(
(.user.login | contains("coderabbit") | not) or
@@ -68,9 +68,9 @@ filter_coderabbit_addressed_comments()
)'
if [[ "$is_wrapped" == "true" ]]; then
echo "$input_data" | jq "{comments: [.comments[] | $jq_filter]}" 2>/dev/null || echo "$input_data"
echo "$input_data" | jq "{comments: [.comments[] | $jq_filter]}" 2> /dev/null || echo "$input_data"
else
echo "$input_data" | jq "[.[] | $jq_filter]" 2>/dev/null || echo "$input_data"
echo "$input_data" | jq "[.[] | $jq_filter]" 2> /dev/null || echo "$input_data"
fi
}
@@ -79,13 +79,13 @@ fetch_and_filter_data()
{
local endpoint="$1"
local data_name="$2"
local is_wrapped="$3" # true/false
local is_wrapped="$3" # true/false
local data
data=$(gh api "$endpoint" 2>/dev/null || echo "[]")
data=$(gh api "$endpoint" 2> /dev/null || echo "[]")
if [[ "$is_wrapped" == "true" ]]; then
data=$(echo "$data" | jq '{comments: .}' 2>/dev/null || echo '{"comments":[]}')
data=$(echo "$data" | jq '{comments: .}' 2> /dev/null || echo '{"comments":[]}')
fi
data=$(filter_coderabbit_addressed_comments "$data" "$is_wrapped")
@@ -94,14 +94,12 @@ fetch_and_filter_data()
[[ "$is_wrapped" == "true" ]] && count_field=".comments | length"
local count
count=$(echo "$data" | jq -r "$count_field" 2>/dev/null || echo "0")
count=$(echo "$data" | jq -r "$count_field" 2> /dev/null || echo "0")
log_debug "$data_name count: $count"
echo "$data"
}
# Format file-specific comments grouped by review
format_grouped_review_comments()
{
@@ -110,7 +108,7 @@ format_grouped_review_comments()
local repo="$3"
local count
count=$(echo "$review_comments" | jq -r 'length' 2>/dev/null || echo "0")
count=$(echo "$review_comments" | jq -r 'length' 2> /dev/null || echo "0")
if [[ "$count" -eq 0 ]]; then
echo "No file-specific comments found."
@@ -143,7 +141,7 @@ Review ID: \($review.id) - API: gh api /repos/'"$repo"'/pulls/1/reviews/\($revie
"] | join("")) + "
---
"
' 2>/dev/null || {
' 2> /dev/null || {
log_debug "Error grouping review comments by review ID"
echo "Error parsing grouped review comments."
}
@@ -244,7 +242,7 @@ EOF
**URL:** \(.url)
**Number:** '"$pr_number"'
**Repository:** '"$repo"'
"' 2>/dev/null || {
"' 2> /dev/null || {
echo "**Error:** Could not parse PR information"
return 1
}

2
local/bin/x-ssh-audit Normal file → Executable file
View File

@@ -350,7 +350,7 @@ ssh_with_retry()
log_message "INFO" "Trying SSH agent/default authentication"
fi
# shellcheck disable=SC2086
# shellcheck disable=SC2086,SC2029
if ssh $ssh_opts "${username}@${host}" "$command" 2> /dev/null; then
if [ "$try_key" != "NO_KEY" ]; then
log_message "SUCCESS" "Connected using SSH key: $try_key"

View File

@@ -52,17 +52,18 @@ fi
for name in "$@"; do
# Make a temporary file
# Test if we have BSD or GNU version of mktemp
if (strings "$(which mktemp)" | grep -q GNU); then
# We have the GNU version
tmp=$(mktemp)
# Try GNU syntax first, fall back to BSD
if tmp=$(mktemp 2> /dev/null) && [ -f "$tmp" ]; then
# GNU mktemp succeeded
:
else
# We have the BSD version
# Try BSD syntax
tmp=$(mktemp -t tmp)
fi
# Download the certificate
if (! echo "" | openssl s_client -connect "$name:$port" > "$tmp" 2> /dev/null); then
rm -f "$tmp"
echo "Failed to get cert from https://$name:$port/"
exit 3
fi
@@ -74,26 +75,26 @@ for name in "$@"; do
rm -f "$tmp"
# Convert the expiry date + todays date to seconds-past epoch
# Check if we have the BSD or the GNU version of date
if (strings "$(which date)" | grep -q GNU); then
# We have GNU this is easy
then=$(date --date "$date" +%s)
# Try GNU syntax first, fall back to BSD
if then=$(date --date "$date" +%s 2> /dev/null); then
# GNU date succeeded
:
else
# We have BSD now it is getting complicated
# BSD date requires manual parsing
year=$(echo "$date" | awk '{print $4}')
month=$(echo "$date" | awk '{print $1}')
day=$(echo "$date" | awk '{print $2}')
hour=$(echo "$date" | awk '{print $3}' | awk -F: '{print $1}')
minute=$(echo "$date" | awk '{print $3}' | awk -F: '{print $2}')
second=$(echo "$date" | awk '{print $3}' | awk -F: '{print $3}')
then=$(date -v${year}y -v${month} -v${day}d -v${hour}H -v${minute}M -v${second}S -u +%s)
then=$(date -v"${year}"y -v"${month}" -v"${day}"d -v"${hour}"H -v"${minute}"M -v"${second}"S -u +%s)
fi
now=$(date +%s)
# Day diff
diff=$(("$then" - "$now"))
diff=$($diff / 86400)
diff=$((diff / 86400))
# All done
if [ "$days" = "1" ]; then

View File

@@ -24,10 +24,10 @@ resetOutput()
# ranging between 0 and 255 inclusive
rainbowColor()
{
let h=$1/43
let f=$1-43*$h
let t=$f*255/43
let q=255-t
((h = $1 / 43))
((f = $1 - 43 * h))
((t = f * 255 / 43))
((q = 255 - t))
if [ $h -eq 0 ]; then
echo "255 $t 0"
@@ -81,11 +81,13 @@ done
resetOutput
for i in $(seq 0 127); do
# shellcheck disable=SC2046 # Intentional word splitting to pass 3 RGB values as separate args
setBackgroundColor $(rainbowColor "$i")
echo -n " "
done
resetOutput
for i in $(seq 255 128); do
# shellcheck disable=SC2046 # Intentional word splitting to pass 3 RGB values as separate args
setBackgroundColor $(rainbowColor "$i")
echo -n " "
done

View File

@@ -126,8 +126,8 @@ parse_options()
# Generate thumbnails recursively using find and filtering by MIME type
generate_thumbnails()
{
local source_dir=$1
local output_dir=$2
local source_dir="$1"
local output_dir="$2"
# Ensure the output directory exists (create if necessary)
if [ ! -d "$output_dir" ]; then
@@ -144,7 +144,7 @@ generate_thumbnails()
fi
# Determine the relative path with respect to the source directory.
rel_path="${file#$source_dir/}"
rel_path="${file#"$source_dir"/}"
dir="$(dirname "$rel_path")"
base="$(basename "$rel_path")"
filename="${base%.*}"

View File

@@ -1,260 +0,0 @@
#!/usr/bin/env bash
# Migration helper script: Dotbot to Chezmoi
# This script helps restructure files from dotbot format to chezmoi format
#
# IMPORTANT: Review changes carefully before running!
# It's recommended to run this in a new git branch
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
log_info() {
echo -e "${BLUE}${NC} $1"
}
log_success() {
echo -e "${GREEN}${NC} $1"
}
log_warning() {
echo -e "${YELLOW}${NC} $1"
}
log_error() {
echo -e "${RED}${NC} $1"
}
# Check if we're in a git repository
if [ ! -d .git ]; then
log_error "Not a git repository. Please run from your dotfiles directory."
exit 1
fi
# Confirm with user
log_warning "This script will restructure your dotfiles for chezmoi."
log_warning "It's STRONGLY recommended to:"
log_warning " 1. Commit all current changes"
log_warning " 2. Create a new branch for migration"
log_warning " 3. Review all changes before merging"
echo ""
read -p "Do you want to continue? (yes/no): " -r
echo
if [[ ! $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
log_info "Migration cancelled."
exit 0
fi
# Create backup branch
log_info "Creating backup branch..."
BACKUP_BRANCH="backup-before-chezmoi-$(date +%Y%m%d-%H%M%S)"
git branch "$BACKUP_BRANCH"
log_success "Created backup branch: $BACKUP_BRANCH"
# Create migration branch
log_info "Creating migration branch..."
MIGRATION_BRANCH="migrate-to-chezmoi"
git checkout -b "$MIGRATION_BRANCH" 2>/dev/null || git checkout "$MIGRATION_BRANCH"
log_success "Switched to migration branch: $MIGRATION_BRANCH"
# Function to move and rename files
move_dotfiles() {
local src=$1
local dest=$2
local prefix=$3
if [ -f "$src" ]; then
mkdir -p "$(dirname "$dest")"
log_info "Moving: $src$dest"
git mv "$src" "$dest" 2>/dev/null || mv "$src" "$dest"
fi
}
# Migrate base files (these become dot_ files)
log_info "Migrating base files..."
if [ -d base ]; then
for file in base/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
# Skip certain files
if [[ "$filename" =~ \.(md|MD)$ ]]; then
continue
fi
move_dotfiles "$file" "dot_${filename}" ""
fi
done
log_success "Base files migrated"
fi
# Migrate config directory
log_info "Migrating config directory..."
if [ -d config ]; then
# Create dot_config if it doesn't exist
mkdir -p dot_config
for item in config/*; do
if [ -e "$item" ]; then
basename_item=$(basename "$item")
# Skip certain directories
if [[ "$basename_item" == "homebrew" ]] || [[ "$basename_item" == "shared.sh" ]]; then
log_info "Keeping $item in place (referenced by scripts)"
continue
fi
log_info "Moving: $item → dot_config/$basename_item"
git mv "$item" "dot_config/$basename_item" 2>/dev/null || mv "$item" "dot_config/$basename_item"
fi
done
log_success "Config files migrated"
fi
# Migrate local/bin with executable prefix
log_info "Migrating local/bin scripts..."
if [ -d local/bin ]; then
mkdir -p executable_dot_local/bin
for script in local/bin/*; do
if [ -f "$script" ]; then
basename_script=$(basename "$script")
log_info "Moving: $script → executable_dot_local/bin/$basename_script"
git mv "$script" "executable_dot_local/bin/$basename_script" 2>/dev/null || \
mv "$script" "executable_dot_local/bin/$basename_script"
fi
done
log_success "Local bin scripts migrated"
fi
# Migrate local/share
log_info "Migrating local/share..."
if [ -d local/share ]; then
mkdir -p dot_local/share
for item in local/share/*; do
if [ -e "$item" ]; then
basename_item=$(basename "$item")
log_info "Moving: $item → dot_local/share/$basename_item"
git mv "$item" "dot_local/share/$basename_item" 2>/dev/null || \
mv "$item" "dot_local/share/$basename_item"
fi
done
log_success "Local share migrated"
fi
# Migrate local/man
log_info "Migrating local/man..."
if [ -d local/man ]; then
mkdir -p dot_local/man
for item in local/man/*; do
if [ -e "$item" ]; then
basename_item=$(basename "$item")
log_info "Moving: $item → dot_local/man/$basename_item"
git mv "$item" "dot_local/man/$basename_item" 2>/dev/null || \
mv "$item" "dot_local/man/$basename_item"
fi
done
log_success "Local man pages migrated"
fi
# Migrate SSH files with private prefix
log_info "Migrating SSH files..."
if [ -d ssh ]; then
mkdir -p private_dot_ssh
for item in ssh/*; do
if [ -f "$item" ]; then
basename_item=$(basename "$item")
log_info "Moving: $item → private_dot_ssh/$basename_item"
git mv "$item" "private_dot_ssh/$basename_item" 2>/dev/null || \
mv "$item" "private_dot_ssh/$basename_item"
fi
done
log_success "SSH files migrated"
fi
# Clean up empty directories
log_info "Cleaning up empty directories..."
find . -type d -empty -delete 2>/dev/null || true
log_success "Empty directories removed"
# Create README for old structure
log_info "Creating migration notes..."
cat > MIGRATION-NOTES.md << 'EOF'
# Migration Notes
This repository has been migrated from dotbot to chezmoi.
## Old Structure (Dotbot)
```
~/.dotfiles/
├── base/ # Files symlinked to ~/.*
├── config/ # Files symlinked to ~/.config/
├── local/ # Scripts and local files
├── ssh/ # SSH configuration
├── install # Dotbot installation script
└── install.conf.yaml # Dotbot configuration
```
## New Structure (Chezmoi)
```
~/.dotfiles/ (or ~/.local/share/chezmoi)
├── dot_* # Files that become ~/.*
├── dot_config/ # Files that become ~/.config/
├── executable_dot_local/ # Executable scripts
├── private_dot_ssh/ # SSH files with 0700 permissions
├── run_once_*.sh.tmpl # One-time setup scripts
├── .chezmoi.yaml.tmpl # Chezmoi configuration
└── .chezmoiignore # Files to ignore
```
## File Naming Conventions
- `dot_bashrc``~/.bashrc`
- `dot_config/fish/``~/.config/fish/`
- `private_dot_ssh/``~/.ssh/` (mode 0700)
- `executable_dot_local/bin/script``~/.local/bin/script` (executable)
- `symlink_dot_vim``~/.vim` (symlink)
## Next Steps
1. Review the migration with: `git diff`
2. Test with chezmoi: `chezmoi init --dry-run --verbose $(pwd)`
3. Apply if everything looks good: `chezmoi init --apply $(pwd)`
4. Read the full migration guide: `MIGRATION-DOTBOT-TO-CHEZMOI.md`
## Backup
A backup branch was created: `$BACKUP_BRANCH`
You can switch back with: `git checkout $BACKUP_BRANCH`
EOF
log_success "Migration notes created: MIGRATION-NOTES.md"
# Show summary
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_success "Migration complete!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
log_info "Summary:"
echo " • Backup branch: $BACKUP_BRANCH"
echo " • Migration branch: $MIGRATION_BRANCH"
echo ""
log_info "Next steps:"
echo " 1. Review changes: git status && git diff"
echo " 2. Test with chezmoi: chezmoi init --dry-run --verbose \$(pwd)"
echo " 3. Read migration guide: cat MIGRATION-DOTBOT-TO-CHEZMOI.md"
echo " 4. Commit changes: git add -A && git commit -m 'Migrate to chezmoi'"
echo ""
log_warning "IMPORTANT: Review all changes before committing!"
log_warning "Test thoroughly before applying to your home directory!"
echo ""

View File

@@ -6,14 +6,13 @@
"doc": "docs"
},
"scripts": {
"lint:markdown": "markdownlint -d .",
"fix:markdown": "markdownlint -df .",
"lint:prettier": "prettier . --check",
"fix:prettier": "prettier . --write",
"lint:biome": "biome check .",
"fix:biome": "biome check --write .",
"format": "biome format --write .",
"test": "bash test-all.sh",
"lint:ec": "ec -f gcc",
"lint": "yarn lint:markdown && yarn lint:prettier && yarn lint:ec",
"fix": "yarn fix:markdown && yarn fix:prettier"
"lint": "yarn lint:biome && yarn lint:ec",
"fix": "yarn fix:biome"
},
"repository": {
"type": "git",
@@ -30,13 +29,11 @@
},
"homepage": "https://github.com/ivuorinen/dotfiles#readme",
"devDependencies": {
"@ivuorinen/base-configs": "^2.0.0",
"@biomejs/biome": "^2.3.1",
"@types/node": "^24.0.1",
"bats": "^1.12.0",
"editorconfig-checker": "^6.1.0",
"markdownlint": "^0.39.0",
"prettier": "^3.6.2",
"typescript": "^5.8.3"
},
"packageManager": "yarn@1.22.22"
"packageManager": "yarn@4.12.0"
}

View File

@@ -1,32 +0,0 @@
#!/usr/bin/env bash
# run_once_after script to create required directories
# This runs once after applying dotfiles
set -e
echo "→ Creating required directories..."
# Create directories with proper permissions
mkdir -p "$HOME/.cache"
mkdir -p "$HOME/.cache/git"
mkdir -p "$HOME/.config"
mkdir -p "$HOME/.local"
mkdir -p "$HOME/.local/bin"
mkdir -p "$HOME/.local/run"
mkdir -p "$HOME/.local/share"
mkdir -p "$HOME/.local/state"
mkdir -p "$HOME/.local/state/tmux"
mkdir -p "$HOME/.local/state/zsh"
mkdir -p "$HOME/Code"
# Create directories with restricted permissions
mkdir -p "$HOME/.local/share/gnupg"
chmod 0700 "$HOME/.local/share/gnupg"
mkdir -p "$HOME/.ssh"
chmod 0700 "$HOME/.ssh"
mkdir -p "$HOME/.ssh/local.d"
chmod 0700 "$HOME/.ssh/local.d"
echo "✓ Directories created!"

View File

@@ -1,52 +0,0 @@
#!/usr/bin/env bash
# run_once_after script to install packages
# This runs once after applying dotfiles
set -e
DOTFILES="{{ .chezmoi.sourceDir }}"
export DOTFILES
# Source shared configuration
if [ -f "$DOTFILES/config/shared.sh" ]; then
source "$DOTFILES/config/shared.sh"
fi
# Source message helper if available
if [ -f "$DOTFILES/local/bin/msgr" ]; then
source "$DOTFILES/local/bin/msgr"
fi
echo "→ Installing packages..."
{{- if .is_macos }}
# Install Homebrew packages
if [ -f "$DOTFILES/config/homebrew/Brewfile" ]; then
echo "→ Installing Homebrew packages..."
brew bundle install --file="$DOTFILES/config/homebrew/Brewfile" --no-lock || true
fi
# Setup macOS defaults
if [ -f "$DOTFILES/scripts/install-macos-defaults.sh" ]; then
echo "→ Setting up macOS defaults..."
bash "$DOTFILES/scripts/install-macos-defaults.sh" || true
fi
{{- end }}
{{- if .is_linux }}
# Install apt packages if on Debian/Ubuntu
if command -v apt &> /dev/null && [ -f "$DOTFILES/tools/apt.txt" ]; then
echo "→ Installing apt packages..."
sudo apt install -y $(grep -vE '^\s*#' "$DOTFILES/tools/apt.txt" | sed -e 's/#.*//' | tr '\n' ' ') || true
fi
{{- end }}
# Install pipx packages
if command -v pipx &> /dev/null && [ -f "$DOTFILES/tools/requirements-pipx.txt" ]; then
echo "→ Installing pipx packages..."
while IFS= read -r package; do
[ -z "$package" ] || pipx install "$package" || true
done < "$DOTFILES/tools/requirements-pipx.txt"
fi
echo "✓ Packages installed!"

View File

@@ -1,76 +0,0 @@
#!/usr/bin/env bash
# run_once_after script to setup programming languages and tools
# This runs once after applying dotfiles
set -e
DOTFILES="{{ .chezmoi.sourceDir }}"
export DOTFILES
echo "→ Setting up programming languages and tools..."
# Install fonts
if [ -f "$DOTFILES/scripts/install-fonts.sh" ]; then
echo "→ Installing fonts..."
bash "$DOTFILES/scripts/install-fonts.sh" || true
fi
# Install Cargo packages
if command -v cargo &> /dev/null && [ -f "$DOTFILES/scripts/install-cargo-packages.sh" ]; then
echo "→ Installing Cargo packages..."
bash "$DOTFILES/scripts/install-cargo-packages.sh" || true
fi
# Install Go packages
if command -v go &> /dev/null && [ -f "$DOTFILES/scripts/install-go-packages.sh" ]; then
echo "→ Installing Go packages..."
bash "$DOTFILES/scripts/install-go-packages.sh" || true
fi
# Install Composer
if [ -f "$DOTFILES/scripts/install-composer.sh" ]; then
echo "→ Installing Composer..."
bash "$DOTFILES/scripts/install-composer.sh" || true
fi
# Install NVM
if [ ! -d "$HOME/.nvm" ] && command -v curl &> /dev/null; then
echo "→ Installing NVM..."
NVM_VERSION=$(curl -s https://api.github.com/repos/nvm-sh/nvm/releases/latest | grep -o '"tag_name": "[^"]*' | cut -d'"' -f4)
PROFILE=/dev/null bash -c "curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh | bash" || true
fi
# Install latest Node LTS
if [ -s "$HOME/.nvm/nvm.sh" ]; then
echo "→ Installing latest Node LTS..."
source "$HOME/.nvm/nvm.sh"
nvm install --lts --latest-npm --default || true
fi
# Install NPM packages
if command -v npm &> /dev/null && [ -f "$DOTFILES/scripts/install-npm-packages.sh" ]; then
echo "→ Installing NPM packages..."
bash "$DOTFILES/scripts/install-npm-packages.sh" || true
fi
# Install GitHub CLI extensions
if command -v gh &> /dev/null && [ -f "$DOTFILES/scripts/install-gh-extensions.sh" ]; then
echo "→ Installing GitHub CLI extensions..."
bash "$DOTFILES/scripts/install-gh-extensions.sh" || true
fi
# Install z
if [ -f "$DOTFILES/scripts/install-z.sh" ]; then
echo "→ Installing z..."
bash "$DOTFILES/scripts/install-z.sh" || true
fi
# Install cheat databases
for database in "$DOTFILES"/scripts/install-cheat-*; do
if [ -f "$database" ]; then
echo "→ Installing $(basename "$database")..."
bash "$database" || true
fi
done
echo "✓ Programming languages and tools setup complete!"

View File

@@ -1,31 +0,0 @@
#!/usr/bin/env bash
# run_once_before script to install prerequisites
# This runs once before applying dotfiles
set -e
echo "→ Installing prerequisites..."
{{- if .is_macos }}
# Install Homebrew if not present
if ! command -v brew &> /dev/null; then
echo "→ Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
# Install Xcode CLI tools if needed
if ! xcode-select -p &> /dev/null; then
echo "→ Installing Xcode Command Line Tools..."
xcode-select --install || true
fi
{{- end }}
{{- if .is_linux }}
# Update package manager
if command -v apt &> /dev/null; then
echo "→ Updating apt..."
sudo apt update
fi
{{- end }}
echo "✓ Prerequisites installed!"

6392
yarn.lock

File diff suppressed because it is too large Load Diff