Compare commits
9 Commits
master
...
rewrite/UI
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32ab9e03b2 | ||
|
|
edbbf47e9f | ||
|
|
897dc424dc | ||
|
|
9c3cdbc90f | ||
|
|
f53663298e | ||
|
|
33f1112bf8 | ||
|
|
9bec4660f6 | ||
|
|
9c38a8414e | ||
|
|
b512d41dc8 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
.idea
|
.idea
|
||||||
|
WokwiKey.txt
|
||||||
|
|||||||
2615
docs/superpowers/plans/2026-04-13-installer-foundation.md
Normal file
2615
docs/superpowers/plans/2026-04-13-installer-foundation.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,228 @@
|
|||||||
|
# Installer Architecture Redesign
|
||||||
|
|
||||||
|
**Status:** Design approved, pending implementation plan
|
||||||
|
**Date:** 2026-04-13
|
||||||
|
**Scope:** Installer architecture only. Toolset overhaul, CLI browser, and TTY-font story are queued as follow-up specs.
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The current Archduino installer is a Bash entry point (`install.sh`) that sources 13 files under `lib/`. It has grown beyond what Bash handles comfortably:
|
||||||
|
|
||||||
|
- **Monolithic / ordering-fragile.** `install.sh` sources lib files in a fixed order at top level; hard to run a single step and hard to re-run safely.
|
||||||
|
- **Not idempotent / no resume.** Re-running either duplicates work or silently skips things.
|
||||||
|
- **Mixed concerns per file.** Detection, templating, package install, and theme application are intertwined in every lib.
|
||||||
|
- **Thin UX.** Only choices are theme + verbose; no dry-run, no module selection, no preview.
|
||||||
|
- **Platform coupling.** Arch vs Ubuntu-WSL branches are scattered throughout.
|
||||||
|
|
||||||
|
The goal is a principled rebuild across all five axes.
|
||||||
|
|
||||||
|
## Decision summary
|
||||||
|
|
||||||
|
| Area | Choice |
|
||||||
|
|---|---|
|
||||||
|
| Language / runtime | Go, single static binary |
|
||||||
|
| UI | Bubble Tea + Huh (wizard for input, dashboard for execution) |
|
||||||
|
| Pre-install shim | Minimal Bash script: ensures `sudo`, `git`, `curl`, `ca-certificates`, fetches binary |
|
||||||
|
| Module contract | Four-phase: `Detect → Plan → Apply → Verify` |
|
||||||
|
| Configuration | Embedded defaults + optional `~/.config/archduino/overlay.yaml` |
|
||||||
|
| Privilege model | User-mode binary; `sudo` per privileged command; upfront `sudo -v` + keepalive goroutine |
|
||||||
|
| State / logging | `Detect()` is authoritative; run log is advisory UX only |
|
||||||
|
| Failure policy | DAG execution; failed node fails its descendants; siblings proceed; `--halt-on-error` flag available |
|
||||||
|
| Subcommands | One binary: `install`, `theme`, `new`, `doctor` |
|
||||||
|
| Platform scope (v1) | Arch-only native + WSL2; `PackageManager` interface ready for Debian/Fedora later |
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Module contract
|
||||||
|
|
||||||
|
Every installable unit implements:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Module interface {
|
||||||
|
Meta() ModuleMeta // id, human name, description, deps []string
|
||||||
|
Detect(ctx) (State, error) // read current system
|
||||||
|
Plan(ctx, State) (Plan, error) // diff vs desired; []Action with descriptions
|
||||||
|
Apply(ctx, Plan, *Reporter) error // execute; stream progress to Reporter
|
||||||
|
Verify(ctx) error // confirm desired state reached
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- `State` is module-defined.
|
||||||
|
- `Plan` is a flat list of `Action{Description, Kind, Exec}` so the engine can render plans without knowing modules.
|
||||||
|
- `Reporter` decouples modules from the TUI.
|
||||||
|
- **`Detect()` is authoritative.** No cached state overrides what the system reports.
|
||||||
|
|
||||||
|
Initial module set (1:1 with today's `lib/*.sh`):
|
||||||
|
`packages`, `fonts`, `zsh`, `starship`, `zellij`, `neovim`, `yazi`, `arduino-cli`, `renode`, `git` (lazygit), `scaffold`, `shell-config`, `themes`.
|
||||||
|
|
||||||
|
### Execution engine
|
||||||
|
|
||||||
|
- **DAG-scheduled.** Modules declare `deps []string`. Engine topologically sorts and runs independent branches concurrently, default parallelism 4.
|
||||||
|
- **Failure policy.** Failed node marks its descendants `skipped-due-to-dep`; siblings proceed. End-of-run summary: `X succeeded, Y failed, Z skipped`.
|
||||||
|
- **Dry-run** (`--dry-run`, or wizard "Review plan" step): runs Detect + Plan for every selected module, renders the combined plan, exits.
|
||||||
|
- **Halt mode** (`--halt-on-error`): opts into fail-fast for scripted use.
|
||||||
|
- **Resume hint.** If a prior run log exists, TUI offers "last run: `starship` failed — resume? / start over? / pick modules?" Hint only; Detect decides what actually runs.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
- **Embedded defaults** via `//go:embed`: package lists, theme files, Zellij layouts, config templates.
|
||||||
|
- **Optional overlay** at `~/.config/archduino/overlay.yaml`:
|
||||||
|
```yaml
|
||||||
|
version: 1
|
||||||
|
extra_packages: [htop, ncdu]
|
||||||
|
disabled_modules: [renode]
|
||||||
|
theme_overrides:
|
||||||
|
starship: ~/my-starship.toml
|
||||||
|
```
|
||||||
|
- Overlay is merged at load time. Schema is versioned; a migration path exists when it grows.
|
||||||
|
|
||||||
|
### Privilege model
|
||||||
|
|
||||||
|
- Binary runs as the invoking user.
|
||||||
|
- On `install` start, one `sudo -v` call; a keepalive goroutine refreshes the timestamp every 50 seconds while the installer is live.
|
||||||
|
- Privileged operations shell out to `sudo pacman …`, `sudo usermod …`. If sudo needs to re-prompt (timestamp expired), the TUI is suspended via `tea.ExecProcess`.
|
||||||
|
- Config files, git clones, and anything under `$HOME` run as the user — no root-owned files in home.
|
||||||
|
|
||||||
|
### Platform abstraction
|
||||||
|
|
||||||
|
```go
|
||||||
|
type PackageManager interface {
|
||||||
|
Install(pkgs []string) error
|
||||||
|
IsInstalled(pkg string) (bool, error)
|
||||||
|
Update() error
|
||||||
|
Name() string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- V1 ships `Pacman` only. Debian/Ubuntu/Fedora impls are stubbed; wiring them is a later spec.
|
||||||
|
- `Platform{Distro, IsWSL, Arch}` detection is centralized. WSL path sets `/etc/wsl.conf` hints and adds the user to `dialout`/`uucp`.
|
||||||
|
|
||||||
|
### State and logs
|
||||||
|
|
||||||
|
- `~/.local/state/archduino/runs/<timestamp>.json` — per-run structured log: `{module, phase, status, duration, error}`.
|
||||||
|
- `~/.local/state/archduino/last.json` — most recent run; read by TUI for the resume hint.
|
||||||
|
- Log rotation: keep the last 10 runs.
|
||||||
|
- Safe to delete at any time; never read for correctness decisions.
|
||||||
|
|
||||||
|
## User-facing surface
|
||||||
|
|
||||||
|
### Pre-install shim (`scripts/bootstrap.sh`)
|
||||||
|
|
||||||
|
~30 lines of Bash, served from a stable URL. Invocation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://archduino.dev/install.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
Responsibilities in order:
|
||||||
|
|
||||||
|
1. Refuse to run as root.
|
||||||
|
2. Detect distro; abort with a clear message if not Arch (v1 scope).
|
||||||
|
3. Ensure `sudo`, `git`, `curl`, `ca-certificates` are installed (`pacman -S --needed`).
|
||||||
|
4. Detect architecture, fetch the matching release binary from GitHub Releases, verify its SHA256 against the published checksum file, install to `~/.local/bin/archduino`, `chmod +x`.
|
||||||
|
5. `exec archduino install`.
|
||||||
|
|
||||||
|
Everything further (base-devel, multilib, user groups, toolset) is handled by modules inside the binary.
|
||||||
|
|
||||||
|
### Subcommands
|
||||||
|
|
||||||
|
| Command | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `archduino install` | Default; wizard + dashboard flow |
|
||||||
|
| `archduino theme [name]` | Switch colorscheme across all tools; no arg = TUI picker |
|
||||||
|
| `archduino new <name> <board>` | Scaffold a project (current `arduino-new` behavior) |
|
||||||
|
| `archduino doctor` | Run Detect across all modules; report drift in a read-only dashboard |
|
||||||
|
| `archduino --version` / `completion <shell>` | Standard |
|
||||||
|
|
||||||
|
Global flags: `--dry-run`, `--halt-on-error`, `--verbose`, `--no-tui`, `--only <mods>`, `--skip <mods>`.
|
||||||
|
|
||||||
|
Shell aliases `theme` and `arduino-new` are preserved via thin wrappers dropped in `~/.local/bin` by the `shell-config` module.
|
||||||
|
|
||||||
|
### TUI flow (`install`)
|
||||||
|
|
||||||
|
**Wizard phase (Huh forms):**
|
||||||
|
|
||||||
|
1. Welcome — detected platform, WSL status, binary version.
|
||||||
|
2. Theme picker — 5 options, palette preview.
|
||||||
|
3. Module selector — checkbox list; pre-ticked from overlay or "all" by default; disabled modules grayed with reason.
|
||||||
|
4. Advanced (collapsible) — parallelism, halt-on-error toggle, overlay path override.
|
||||||
|
5. Review plan — rendered `Plan()` grouped by module, expandable. Back-navigable.
|
||||||
|
6. Confirm — `[y/N]` gate into Apply.
|
||||||
|
|
||||||
|
**Apply phase (Bubble Tea dashboard):**
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─ archduino install ──────────────────────────────────┐
|
||||||
|
│ ✓ packages 12/12 2.4s │
|
||||||
|
│ ✓ fonts 1/1 0.8s │
|
||||||
|
│ ⠋ neovim 3/7 running: :MasonInstall… │
|
||||||
|
│ ⠋ arduino-cli 2/4 running: core install… │
|
||||||
|
│ · zellij pending (waits: packages) │
|
||||||
|
│ ✗ starship failed — config template parse │
|
||||||
|
│ ⊘ shell-config skipped (dep: starship) │
|
||||||
|
├──────────────────────────────────────────────────────┤
|
||||||
|
│ [tab] focus module [enter] expand log [q] abort │
|
||||||
|
└──────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
- Concurrent modules visible live.
|
||||||
|
- `enter` on a row expands a scrollable log tail.
|
||||||
|
- On completion: summary view; footer offers `[r]etry failed / [v]iew full log / [q]uit`.
|
||||||
|
|
||||||
|
## Project layout
|
||||||
|
|
||||||
|
```
|
||||||
|
archduino/
|
||||||
|
├── cmd/archduino/ # main.go, cobra wiring
|
||||||
|
├── internal/
|
||||||
|
│ ├── engine/ # DAG scheduler, Reporter, dry-run, resume
|
||||||
|
│ ├── module/ # Module interface, Plan/Action types, registry
|
||||||
|
│ ├── modules/ # one package per module
|
||||||
|
│ │ ├── packages/
|
||||||
|
│ │ ├── zsh/
|
||||||
|
│ │ └── ...
|
||||||
|
│ ├── platform/ # detection; PackageManager interface + pacman impl
|
||||||
|
│ ├── privilege/ # sudo -v + keepalive
|
||||||
|
│ ├── config/ # embedded defaults + overlay merge
|
||||||
|
│ ├── state/ # run log, last-run tracking
|
||||||
|
│ ├── theme/ # theme model + switcher
|
||||||
|
│ └── tui/
|
||||||
|
│ ├── wizard/ # Huh forms
|
||||||
|
│ └── dashboard/ # Bubble Tea Apply view
|
||||||
|
├── assets/ # embedded configs, themes, zellij layout, templates
|
||||||
|
│ ├── themes/
|
||||||
|
│ ├── templates/
|
||||||
|
│ └── layouts/
|
||||||
|
├── scripts/bootstrap.sh
|
||||||
|
├── .github/workflows/
|
||||||
|
│ ├── ci.yml
|
||||||
|
│ └── release.yml # goreleaser
|
||||||
|
└── docs/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
- **Unit** — every module's `Detect` and `Plan` against an injected `System` fake; table-driven cases for clean / already-installed / partial / drifted.
|
||||||
|
- **Engine** — DAG scheduling, failure propagation, dry-run, resume; pure Go, fully covered.
|
||||||
|
- **Integration** — Dockerfile on `archlinux:base` runs `archduino install --no-tui --yes` end-to-end in CI; asserts key files/packages/services. One matrix entry for native Arch. WSL smoke test remains manual for v1.
|
||||||
|
- **TUI** — `teatest` for wizard navigation and dashboard state transitions. No screenshot tests.
|
||||||
|
|
||||||
|
## Distribution
|
||||||
|
|
||||||
|
- **GitHub Releases** via `goreleaser`: `linux/amd64`, `linux/arm64` static binaries; `SHA256SUMS` file.
|
||||||
|
- No AUR package for v1; the shim is the distribution channel. AUR can follow later.
|
||||||
|
- Semver; breaking changes bump major.
|
||||||
|
|
||||||
|
## Migration
|
||||||
|
|
||||||
|
- Existing `install.sh` + `lib/*.sh` stay on `master` at a tagged `v0-bash-final` so users can still run the old installer if they want.
|
||||||
|
- `feat/renode-dap` merges first; a new `feat/go-rewrite` branch hosts the rewrite.
|
||||||
|
- First Go release (`v1.0.0`) lands when feature parity with the current Bash installer is verified on a clean Arch VM.
|
||||||
|
|
||||||
|
## Out of scope (queued for follow-up specs)
|
||||||
|
|
||||||
|
- Toolset redesign (re-evaluating which CLI tools are curated).
|
||||||
|
- CLI browser integration.
|
||||||
|
- Nerd Font rendering on bare TTY (constrained by the Linux console's 512-glyph PSF limit; needs a separate design covering `fbterm`/`kmscon` or the "SSH-in-from-a-real-terminal" fallback).
|
||||||
|
- Non-Arch platform support (Debian/Ubuntu/Fedora).
|
||||||
|
- AUR packaging.
|
||||||
@@ -82,6 +82,7 @@ source "$SCRIPT_DIR/lib/zellij.sh"
|
|||||||
source "$SCRIPT_DIR/lib/neovim.sh"
|
source "$SCRIPT_DIR/lib/neovim.sh"
|
||||||
source "$SCRIPT_DIR/lib/yazi.sh"
|
source "$SCRIPT_DIR/lib/yazi.sh"
|
||||||
source "$SCRIPT_DIR/lib/arduino.sh"
|
source "$SCRIPT_DIR/lib/arduino.sh"
|
||||||
|
source "$SCRIPT_DIR/lib/renode.sh"
|
||||||
source "$SCRIPT_DIR/lib/git.sh"
|
source "$SCRIPT_DIR/lib/git.sh"
|
||||||
source "$SCRIPT_DIR/lib/scaffold.sh"
|
source "$SCRIPT_DIR/lib/scaffold.sh"
|
||||||
source "$SCRIPT_DIR/lib/shell-config.sh"
|
source "$SCRIPT_DIR/lib/shell-config.sh"
|
||||||
@@ -104,6 +105,9 @@ echo " arduino-new my-project uno # scaffold a project"
|
|||||||
echo " adev # launch Arduino workspace"
|
echo " adev # launch Arduino workspace"
|
||||||
echo " <leader>av # compile in Neovim"
|
echo " <leader>av # compile in Neovim"
|
||||||
echo " <leader>au # upload in Neovim"
|
echo " <leader>au # upload in Neovim"
|
||||||
|
echo " wokwi-cli . # simulate with Wokwi (visual)"
|
||||||
|
echo " arduino-sim build/fw.elf # simulate with Renode (GDB)"
|
||||||
|
echo " <leader>ds # attach debugger to Renode"
|
||||||
echo " theme # switch colorscheme"
|
echo " theme # switch colorscheme"
|
||||||
echo ""
|
echo ""
|
||||||
warn "A reboot is recommended to apply all changes (shell, groups, PATH)."
|
warn "A reboot is recommended to apply all changes (shell, groups, PATH)."
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Step 7: Arduino CLI + board cores
|
# Step 7: Arduino CLI + board cores
|
||||||
|
|
||||||
step "9/11 — Installing Arduino CLI + board cores"
|
step "9/12 — Installing Arduino CLI + board cores"
|
||||||
|
|
||||||
if $IS_ARCH; then
|
if $IS_ARCH; then
|
||||||
$PKG_INSTALL arduino-cli
|
$PKG_INSTALL arduino-cli
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ NC='\033[0m'
|
|||||||
VERBOSE=true
|
VERBOSE=true
|
||||||
LOG_FILE="/tmp/archduino-install.log"
|
LOG_FILE="/tmp/archduino-install.log"
|
||||||
CURRENT_STEP=0
|
CURRENT_STEP=0
|
||||||
TOTAL_STEPS=12
|
TOTAL_STEPS=13
|
||||||
|
|
||||||
info() { echo -e "${GREEN}[✓]${NC} $1"; }
|
info() { echo -e "${GREEN}[✓]${NC} $1"; }
|
||||||
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
||||||
@@ -39,7 +39,7 @@ draw_progress() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
begin_quiet_mode() {
|
begin_quiet_mode() {
|
||||||
$IS_WSL && TOTAL_STEPS=13
|
$IS_WSL && TOTAL_STEPS=14
|
||||||
: >"$LOG_FILE"
|
: >"$LOG_FILE"
|
||||||
|
|
||||||
# Save real terminal to fd 3/4, redirect everything else to log
|
# Save real terminal to fd 3/4, redirect everything else to log
|
||||||
@@ -82,9 +82,12 @@ BACKUP_DIR="$HOME/.config/archduino/backups/$(date +%Y%m%d_%H%M%S)"
|
|||||||
backup_config() {
|
backup_config() {
|
||||||
local src="$1"
|
local src="$1"
|
||||||
[[ ! -e "$src" ]] && return 0
|
[[ ! -e "$src" ]] && return 0
|
||||||
mkdir -p "$BACKUP_DIR"
|
# Use parent path to avoid collisions when different sources share a basename
|
||||||
cp -a "$src" "$BACKUP_DIR/"
|
# e.g. ~/.config/nvim and ~/.local/share/nvim both have basename "nvim"
|
||||||
info "Backed up $(basename "$src") → $BACKUP_DIR/"
|
local dest="$BACKUP_DIR${src#"$HOME"}"
|
||||||
|
mkdir -p "$(dirname "$dest")"
|
||||||
|
cp -a "$src" "$dest"
|
||||||
|
info "Backed up ${src/#"$HOME"/\~} → ${dest/#"$HOME"/\~}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── TLS workaround ───────────────────────────────────────────────
|
# ── TLS workaround ───────────────────────────────────────────────
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Step 2: Nerd Font installation
|
# Step 2: Nerd Font installation
|
||||||
|
|
||||||
step "2/11 — Installing Nerd Font"
|
step "2/12 — Installing Nerd Font"
|
||||||
|
|
||||||
FONT_DIR="$HOME/.local/share/fonts/NerdFonts"
|
FONT_DIR="$HOME/.local/share/fonts/NerdFonts"
|
||||||
FONT_NAME="JetBrainsMono"
|
FONT_NAME="JetBrainsMono"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Step 8: Git + Lazygit
|
# Step 8: Git + Lazygit
|
||||||
|
|
||||||
step "10/11 — Setting up Git + Lazygit"
|
step "11/12 — Setting up Git + Lazygit"
|
||||||
|
|
||||||
if $IS_ARCH; then
|
if $IS_ARCH; then
|
||||||
$PKG_INSTALL lazygit
|
$PKG_INSTALL lazygit
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Steps 5+6: Neovim + NvChad
|
# Steps 5+6: Neovim + NvChad
|
||||||
|
|
||||||
step "6/11 — Installing Neovim (latest)"
|
step "6/12 — Installing Neovim (latest)"
|
||||||
|
|
||||||
NVIM_NEEDED=true
|
NVIM_NEEDED=true
|
||||||
if command -v nvim &>/dev/null; then
|
if command -v nvim &>/dev/null; then
|
||||||
@@ -21,7 +21,7 @@ if $NVIM_NEEDED; then
|
|||||||
info "Neovim installed: $(nvim --version | head -1)"
|
info "Neovim installed: $(nvim --version | head -1)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
step "7/11 — Setting up NvChad"
|
step "7/12 — Setting up NvChad"
|
||||||
|
|
||||||
NVIM_CFG="$HOME/.config/nvim"
|
NVIM_CFG="$HOME/.config/nvim"
|
||||||
NVCHAD_FRESH=false
|
NVCHAD_FRESH=false
|
||||||
@@ -29,7 +29,7 @@ MIGRATED_PLUGINS_DIR="/tmp/archduino-migrated-plugins"
|
|||||||
rm -rf "$MIGRATED_PLUGINS_DIR"
|
rm -rf "$MIGRATED_PLUGINS_DIR"
|
||||||
|
|
||||||
# Files managed by Archduino or LazyVim-specific — skip during migration
|
# Files managed by Archduino or LazyVim-specific — skip during migration
|
||||||
SKIP_PLUGINS="gruvbox.lua|theme.lua|lsp.lua|arduino.lua|lspconfig.lua"
|
SKIP_PLUGINS="gruvbox.lua|theme.lua|lsp.lua|arduino.lua|lspconfig.lua|dap.lua"
|
||||||
|
|
||||||
# ── Detect existing config ──────────────────────────────────────
|
# ── Detect existing config ──────────────────────────────────────
|
||||||
if [[ -d "$NVIM_CFG/lua" ]]; then
|
if [[ -d "$NVIM_CFG/lua" ]]; then
|
||||||
@@ -94,6 +94,10 @@ if $NVCHAD_FRESH; then
|
|||||||
info "NvChad starter cloned"
|
info "NvChad starter cloned"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ── Strip starter's nvim-lspconfig block (we use native vim.lsp) ─
|
||||||
|
sed -i '/neovim\/nvim-lspconfig/,/},/d' "$NVIM_CFG/lua/plugins/init.lua"
|
||||||
|
rm -f "$NVIM_CFG/lua/configs/lspconfig.lua"
|
||||||
|
|
||||||
# ── Restore migrated plugins ─────────────────────────────────────
|
# ── Restore migrated plugins ─────────────────────────────────────
|
||||||
if [[ -d "$MIGRATED_PLUGINS_DIR" ]] && ls "$MIGRATED_PLUGINS_DIR"/*.lua &>/dev/null; then
|
if [[ -d "$MIGRATED_PLUGINS_DIR" ]] && ls "$MIGRATED_PLUGINS_DIR"/*.lua &>/dev/null; then
|
||||||
mkdir -p "$NVIM_CFG/lua/plugins"
|
mkdir -p "$NVIM_CFG/lua/plugins"
|
||||||
@@ -165,8 +169,67 @@ vim.lsp.enable("clangd")
|
|||||||
return {}
|
return {}
|
||||||
LUA
|
LUA
|
||||||
|
|
||||||
# Clean up legacy configs/lspconfig.lua if present
|
# ── DAP (debug adapter) — for Renode GDB remote debugging ──────
|
||||||
rm -f "$NVIM_CFG/lua/configs/lspconfig.lua"
|
cat >"$NVIM_CFG/lua/plugins/dap.lua" <<'LUA'
|
||||||
|
return {
|
||||||
|
{
|
||||||
|
"mfussenegger/nvim-dap",
|
||||||
|
keys = { "<leader>d" },
|
||||||
|
config = function()
|
||||||
|
local dap = require("dap")
|
||||||
|
|
||||||
|
-- GDB remote adapter (connects to Renode's GDB server)
|
||||||
|
dap.adapters.gdb_remote = {
|
||||||
|
type = "executable",
|
||||||
|
command = vim.fn.executable("arm-none-eabi-gdb") == 1
|
||||||
|
and "arm-none-eabi-gdb"
|
||||||
|
or "gdb-multiarch",
|
||||||
|
args = { "-i", "dap" },
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Default debug configurations for Arduino/embedded
|
||||||
|
dap.configurations.c = {
|
||||||
|
{
|
||||||
|
name = "Attach to Renode (GDB :3333)",
|
||||||
|
type = "gdb_remote",
|
||||||
|
request = "attach",
|
||||||
|
target = "localhost:3333",
|
||||||
|
cwd = "${workspaceFolder}",
|
||||||
|
program = function()
|
||||||
|
return vim.fn.input("ELF path: ", vim.fn.getcwd() .. "/build/", "file")
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
dap.configurations.cpp = dap.configurations.c
|
||||||
|
dap.configurations.arduino = dap.configurations.c
|
||||||
|
|
||||||
|
-- Breakpoint signs
|
||||||
|
vim.fn.sign_define("DapBreakpoint", { text = "●", texthl = "DiagnosticError" })
|
||||||
|
vim.fn.sign_define("DapStopped", { text = "▶", texthl = "DiagnosticOk", linehl = "DiffAdd" })
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rcarriga/nvim-dap-ui",
|
||||||
|
dependencies = { "mfussenegger/nvim-dap", "nvim-neotest/nvim-nio" },
|
||||||
|
keys = { "<leader>du" },
|
||||||
|
config = function()
|
||||||
|
local dapui = require("dapui")
|
||||||
|
dapui.setup()
|
||||||
|
|
||||||
|
-- Auto open/close UI on debug sessions
|
||||||
|
local dap = require("dap")
|
||||||
|
dap.listeners.after.event_initialized["dapui_config"] = function() dapui.open() end
|
||||||
|
dap.listeners.before.event_terminated["dapui_config"] = function() dapui.close() end
|
||||||
|
dap.listeners.before.event_exited["dapui_config"] = function() dapui.close() end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nvim-neotest/nvim-nio",
|
||||||
|
lazy = true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
LUA
|
||||||
|
|
||||||
|
|
||||||
# ── Keymaps ─────────────────────────────────────────────────────
|
# ── Keymaps ─────────────────────────────────────────────────────
|
||||||
cat >"$NVIM_CFG/lua/mappings.lua" <<'LUA'
|
cat >"$NVIM_CFG/lua/mappings.lua" <<'LUA'
|
||||||
@@ -180,6 +243,16 @@ map("n", "<leader>av", "<cmd>ArduinoVerify<cr>", { desc = "Arduino Verify (compi
|
|||||||
map("n", "<leader>au", "<cmd>ArduinoUpload<cr>", { desc = "Arduino Upload" })
|
map("n", "<leader>au", "<cmd>ArduinoUpload<cr>", { desc = "Arduino Upload" })
|
||||||
map("n", "<leader>as", "<cmd>ArduinoSerial<cr>", { desc = "Arduino Serial Monitor" })
|
map("n", "<leader>as", "<cmd>ArduinoSerial<cr>", { desc = "Arduino Serial Monitor" })
|
||||||
map("n", "<leader>ai", "<cmd>ArduinoInfo<cr>", { desc = "Arduino Board Info" })
|
map("n", "<leader>ai", "<cmd>ArduinoInfo<cr>", { desc = "Arduino Board Info" })
|
||||||
|
map("n", "<leader>aw", "<cmd>!wokwi-cli .<cr>", { desc = "Arduino Wokwi Simulate" })
|
||||||
|
|
||||||
|
-- Debug (DAP)
|
||||||
|
map("n", "<leader>ds", function() require("dap").continue() end, { desc = "Debug Start/Continue" })
|
||||||
|
map("n", "<leader>db", function() require("dap").toggle_breakpoint() end, { desc = "Debug Toggle Breakpoint" })
|
||||||
|
map("n", "<leader>dn", function() require("dap").step_over() end, { desc = "Debug Step Over" })
|
||||||
|
map("n", "<leader>di", function() require("dap").step_into() end, { desc = "Debug Step Into" })
|
||||||
|
map("n", "<leader>do", function() require("dap").step_out() end, { desc = "Debug Step Out" })
|
||||||
|
map("n", "<leader>dx", function() require("dap").terminate() end, { desc = "Debug Terminate" })
|
||||||
|
map("n", "<leader>du", function() require("dapui").toggle() end, { desc = "Debug UI Toggle" })
|
||||||
LUA
|
LUA
|
||||||
|
|
||||||
info "NvChad configured ($THEME_DISPLAY_NAME + Arduino + LSP)"
|
info "NvChad configured ($THEME_DISPLAY_NAME + Arduino + LSP + DAP)"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Step 1: Base packages
|
# Step 1: Base packages
|
||||||
|
|
||||||
step "1/11 — Installing base packages"
|
step "1/12 — Installing base packages"
|
||||||
|
|
||||||
if $IS_ARCH; then
|
if $IS_ARCH; then
|
||||||
sudo pacman -Syu --noconfirm
|
sudo pacman -Syu --noconfirm
|
||||||
|
|||||||
116
lib/renode.sh
Normal file
116
lib/renode.sh
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Step 10: Renode emulator for Arduino simulation with USB HID support
|
||||||
|
|
||||||
|
step "10/12 — Installing Renode emulator"
|
||||||
|
|
||||||
|
# gdb-multiarch is needed for nvim-dap to connect to Renode's GDB server
|
||||||
|
if $IS_ARCH; then
|
||||||
|
if ! command -v renode &>/dev/null; then
|
||||||
|
info "Installing Renode from AUR..."
|
||||||
|
yay -S --needed --noconfirm renode-bin
|
||||||
|
else
|
||||||
|
info "Renode already installed"
|
||||||
|
fi
|
||||||
|
$PKG_INSTALL arm-none-eabi-gdb
|
||||||
|
else
|
||||||
|
if ! command -v renode &>/dev/null; then
|
||||||
|
info "Installing Renode..."
|
||||||
|
RENODE_VERSION=$(curl -ks "https://api.github.com/repos/renode/renode/releases/latest" | jq -r '.tag_name' | sed 's/^v//')
|
||||||
|
curl -ksSLo /tmp/renode.deb "https://github.com/renode/renode/releases/download/v${RENODE_VERSION}/renode_${RENODE_VERSION}_amd64.deb"
|
||||||
|
sudo apt install -y /tmp/renode.deb
|
||||||
|
rm -f /tmp/renode.deb
|
||||||
|
else
|
||||||
|
info "Renode already installed"
|
||||||
|
fi
|
||||||
|
$PKG_INSTALL gdb-multiarch
|
||||||
|
fi
|
||||||
|
info "Renode installed: $(renode --version 2>/dev/null | head -1 || echo 'OK')"
|
||||||
|
|
||||||
|
# ── Renode helper script ─────────────────────────────────────────
|
||||||
|
# Provides a quick way to launch Renode with a GDB server for a firmware ELF
|
||||||
|
cat >~/.local/bin/arduino-sim <<'SIMSCRIPT'
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: arduino-sim <firmware.elf> [platform]"
|
||||||
|
echo ""
|
||||||
|
echo "Launch Renode with a GDB server for debugging firmware."
|
||||||
|
echo "Connect nvim-dap or gdb to localhost:3333"
|
||||||
|
echo ""
|
||||||
|
echo "Platforms:"
|
||||||
|
echo " stm32f4 STM32F4 Discovery (default)"
|
||||||
|
echo " rp2040 Raspberry Pi Pico"
|
||||||
|
echo " nrf52840 nRF52840 (USB HID capable)"
|
||||||
|
echo ""
|
||||||
|
echo "Example:"
|
||||||
|
echo " arduino-sim build/firmware.elf nrf52840"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ $# -lt 1 ]] && usage
|
||||||
|
|
||||||
|
ELF="$1"
|
||||||
|
PLATFORM="${2:-stm32f4}"
|
||||||
|
|
||||||
|
[[ ! -f "$ELF" ]] && echo "Error: $ELF not found" && exit 1
|
||||||
|
|
||||||
|
# Map platform to Renode machine definition
|
||||||
|
case "$PLATFORM" in
|
||||||
|
stm32f4)
|
||||||
|
RENODE_PLATFORM="platforms/boards/stm32f4_discovery.repl"
|
||||||
|
MACHINE="STM32F4_Discovery"
|
||||||
|
;;
|
||||||
|
rp2040)
|
||||||
|
RENODE_PLATFORM="platforms/cpus/rp2040.repl"
|
||||||
|
MACHINE="RP2040"
|
||||||
|
;;
|
||||||
|
nrf52840)
|
||||||
|
RENODE_PLATFORM="platforms/cpus/nrf52840.repl"
|
||||||
|
MACHINE="nRF52840"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown platform: $PLATFORM"
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Generate a temporary Renode script
|
||||||
|
RESC=$(mktemp /tmp/renode-XXXXXX.resc)
|
||||||
|
cat >"$RESC" <<EOF
|
||||||
|
using sysbus
|
||||||
|
|
||||||
|
mach create "$MACHINE"
|
||||||
|
machine LoadPlatformDescription @$RENODE_PLATFORM
|
||||||
|
|
||||||
|
sysbus LoadELF @$(realpath "$ELF")
|
||||||
|
|
||||||
|
machine StartGdbServer 3333
|
||||||
|
|
||||||
|
showAnalyzer sysbus.uart0 Antmicro.Renode.Analyzers.LoggingUartAnalyzer
|
||||||
|
|
||||||
|
start
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "Starting Renode ($MACHINE) with GDB server on :3333"
|
||||||
|
echo "Connect debugger: nvim → <leader>ds or gdb → target remote :3333"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
renode --disable-xwt "$RESC"
|
||||||
|
rm -f "$RESC"
|
||||||
|
SIMSCRIPT
|
||||||
|
chmod +x ~/.local/bin/arduino-sim
|
||||||
|
|
||||||
|
info "Renode simulation helper created (arduino-sim)"
|
||||||
|
|
||||||
|
# ── Wokwi CLI (visual breadboard simulation) ────────────────────
|
||||||
|
if ! command -v wokwi-cli &>/dev/null; then
|
||||||
|
info "Installing Wokwi CLI..."
|
||||||
|
WOKWI_VERSION=$(curl -ks "https://api.github.com/repos/wokwi/wokwi-cli/releases/latest" | jq -r '.tag_name' | sed 's/^v//')
|
||||||
|
curl -ksSLo /tmp/wokwi-cli "https://github.com/wokwi/wokwi-cli/releases/download/v${WOKWI_VERSION}/wokwi-cli-linuxstatic-x64"
|
||||||
|
sudo install -m 755 /tmp/wokwi-cli /usr/local/bin/wokwi-cli
|
||||||
|
rm -f /tmp/wokwi-cli
|
||||||
|
else
|
||||||
|
info "Wokwi CLI already installed"
|
||||||
|
fi
|
||||||
|
info "Wokwi CLI installed (set WOKWI_CLI_TOKEN to enable — get one at https://wokwi.com/dashboard/ci)"
|
||||||
166
lib/scaffold.sh
166
lib/scaffold.sh
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Step 9: Project scaffolding tool + templates
|
# Step 9: Project scaffolding tool + templates
|
||||||
|
|
||||||
step "11/11 — Creating project scaffolding tool"
|
step "12/12 — Creating project scaffolding tool"
|
||||||
|
|
||||||
mkdir -p ~/.local/bin ~/.config/archduino/templates
|
mkdir -p ~/.local/bin ~/.config/archduino/templates
|
||||||
|
|
||||||
@@ -67,9 +67,38 @@ build/
|
|||||||
*.bin
|
*.bin
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# ── Wokwi simulation config ─────────────────────────────────────
|
||||||
|
# Determine firmware path format based on board family
|
||||||
|
case "$BOARD" in
|
||||||
|
esp32|esp32s3|esp8266)
|
||||||
|
WOKWI_FW="build/$PROJECT.ino.merged.bin"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
WOKWI_FW="build/$PROJECT.ino.hex"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
cat > wokwi.toml <<EOF
|
||||||
|
[wokwi]
|
||||||
|
version = 1
|
||||||
|
firmware = "$WOKWI_FW"
|
||||||
|
elf = "build/$PROJECT.ino.elf"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Board-specific diagram with button + LED on breadboard
|
||||||
|
DIAGRAM_TEMPLATE="$TEMPLATE_DIR/diagram-$BOARD.json"
|
||||||
|
if [[ -f "$DIAGRAM_TEMPLATE" ]]; then
|
||||||
|
cp "$DIAGRAM_TEMPLATE" diagram.json
|
||||||
|
else
|
||||||
|
cp "$TEMPLATE_DIR/diagram-default.json" diagram.json
|
||||||
|
fi
|
||||||
|
|
||||||
git init -q
|
git init -q
|
||||||
echo "✓ Created '$PROJECT' for $BOARD ($FQBN)"
|
echo "✓ Created '$PROJECT' for $BOARD ($FQBN)"
|
||||||
echo " cd $PROJECT && nvim $PROJECT.ino"
|
echo " cd $PROJECT && nvim $PROJECT.ino"
|
||||||
|
echo ""
|
||||||
|
echo " Simulate: arduino-cli compile --fqbn $FQBN --output-dir build ."
|
||||||
|
echo " wokwi-cli ."
|
||||||
SCAFFOLD
|
SCAFFOLD
|
||||||
chmod +x ~/.local/bin/arduino-new
|
chmod +x ~/.local/bin/arduino-new
|
||||||
|
|
||||||
@@ -135,6 +164,141 @@ void loop() {
|
|||||||
delay(1000);
|
delay(1000);
|
||||||
}
|
}
|
||||||
INO
|
INO
|
||||||
|
# ── Wokwi diagram templates ──────────────────────────────────────
|
||||||
|
cat >~/.config/archduino/templates/diagram-default.json <<'JSON'
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"author": "Archduino",
|
||||||
|
"editor": "wokwi",
|
||||||
|
"parts": [
|
||||||
|
{ "type": "wokwi-arduino-uno", "id": "mcu", "top": 0, "left": 0 },
|
||||||
|
{ "type": "wokwi-led", "id": "led1", "top": 110, "left": 50, "attrs": { "color": "green" } },
|
||||||
|
{ "type": "wokwi-resistor", "id": "r1", "top": 150, "left": 30, "attrs": { "value": "220" } },
|
||||||
|
{ "type": "wokwi-pushbutton", "id": "btn1", "top": 110, "left": 150, "attrs": { "color": "blue" } }
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
["mcu:2", "led1:A", "green", []],
|
||||||
|
["led1:C", "r1:1", "black", []],
|
||||||
|
["r1:2", "mcu:GND.1", "black", []],
|
||||||
|
["mcu:4", "btn1:1.l", "blue", []],
|
||||||
|
["btn1:2.l", "mcu:GND.2", "black", []]
|
||||||
|
],
|
||||||
|
"serialMonitor": { "display": "auto" }
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
cat >~/.config/archduino/templates/diagram-esp32.json <<'JSON'
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"author": "Archduino",
|
||||||
|
"editor": "wokwi",
|
||||||
|
"parts": [
|
||||||
|
{ "type": "board-esp32-devkit-c-v4", "id": "esp", "top": 0, "left": 0 },
|
||||||
|
{ "type": "wokwi-led", "id": "led1", "top": 110, "left": 50, "attrs": { "color": "green" } },
|
||||||
|
{ "type": "wokwi-resistor", "id": "r1", "top": 150, "left": 30, "attrs": { "value": "220" } },
|
||||||
|
{ "type": "wokwi-pushbutton", "id": "btn1", "top": 110, "left": 150, "attrs": { "color": "blue" } }
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
["esp:TX", "$serialMonitor:RX", "", []],
|
||||||
|
["esp:RX", "$serialMonitor:TX", "", []],
|
||||||
|
["esp:2", "led1:A", "green", []],
|
||||||
|
["led1:C", "r1:1", "black", []],
|
||||||
|
["r1:2", "esp:GND.1", "black", []],
|
||||||
|
["esp:4", "btn1:1.l", "blue", []],
|
||||||
|
["btn1:2.l", "esp:GND.2", "black", []]
|
||||||
|
],
|
||||||
|
"serialMonitor": { "display": "auto" }
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
cat >~/.config/archduino/templates/diagram-esp32s3.json <<'JSON'
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"author": "Archduino",
|
||||||
|
"editor": "wokwi",
|
||||||
|
"parts": [
|
||||||
|
{ "type": "board-esp32-s3-devkitc-1", "id": "esp", "top": 0, "left": 0, "attrs": { "serialInterface": "USB_SERIAL_JTAG" } },
|
||||||
|
{ "type": "wokwi-led", "id": "led1", "top": 110, "left": 50, "attrs": { "color": "green" } },
|
||||||
|
{ "type": "wokwi-resistor", "id": "r1", "top": 150, "left": 30, "attrs": { "value": "220" } },
|
||||||
|
{ "type": "wokwi-pushbutton", "id": "btn1", "top": 110, "left": 150, "attrs": { "color": "blue" } }
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
["esp:2", "led1:A", "green", []],
|
||||||
|
["led1:C", "r1:1", "black", []],
|
||||||
|
["r1:2", "esp:GND.1", "black", []],
|
||||||
|
["esp:4", "btn1:1.l", "blue", []],
|
||||||
|
["btn1:2.l", "esp:GND.2", "black", []]
|
||||||
|
],
|
||||||
|
"serialMonitor": { "display": "auto" }
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
cat >~/.config/archduino/templates/diagram-uno.json <<'JSON'
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"author": "Archduino",
|
||||||
|
"editor": "wokwi",
|
||||||
|
"parts": [
|
||||||
|
{ "type": "wokwi-arduino-uno", "id": "mcu", "top": 0, "left": 0 },
|
||||||
|
{ "type": "wokwi-led", "id": "led1", "top": 110, "left": 50, "attrs": { "color": "green" } },
|
||||||
|
{ "type": "wokwi-resistor", "id": "r1", "top": 150, "left": 30, "attrs": { "value": "220" } },
|
||||||
|
{ "type": "wokwi-pushbutton", "id": "btn1", "top": 110, "left": 150, "attrs": { "color": "blue" } }
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
["mcu:2", "led1:A", "green", []],
|
||||||
|
["led1:C", "r1:1", "black", []],
|
||||||
|
["r1:2", "mcu:GND.1", "black", []],
|
||||||
|
["mcu:4", "btn1:1.l", "blue", []],
|
||||||
|
["btn1:2.l", "mcu:GND.2", "black", []]
|
||||||
|
],
|
||||||
|
"serialMonitor": { "display": "auto" }
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
cat >~/.config/archduino/templates/diagram-mega.json <<'JSON'
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"author": "Archduino",
|
||||||
|
"editor": "wokwi",
|
||||||
|
"parts": [
|
||||||
|
{ "type": "wokwi-arduino-mega", "id": "mcu", "top": 0, "left": 0 },
|
||||||
|
{ "type": "wokwi-led", "id": "led1", "top": 110, "left": 50, "attrs": { "color": "green" } },
|
||||||
|
{ "type": "wokwi-resistor", "id": "r1", "top": 150, "left": 30, "attrs": { "value": "220" } },
|
||||||
|
{ "type": "wokwi-pushbutton", "id": "btn1", "top": 110, "left": 150, "attrs": { "color": "blue" } }
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
["mcu:2", "led1:A", "green", []],
|
||||||
|
["led1:C", "r1:1", "black", []],
|
||||||
|
["r1:2", "mcu:GND.1", "black", []],
|
||||||
|
["mcu:4", "btn1:1.l", "blue", []],
|
||||||
|
["btn1:2.l", "mcu:GND.2", "black", []]
|
||||||
|
],
|
||||||
|
"serialMonitor": { "display": "auto" }
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
cat >~/.config/archduino/templates/diagram-nano.json <<'JSON'
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"author": "Archduino",
|
||||||
|
"editor": "wokwi",
|
||||||
|
"parts": [
|
||||||
|
{ "type": "wokwi-arduino-nano", "id": "mcu", "top": 0, "left": 0 },
|
||||||
|
{ "type": "wokwi-led", "id": "led1", "top": 110, "left": 50, "attrs": { "color": "green" } },
|
||||||
|
{ "type": "wokwi-resistor", "id": "r1", "top": 150, "left": 30, "attrs": { "value": "220" } },
|
||||||
|
{ "type": "wokwi-pushbutton", "id": "btn1", "top": 110, "left": 150, "attrs": { "color": "blue" } }
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
["mcu:D2", "led1:A", "green", []],
|
||||||
|
["led1:C", "r1:1", "black", []],
|
||||||
|
["r1:2", "mcu:GND.1", "black", []],
|
||||||
|
["mcu:D4", "btn1:1.l", "blue", []],
|
||||||
|
["btn1:2.l", "mcu:GND.2", "black", []]
|
||||||
|
],
|
||||||
|
"serialMonitor": { "display": "auto" }
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
# ── Install theme files + theme switcher ─────────────────────────
|
# ── Install theme files + theme switcher ─────────────────────────
|
||||||
mkdir -p ~/.config/archduino/themes
|
mkdir -p ~/.config/archduino/themes
|
||||||
cp "$SCRIPT_DIR/lib/themes/"*.sh ~/.config/archduino/themes/
|
cp "$SCRIPT_DIR/lib/themes/"*.sh ~/.config/archduino/themes/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Step 3: Starship prompt
|
# Step 3: Starship prompt
|
||||||
|
|
||||||
step "4/11 — Installing Starship"
|
step "4/12 — Installing Starship"
|
||||||
|
|
||||||
if $IS_ARCH; then
|
if $IS_ARCH; then
|
||||||
$PKG_INSTALL starship
|
$PKG_INSTALL starship
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Step 8: Yazi file manager
|
# Step 8: Yazi file manager
|
||||||
|
|
||||||
step "8/11 — Installing Yazi"
|
step "8/12 — Installing Yazi"
|
||||||
|
|
||||||
if $IS_ARCH; then
|
if $IS_ARCH; then
|
||||||
$PKG_INSTALL yazi ffmpegthumbnailer p7zip poppler
|
$PKG_INSTALL yazi ffmpegthumbnailer p7zip poppler
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Step 4: Zellij terminal multiplexer
|
# Step 4: Zellij terminal multiplexer
|
||||||
|
|
||||||
step "5/11 — Installing Zellij"
|
step "5/12 — Installing Zellij"
|
||||||
|
|
||||||
if $IS_ARCH; then
|
if $IS_ARCH; then
|
||||||
$PKG_INSTALL zellij
|
$PKG_INSTALL zellij
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Step 2: Zsh + Oh My Zsh + plugins
|
# Step 2: Zsh + Oh My Zsh + plugins
|
||||||
|
|
||||||
step "3/11 — Setting up Zsh"
|
step "3/12 — Setting up Zsh"
|
||||||
|
|
||||||
if [[ ! -d "$HOME/.oh-my-zsh" ]]; then
|
if [[ ! -d "$HOME/.oh-my-zsh" ]]; then
|
||||||
RUNZSH=no KEEP_ZSHRC=yes CHSH=no sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended ||
|
RUNZSH=no KEEP_ZSHRC=yes CHSH=no sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended ||
|
||||||
|
|||||||
Reference in New Issue
Block a user