diff --git a/.gitignore b/.gitignore index 474b2e6..8d91bd2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ nvim-macos-arm64 nvim.appimage .DS_Store +docs/superpowers +.worktrees diff --git a/install/lib/common.sh b/install/lib/common.sh index 7ec00d6..13a5542 100644 --- a/install/lib/common.sh +++ b/install/lib/common.sh @@ -75,16 +75,3 @@ install_fzf() { mkdir -p "${local_bin_dir}" ln -sf "$HOME/.fzf/bin/fzf" "${local_bin_dir}/fzf" } - -fix_linux_cli_names() { - local local_bin_dir="${HOME}/.local/bin" - mkdir -p "${local_bin_dir}" - - if ! command -v fd >/dev/null 2>&1 && command -v fdfind >/dev/null 2>&1; then - ln -sf "$(command -v fdfind)" "${local_bin_dir}/fd" - fi - - if ! command -v bat >/dev/null 2>&1 && command -v batcat >/dev/null 2>&1; then - ln -sf "$(command -v batcat)" "${local_bin_dir}/bat" - fi -} diff --git a/install/nvim-bin.sh b/install/nvim-bin.sh new file mode 100755 index 0000000..b054bed --- /dev/null +++ b/install/nvim-bin.sh @@ -0,0 +1,183 @@ +#!/usr/bin/env bash +set -euo pipefail + +NVIM_CHANNEL="nightly" + +LOCAL_DIR="${HOME}/.local" +LOCAL_BIN_DIR="${LOCAL_DIR}/bin" + +OS="$(uname -s)" +ARCH="$(uname -m)" + +mkdir -p "${LOCAL_DIR}" "${LOCAL_BIN_DIR}" + +need_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "Error: required command '$1' not found." + exit 1 + } +} + +append_once() { + local line="$1" + local file="$2" + mkdir -p "$(dirname "$file")" + touch "$file" + grep -Fqx "$line" "$file" || echo "$line" >> "$file" +} + +apt_install() { + need_cmd apt-get + if [[ "$(id -u)" -eq 0 ]]; then + apt-get update + apt-get install -y "$@" + elif command -v sudo >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y "$@" + else + echo "Error: need root or sudo to install packages with apt-get." + exit 1 + fi +} + +brew_install() { + need_cmd brew + brew install "$@" +} + +ensure_local_bin_path() { + local path_line='export PATH="$HOME/.local/bin:$PATH"' + append_once "${path_line}" "$HOME/.bashrc" + append_once "${path_line}" "$HOME/.zshrc" +} + +install_fzf() { + if command -v fzf >/dev/null 2>&1; then + return + fi + echo "Installing fzf..." + need_cmd git + if [[ ! -d "$HOME/.fzf" ]]; then + git clone --depth 1 https://github.com/junegunn/fzf.git "$HOME/.fzf" + fi + "$HOME/.fzf/install" --bin --no-update-rc + mkdir -p "${LOCAL_BIN_DIR}" + ln -sf "$HOME/.fzf/bin/fzf" "${LOCAL_BIN_DIR}/fzf" +} + +fix_linux_cli_names() { + mkdir -p "${LOCAL_BIN_DIR}" + if ! command -v fd >/dev/null 2>&1 && command -v fdfind >/dev/null 2>&1; then + ln -sf "$(command -v fdfind)" "${LOCAL_BIN_DIR}/fd" + fi + if ! command -v bat >/dev/null 2>&1 && command -v batcat >/dev/null 2>&1; then + ln -sf "$(command -v batcat)" "${LOCAL_BIN_DIR}/bat" + fi +} + +install_linux_deps() { + echo "Installing Neovim dependencies for Linux..." + apt_install \ + curl \ + git \ + ripgrep \ + fd-find \ + bat \ + clang \ + libclang-dev + + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + . "$HOME/.cargo/env" + cargo install --locked tree-sitter-cli + + fix_linux_cli_names + install_fzf +} + +install_macos_deps() { + echo "Installing Neovim dependencies for macOS..." + brew_install curl \ + git \ + fd \ + ripgrep \ + bat \ + llvm \ + tree-sitter-cli + + install_fzf +} + +install_nvim_macos() { + need_cmd curl + need_cmd tar + + local name file url + + case "${ARCH}" in + arm64) name="nvim-macos-arm64" ;; + x86_64) name="nvim-macos-x86_64" ;; + *) + echo "Unsupported macOS architecture: ${ARCH}" + exit 1 + ;; + esac + + file="${name}.tar.gz" + url="https://github.com/neovim/neovim/releases/download/${NVIM_CHANNEL}/${file}" + + echo "Downloading Neovim ${NVIM_CHANNEL} for macOS (${ARCH})..." + curl -fL "${url}" -o "/tmp/${file}" + + rm -rf "${LOCAL_DIR:?}/${name}" "${LOCAL_BIN_DIR}/nvim" + tar xzf "/tmp/${file}" -C "${LOCAL_DIR}" + ln -sf "${LOCAL_DIR}/${name}/bin/nvim" "${LOCAL_BIN_DIR}/nvim" + + rm -f "/tmp/${file}" +} + +install_nvim_linux() { + need_cmd curl + + local name url + + case "${ARCH}" in + x86_64) name="nvim-linux-x86_64.appimage" ;; + aarch64|arm64) name="nvim-linux-arm64.appimage" ;; + *) + echo "Unsupported Linux architecture: ${ARCH}" + exit 1 + ;; + esac + + url="https://github.com/neovim/neovim/releases/download/${NVIM_CHANNEL}/${name}" + + echo "Downloading Neovim ${NVIM_CHANNEL} AppImage for Linux (${ARCH})..." + curl -fL "${url}" -o "${LOCAL_BIN_DIR}/nvim" + chmod u+x "${LOCAL_BIN_DIR}/nvim" +} + +main() { + case "${OS}" in + Darwin) + install_macos_deps + install_nvim_macos + ;; + Linux) + install_linux_deps + install_nvim_linux + ;; + *) + echo "Unsupported operating system: ${OS}" + exit 1 + ;; + esac + + ensure_local_bin_path + + echo + echo "Neovim binary installation completed." +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + main "$@" +fi diff --git a/install/nvim.sh b/install/nvim.sh index 84ab15e..f850d5d 100755 --- a/install/nvim.sh +++ b/install/nvim.sh @@ -3,110 +3,13 @@ set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)" -# shellcheck source=lib/common.sh -source "${SCRIPT_DIR}/lib/common.sh" -NVIM_CHANNEL="nightly" +# shellcheck source=install/nvim-bin.sh +source "${SCRIPT_DIR}/nvim-bin.sh" -LOCAL_DIR="${HOME}/.local" -LOCAL_BIN_DIR="${LOCAL_DIR}/bin" CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/nvim" NVIM_SOURCE_DIR="${REPO_ROOT}/nvim" -OS="$(uname -s)" -ARCH="$(uname -m)" - -mkdir -p "${LOCAL_DIR}" "${LOCAL_BIN_DIR}" - -install_linux_deps() { - echo "Installing Neovim dependencies for Linux..." - apt_install \ - curl \ - git \ - ripgrep \ - fd-find \ - bat \ - clang \ - libclang-dev - - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - . "$HOME/.cargo/env" - cargo install --locked tree-sitter-cli - - fix_linux_cli_names - install_fzf -} - -install_macos_deps() { - echo "Installing Neovim dependencies for macOS..." - brew_install curl \ - git \ - fd \ - ripgrep \ - bat \ - llvm \ - tree-sitter-cli - - install_fzf -} - -install_nvim_macos() { - need_cmd curl - need_cmd tar - - local name file url - - case "${ARCH}" in - arm64) - name="nvim-macos-arm64" - ;; - x86_64) - name="nvim-macos-x86_64" - ;; - *) - echo "Unsupported macOS architecture: ${ARCH}" - exit 1 - ;; - esac - - file="${name}.tar.gz" - url="https://github.com/neovim/neovim/releases/download/${NVIM_CHANNEL}/${file}" - - echo "Downloading Neovim ${NVIM_CHANNEL} for macOS (${ARCH})..." - curl -fL "${url}" -o "/tmp/${file}" - - rm -rf "${LOCAL_DIR:?}/${name}" "${LOCAL_BIN_DIR}/nvim" - tar xzf "/tmp/${file}" -C "${LOCAL_DIR}" - ln -sf "${LOCAL_DIR}/${name}/bin/nvim" "${LOCAL_BIN_DIR}/nvim" - - rm -f "/tmp/${file}" -} - -install_nvim_linux() { - need_cmd curl - - local name url - - case "${ARCH}" in - x86_64) - name="nvim-linux-x86_64.appimage" - ;; - aarch64|arm64) - name="nvim-linux-arm64.appimage" - ;; - *) - echo "Unsupported Linux architecture: ${ARCH}" - exit 1 - ;; - esac - - url="https://github.com/neovim/neovim/releases/download/${NVIM_CHANNEL}/${name}" - - echo "Downloading Neovim ${NVIM_CHANNEL} AppImage for Linux (${ARCH})..." - curl -fL "${url}" -o "${LOCAL_BIN_DIR}/nvim" - chmod u+x "${LOCAL_BIN_DIR}/nvim" -} - install_nvim_config() { [[ -d "${NVIM_SOURCE_DIR}" ]] || { echo "Error: Neovim config directory not found: ${NVIM_SOURCE_DIR}" @@ -119,7 +22,7 @@ install_nvim_config() { cp -R "${NVIM_SOURCE_DIR}" "${CONFIG_DIR}" } -main() { +main_local() { case "${OS}" in Darwin) install_macos_deps @@ -146,4 +49,4 @@ main() { echo " nvim --version" } -main "$@" +main_local "$@" diff --git a/install/zk-bin.sh b/install/zk-bin.sh new file mode 100755 index 0000000..c41d992 --- /dev/null +++ b/install/zk-bin.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env bash +set -euo pipefail + +OS="$(uname -s)" +ARCH="$(uname -m)" + +ZK_VERSION="v0.15.2" + +ZK_INSTALL_DIR="$HOME/.local/bin" +ZK_BIN="${ZK_INSTALL_DIR}/zk" + +TMPDIR_TO_CLEANUP="" +cleanup_tmpdir() { + [[ -n "${TMPDIR_TO_CLEANUP:-}" ]] && rm -rf -- "${TMPDIR_TO_CLEANUP}" +} + +need_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "Error: required command '$1' not found." + exit 1 + } +} + +apt_install() { + need_cmd apt-get + if [[ "$(id -u)" -eq 0 ]]; then + apt-get update + apt-get install -y "$@" + elif command -v sudo >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y "$@" + else + echo "Error: need root or sudo to install packages with apt-get." + exit 1 + fi +} + +brew_install() { + need_cmd brew + brew install "$@" +} + +install_linux_deps() { + echo "Installing zk dependencies for Ubuntu..." + apt_install curl tar +} + +install_macos_deps() { + echo "Installing zk dependencies for macOS..." + brew_install curl gnu-tar +} + +get_zk_platform() { + case "${OS}" in + Linux) echo "linux" ;; + Darwin) echo "macos" ;; + *) + echo "Unsupported operating system: ${OS}" >&2 + exit 1 + ;; + esac +} + +get_zk_arch() { + case "${ARCH}" in + x86_64|amd64) echo "amd64" ;; + arm64|aarch64) echo "arm64" ;; + i386|i686) echo "i386" ;; + *) + echo "Unsupported architecture: ${ARCH}" >&2 + exit 1 + ;; + esac +} + +install_zk_from_release() { + echo "Installing zk ${ZK_VERSION} from prebuilt release..." + + need_cmd curl + need_cmd tar + need_cmd install + need_cmd mktemp + + local platform arch asset_name download_url extracted_bin + platform="$(get_zk_platform)" + arch="$(get_zk_arch)" + + asset_name="zk-${ZK_VERSION}-${platform}-${arch}.tar.gz" + download_url="https://github.com/zk-org/zk/releases/download/${ZK_VERSION}/${asset_name}" + + TMPDIR_TO_CLEANUP="$(mktemp -d)" + trap cleanup_tmpdir EXIT + + mkdir -p "${ZK_INSTALL_DIR}" + + echo "Downloading ${asset_name}..." + curl -fL "${download_url}" -o "${TMPDIR_TO_CLEANUP}/${asset_name}" + + echo "Extracting ${asset_name}..." + tar -xzf "${TMPDIR_TO_CLEANUP}/${asset_name}" -C "${TMPDIR_TO_CLEANUP}" + + extracted_bin="$(find "${TMPDIR_TO_CLEANUP}" -type f -name zk | head -n 1 || true)" + if [[ -z "${extracted_bin}" ]]; then + echo "Error: could not find zk binary after extracting ${asset_name}" + exit 1 + fi + + install -m 0755 "${extracted_bin}" "${ZK_BIN}" +} + +main() { + case "${OS}" in + Darwin) install_macos_deps ;; + Linux) install_linux_deps ;; + *) + echo "Unsupported operating system: ${OS}" + exit 1 + ;; + esac + + install_zk_from_release + + echo + echo "zk binary installation completed." + "${ZK_BIN}" --version +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + main "$@" +fi diff --git a/install/zk.sh b/install/zk.sh index 8e3da19..1458899 100755 --- a/install/zk.sh +++ b/install/zk.sh @@ -3,16 +3,9 @@ set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)" -# shellcheck source=lib/common.sh -source "${SCRIPT_DIR}/lib/common.sh" -OS="$(uname -s)" -ARCH="$(uname -m)" - -ZK_VERSION="v0.15.2" - -ZK_INSTALL_DIR="$HOME/.local/bin" -ZK_BIN="${ZK_INSTALL_DIR}/zk" +# shellcheck source=install/zk-bin.sh +source "${SCRIPT_DIR}/zk-bin.sh" ZK_SOURCE_DIR="${REPO_ROOT}/zk" ZK_SOURCE_CONFIG="${ZK_SOURCE_DIR}/config.toml" @@ -23,18 +16,26 @@ ZK_NOTEBOOK_META_DIR="${ZK_NOTEBOOK_DIR}/.zk" ZK_NOTEBOOK_CONFIG="${ZK_NOTEBOOK_META_DIR}/config.toml" ZK_NOTEBOOK_TEMPLATES_DIR="${ZK_NOTEBOOK_META_DIR}/templates" -cleanup_tmpdir() { - [[ -n "${TMPDIR_TO_CLEANUP:-}" ]] && rm -rf -- "${TMPDIR_TO_CLEANUP}" +append_once() { + local line="$1" + local file="$2" + mkdir -p "$(dirname "$file")" + touch "$file" + grep -Fqx "$line" "$file" || echo "$line" >> "$file" } -install_linux_deps() { - echo "Installing zk dependencies for Ubuntu..." - apt_install curl tar -} +copy_file() { + local src="$1" + local dst="$2" -install_macos_deps() { - echo "Installing zk dependencies for macOS..." - brew_install curl gnu-tar + [[ -f "${src}" ]] || { + echo "Error: source file not found: ${src}" + exit 1 + } + + echo "Copying $(basename "$src")..." + mkdir -p "$(dirname "$dst")" + cp -f "${src}" "${dst}" } setup_shell_init() { @@ -47,68 +48,6 @@ setup_shell_init() { append_once 'export ZK_NOTEBOOK_DIR="$HOME/notebook"' "$HOME/.bashrc" } -get_zk_platform() { - case "${OS}" in - Linux) echo "linux" ;; - Darwin) echo "macos" ;; - *) - echo "Unsupported operating system: ${OS}" >&2 - exit 1 - ;; - esac -} - -get_zk_arch() { - case "${ARCH}" in - x86_64|amd64) echo "amd64" ;; - arm64|aarch64) - if [[ "${OS}" == "Darwin" ]]; then - echo "arm64" - else - echo "arm64" - fi - ;; - i386|i686) echo "i386" ;; - *) - echo "Unsupported architecture: ${ARCH}" >&2 - exit 1 - ;; - esac -} - -install_zk_from_release() { - echo "Installing zk ${ZK_VERSION} from prebuilt release..." - - need_cmd curl - need_cmd tar - need_cmd install - need_cmd mktemp - - local platform arch asset_name download_url extracted_bin - platform="$(get_zk_platform)" - arch="$(get_zk_arch)" - - asset_name="zk-${ZK_VERSION}-${platform}-${arch}.tar.gz" - download_url="https://github.com/zk-org/zk/releases/download/${ZK_VERSION}/${asset_name}" - - TMPDIR_TO_CLEANUP="$(mktemp -d)" - trap cleanup_tmpdir EXIT - - echo "Downloading ${asset_name}..." - curl -fL "${download_url}" -o "${TMPDIR_TO_CLEANUP}/${asset_name}" - - echo "Extracting ${asset_name}..." - tar -xzf "${TMPDIR_TO_CLEANUP}/${asset_name}" -C "${TMPDIR_TO_CLEANUP}" - - extracted_bin="$(find "${TMPDIR_TO_CLEANUP}" -type f -name zk | head -n 1 || true)" - if [[ -z "${extracted_bin}" ]]; then - echo "Error: could not find zk binary after extracting ${asset_name}" - exit 1 - fi - - install -m 0755 "${extracted_bin}" "${ZK_BIN}" -} - bootstrap_zk_notebook() { [[ -f "${ZK_SOURCE_CONFIG}" ]] || { echo "Error: zk config file not found: ${ZK_SOURCE_CONFIG}" @@ -151,14 +90,10 @@ bootstrap_zk_notebook() { mkdir -p "${ZK_NOTEBOOK_DIR}/daily" } -main() { +main_local() { case "${OS}" in - Darwin) - install_macos_deps - ;; - Linux) - install_linux_deps - ;; + Darwin) install_macos_deps ;; + Linux) install_linux_deps ;; *) echo "Unsupported operating system: ${OS}" exit 1 @@ -174,4 +109,4 @@ main() { "${ZK_BIN}" --version } -main "$@" +main_local "$@"