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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 92 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[![Rust](https://img.shields.io/badge/rust-2021_edition-orange.svg)](https://www.rust-lang.org/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey.svg)](https://github.com/IamShreshth/Tman)
[![Shell](https://img.shields.io/badge/shell-zsh%20%7C%20bash-green.svg)](https://github.com/IamShreshth/Tman)
[![Shell](https://img.shields.io/badge/shell-zsh%20%7C%20bash%20%7C%20fish-green.svg)](https://github.com/IamShreshth/Tman)
[![Dependencies](https://img.shields.io/badge/dependencies-zero_runtime-brightgreen.svg)](docs/requirements.txt)

<br/>
Expand Down Expand Up @@ -39,59 +39,121 @@ Press `Ctrl+Shift+T` (or `Ctrl+Space`) anywhere in your shell, or run `tman`.

---

## macOS Installation (Apple Silicon & Intel)

### Option 1: Single-Step Installer (Recommended)
Automatically detects Apple Silicon (`arm64`) or Intel (`x86_64`), installs `tman`, signs the binary (`codesign`) so Gatekeeper never prompts, and configures `~/.zshrc`:

```bash
curl -fsSL https://raw.githubusercontent.com/IamShreshth/Tman/main/files/install.sh | bash
source ~/.zshrc
```

### Option 2: Homebrew + Cargo (Build from Source)
```bash
# 1. Ensure Xcode Command Line Tools & Rust are installed
xcode-select --install 2>/dev/null || true
brew install rust # OR: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# 2. Install tman via Cargo
cargo install --git https://github.com/IamShreshth/Tman.git --locked

# 3. Activate in your shell (Zsh is default on macOS):
echo 'eval "$(tman init zsh)"' >> ~/.zshrc && source ~/.zshrc
# Bash: echo 'eval "$(tman init bash)"' >> ~/.bash_profile && source ~/.bash_profile
# Fish: mkdir -p ~/.config/fish && echo 'tman init fish | source' >> ~/.config/fish/config.fish
```

> **Note on macOS integration:** `pbcopy` (clipboard) and `open` (Finder / default app opener) work out of the box on macOS with zero extra packages. For `Ctrl+Shift+T` in iTerm2, Warp, Kitty, Alacritty, or WezTerm, you can also use `Ctrl+Space` at any time.

---

## Linux Installation

### Universal (All Distros)
### Universal One-Liner (All Distros)

Automatically detects your architecture (`x86_64` / `aarch64`), libc (`glibc` / `musl`), downloads the pre-built binary (or builds via Cargo if needed), and configures your shell:

```bash
curl -fsSL https://raw.githubusercontent.com/IamShreshth/Tman/main/files/install.sh | bash
```

### Fedora
---

### 1. Arch Linux (Manjaro, EndeavourOS, CachyOS)

```bash
# Install Rust toolchain (required to build from source)
sudo dnf install -y cargo rust
# 1. Install build prerequisites & optional clipboard/desktop helpers
sudo pacman -S --needed --noconfirm base-devel git rust wl-clipboard xclip xdg-utils

# Install tman
# 2. Install tman (via installer script or Cargo)
curl -fsSL https://raw.githubusercontent.com/IamShreshth/Tman/main/files/install.sh | bash
# OR build directly via Cargo:
# cargo install --git https://github.com/IamShreshth/Tman.git --locked

# Activate (add to ~/.bashrc or ~/.zshrc)
echo 'eval "$(tman init bash)"' >> ~/.bashrc
source ~/.bashrc
# 3. Activate in your shell:
source ~/.bashrc # Bash
# source ~/.zshrc # Zsh
# tman init fish | source # Fish (append to ~/.config/fish/config.fish)
```

### Arch Linux
---

### 2. Fedora (RHEL, CentOS Stream, Nobara)

```bash
# Install Rust toolchain
sudo pacman -S --noconfirm rust
# 1. Install Rust toolchain & optional clipboard/desktop helpers
sudo dnf install -y gcc git cargo rust wl-clipboard xclip xdg-utils

# Install tman
# 2. Install tman (via installer script or Cargo)
curl -fsSL https://raw.githubusercontent.com/IamShreshth/Tman/main/files/install.sh | bash
# OR build directly via Cargo:
# cargo install --git https://github.com/IamShreshth/Tman.git --locked

# Activate (add to ~/.bashrc or ~/.zshrc)
echo 'eval "$(tman init bash)"' >> ~/.bashrc
source ~/.bashrc
# 3. Activate in your shell:
source ~/.bashrc # Bash
# source ~/.zshrc # Zsh
# tman init fish | source # Fish (append to ~/.config/fish/config.fish)
```

> **AUR users:** If an AUR package becomes available, you can also use `yay -S tman` or `paru -S tman`.
---

### Ubuntu / Debian
### 3. Ubuntu / Debian (Linux Mint, Pop!_OS, Kali)

```bash
# Install Rust toolchain
sudo apt update && sudo apt install -y cargo rustc
# 1. Install build tools, Rust toolchain & optional clipboard/desktop helpers
sudo apt update && sudo apt install -y build-essential curl git cargo rustc wl-clipboard xclip xdg-utils

# Install tman
# 2. Install tman (via installer script or Cargo)
curl -fsSL https://raw.githubusercontent.com/IamShreshth/Tman/main/files/install.sh | bash
# OR build directly via Cargo:
# cargo install --git https://github.com/IamShreshth/Tman.git --locked

# Activate (add to ~/.bashrc or ~/.zshrc)
echo 'eval "$(tman init bash)"' >> ~/.bashrc
source ~/.bashrc
# 3. Activate in your shell:
source ~/.bashrc # Bash
# source ~/.zshrc # Zsh
# tman init fish | source # Fish (append to ~/.config/fish/config.fish)
```

> **Note on keybindings:** Most Linux terminal emulators intercept `Ctrl+Shift+T` (e.g., GNOME Terminal uses it to open a new tab). Use `Ctrl+Space` instead by setting `open = "ctrl-space"` in your tman config (`~/.config/tman/config.toml`).
> **Tip for older Ubuntu/Debian releases:** If the `apt` Rust version is older than `1.70`, install the latest toolchain via `rustup`:
> ```bash
> curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
> source "$HOME/.cargo/env"
> ```

---

### Manual Shell Hook Setup (If Installing via Cargo)

If you installed via `cargo install` instead of `install.sh`, add the shell hook for your shell:

| Shell | Command |
| :--- | :--- |
| **Bash** | `echo 'eval "$(tman init bash)"' >> ~/.bashrc && source ~/.bashrc` |
| **Zsh** | `echo 'eval "$(tman init zsh)"' >> ~/.zshrc && source ~/.zshrc` |
| **Fish** | `mkdir -p ~/.config/fish && echo 'tman init fish \| source' >> ~/.config/fish/config.fish && source ~/.config/fish/config.fish` |

> **Note on Linux keybindings:** Most Linux terminal emulators intercept `Ctrl+Shift+T` to open a new tab. `tman` automatically binds **`Ctrl+Space`** alongside `Ctrl+Shift+T` so you can press `Ctrl+Space` out of the box on GNOME Terminal, Konsole, XFCE Terminal, Alacritty, Kitty, and WezTerm.

---

Expand All @@ -115,8 +177,10 @@ source ~/.bashrc
| `Left` / `h` / `Backspace` | Submenus | Navigate to parent directory / previous view |
| `b` | Menu / Files | Bookmark current directory or highlighted folder |
| `d` or `x` | Bookmarks | Delete highlighted bookmark |
| `Space` | Git Changed Files | Stage / unstage highlighted file in-place |
| `Q` | File Browser | Quit HUD and `cd` shell into the browsed directory |
| `Tab` | Browser / Runners | Open action menu (`Open with app`, `Open file manager`, copy path) |
| `/` | Lists | Filter items with fuzzy search |
| `/` | Lists | Filter items with multi-word fuzzy search |
| `.` | File Browser | Toggle hidden dotfiles |
| `m` | Submenus | Return to main menu |
| `Esc` | Any View | Clear search / close modal / exit HUD |
Expand All @@ -131,10 +195,10 @@ source ~/.bashrc
| Component | Requirement |
| :--- | :--- |
| **Operating System** | macOS (Apple Silicon & Intel) or Linux (x86_64, aarch64, musl/glibc) |
| **Supported Shells** | Zsh (v5.0+) or Bash (v4.0+) |
| **Supported Shells** | Zsh (v5.0+), Bash (v4.0+), or Fish (v3.4+) |
| **Build Toolchain** | Rust 1.70+ and Cargo (only when building from source) |

See [docs/linux.md](docs/linux.md) for Linux-specific details and [docs/requirements.txt](docs/requirements.txt) for technical specifications.
See [linux.md](linux.md) for Linux-specific details and [docs/requirements.txt](docs/requirements.txt) for technical specifications.

---

Expand Down
128 changes: 87 additions & 41 deletions docs/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,111 +72,157 @@ document.addEventListener('DOMContentLoaded', () => {
const simList = document.getElementById('sim-list');
const dynTitle = document.getElementById('dyn-block-title');
const dynContent = document.getElementById('dyn-content');
const rightPanelTitle = document.getElementById('right-panel-title');

const themeColors = {
cyan: '#46d7e6',
blue: '#5aa0ff',
green: '#50dc96',
magenta: '#c878ff',
peach: '#ffb48c'
};

const actionStates = {
navigate: {
title: 'DIRECTORY CONTENTS',
panel: 'MISSION CONTROL',
title: '━━━ DIRECTORY CONTENTS ━━━━━━━━━━━━━━━',
items: [
'▸ src/',
'▸ tests/',
'· Cargo.toml',
'· Dockerfile',
'· README.md'
' Cargo.toml',
' Dockerfile',
' README.md'
]
},
bookmarks: {
title: 'PINNED BOOKMARKS',
panel: 'PREVIEW BOOKMARKS',
title: '━━━ PINNED & RECENT (ZOXIDE) ━━━━━━━━━',
items: [
'* ~/projects/tman',
'* ~/code/dotfiles',
'* ~/.config/nvim',
'* ~/work/backend-api'
'↺ ~/.config/nvim [recent]',
'↺ ~/work/backend-api [recent]'
]
},
history: {
title: 'LIVE SHELL HISTORY (DEDUPLICATED)',
panel: 'PREVIEW HISTORY',
title: '━━━ LIVE SHELL HISTORY (DEDUPLICATED) ━',
items: [
'↺ cargo test --release',
'↺ git status -sb',
'↺ docker compose up -d',
'↺ nvim src/main.rs',
'↺ git push origin main'
'· cargo test --release',
'· git status -sb',
'· docker compose up -d',
'· nvim src/main.rs',
'· git push fork linux_ins'
]
},
search: {
title: 'FUZZY MATCHES (QUERY: "sys")',
panel: 'PREVIEW SEARCH',
title: '━━━ GITIGNORE-AWARE FUZZY MATCHES ━━━━',
items: [
'· src/sys.rs (kernel telemetry)',
'· tests/test_sys.rs',
'· src/safety.rs'
'· src/sys.rs',
'· src/safety.rs',
'· src/git.rs',
'· files/install.sh'
]
},
git: {
title: 'GIT ACTIONS & STATUS',
panel: 'PREVIEW GIT',
title: '━━━ INTERACTIVE GIT WORKFLOWS ━━━━━━━━',
items: [
'⎇ Status: 2 staged, 1 modified, 0 untracked',
'⎇ Commit: "feat: add linux support"',
'⎇ Diff: unstaged changes in src/sys.rs',
'⎇ Pull (fast-forward preview)',
'⎇ Push (origin/main)'
'⎇ Changed files (Space to stage/unstage)',
'⎇ Branches (git switch + log preview)',
'⎇ Stashes (git stash pop + diff)',
'+185 -79 in src/app.rs, src/git.rs'
]
},
run: {
title: 'DISCOVERED WORKFLOW TARGETS',
panel: 'PREVIEW RUN',
title: '━━━ DISCOVERED PROJECT TARGETS ━━━━━━━',
items: [
'▶ cargo build Cargo.toml',
'▶ cargo test Cargo.toml',
'▶ docker compose up -d Docker Compose',
'▶ ${EDITOR:-vi} .env .env (DATABASE_URL = ***)'
]
},
ports: {
panel: 'PREVIEW ACTIVE PORTS',
title: '━━━ LISTENING TCP PORTS (LSOF / SS) ━━',
items: [
'▶ cargo build',
'▶ cargo run -- ui',
'▶ cargo test',
'▶ cargo clippy',
'▶ docker build -t app .'
'◈ :3000 node PID 41230',
'◈ :5432 postgres PID 1892',
'◈ :8080 cargo-watch PID 50211'
]
},
theme: {
title: 'ACCENT COLOR PALETTE',
panel: 'PREVIEW THEMES',
title: '━━━ CLICK A THEME TO PREVIEW ━━━━━━━━━',
items: [
'# Cyan (active default)',
'# Blue (Tokyo Night)',
'# Green (Matrix)',
'# Magenta (Synthwave)',
'# Peach (Catppuccin)'
'# cyan Futuristic high-tech cyan [active]',
'# blue Electric royal blue',
'# green Matrix / terminal emerald green',
'# magenta Cyberpunk neon magenta',
'# peach Soft warm aesthetic peach'
]
}
};

if (simList && dynTitle && dynContent) {
const items = simList.querySelectorAll('.hud-item');
let hudHovered = false;

if (interactiveView) {
interactiveView.addEventListener('mouseenter', () => { hudHovered = true; });
interactiveView.addEventListener('mouseleave', () => { hudHovered = false; });
}

function selectAction(item) {
items.forEach(i => {
i.classList.remove('active');
i.querySelector('.item-pointer').textContent = ' ';
});
item.classList.add('active');
item.querySelector('.item-pointer').textContent = '›';
item.querySelector('.item-pointer').textContent = '❯';

const actionKey = item.getAttribute('data-action');
const state = actionStates[actionKey];
if (state) {
if (rightPanelTitle) rightPanelTitle.textContent = state.panel;
dynTitle.textContent = state.title;
dynContent.innerHTML = state.items.map(text => `<div class="dyn-item">${escapeHtml(text)}</div>`).join('');
dynContent.innerHTML = state.items.map(text => {
const themeMatch = actionKey === 'theme' ? text.match(/^#\s+(\w+)/) : null;
const attr = themeMatch ? ` data-theme-color="${themeMatch[1]}" style="cursor:pointer"` : '';
return `<div class="dyn-item"${attr}>${escapeHtml(text)}</div>`;
}).join('');

if (actionKey === 'theme') {
dynContent.querySelectorAll('[data-theme-color]').forEach(el => {
el.addEventListener('click', () => {
const c = themeColors[el.getAttribute('data-theme-color')];
if (c) document.documentElement.style.setProperty('--cyan-primary', c);
});
});
}
}
}

items.forEach(item => {
item.addEventListener('click', () => selectAction(item));
});

// Keyboard navigation (Up / Down) when focusing on the simulator
// Keyboard navigation (Up/Down or j/k) only when hovering or focusing the simulator
window.addEventListener('keydown', (e) => {
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
const focused = document.activeElement === interactiveView || (interactiveView && interactiveView.contains(document.activeElement));
if (!hudHovered && !focused) return;
if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'j' || e.key === 'k') {
const activeItem = simList.querySelector('.hud-item.active');
if (!activeItem) return;
const all = Array.from(items);
const idx = all.indexOf(activeItem);
if (e.key === 'ArrowDown' && idx < all.length - 1) {
if ((e.key === 'ArrowDown' || e.key === 'j') && idx < all.length - 1) {
e.preventDefault();
selectAction(all[idx + 1]);
} else if (e.key === 'ArrowUp' && idx > 0) {
} else if ((e.key === 'ArrowUp' || e.key === 'k') && idx > 0) {
e.preventDefault();
selectAction(all[idx - 1]);
}
Expand Down
Loading
Loading