just-cli 0.3.0__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- just_cli-0.3.1/.claude/plans/2026-04-18-edit-installer-macos-micro.md +237 -0
- just_cli-0.3.1/.claude/settings.local.json +9 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/PKG-INFO +1 -1
- {just_cli-0.3.0 → just_cli-0.3.1}/pyproject.toml +1 -1
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/workspace.py +5 -2
- just_cli-0.3.1/src/just/installers/edit/installer.py +72 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/tui/workspace.py +101 -8
- just_cli-0.3.0/.claude/settings.local.json +0 -7
- just_cli-0.3.0/src/just/installers/edit/installer.py +0 -31
- {just_cli-0.3.0 → just_cli-0.3.1}/.claude/skills/textual/README.md +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/.claude/skills/textual/SKILL.md +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/.claude/skills/textual/guide.md +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/.claude/skills/textual/quick-reference.md +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/.github/workflows/publish.yml +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/.gitignore +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/AGENTS.md +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/Dockerfile +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/README.md +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/docs/extension_guide.md +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/docs/images/editor_demo.png +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/docs/images/viewer_demo.png +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/scripts/system/linux/proxy/proxy.sh +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/scripts/system/mac/proxy/proxy.sh +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/scripts/system/windows/proxy/proxy.bat +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/scripts/system/windows/proxy/proxy.ps1 +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/cli.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/download.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/edit.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/ext/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/ext/add.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/ext/edit.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/ext/list.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/ext/remove.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/extract.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/install.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/linux.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/note.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/tunnel.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/commands/view.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/config/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/config/config.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/config/utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/extension/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/extension/generator.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/extension/parser.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/extension/utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/extension/validator.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/AGENTS.md +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/decorator.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/install_package.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/installers/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/installers/binary_release.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/installers/remote_script.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/package_info.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/source/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/source/base.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/source/http.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/source/local.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/installer/utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/system_probe/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/system_probe/system_info.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/core/system_probe/system_probe.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/AGENTS.md +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/brew/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/claude-code/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/claude-code/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/cloudflare/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/cloudflare/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/docker/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/docker/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/edit/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/gh/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/gh/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/miniconda3/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/mssh/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/mssh/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/nvm/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/nvm/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/openclaw/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/opencode/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/qodercli/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/qodercli/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/tailscale/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/tailscale/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/uv/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/installers/uv/installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/tui/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/tui/editor.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/tui/extension.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/tui/markdown.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/tui/note.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/AGENTS.md +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/archive/__init__.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/archive/compression_handler.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/archive/extractor.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/archive/format_detect.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/archive/sevenzip_handler.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/archive/tar_handler.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/archive/zip_handler.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/docker_utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/download_utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/echo_utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/env_utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/file_utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/format_utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/note_utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/progress.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/shell_utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/system_probe.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/typer_utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/src/just/utils/user_interaction.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/AGENTS.md +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/requirements.txt +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/run_tests.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_archive_extraction.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_bash_script_installer.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_download.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_extension/README.md +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_extension/test_ext.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_extension/test_extension_add.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_extension.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_file_utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_init.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_installer_e2e.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_linux_commands.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_progress_utils.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/test_system_probe.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/tests/testing.py +0 -0
- {just_cli-0.3.0 → just_cli-0.3.1}/uv.lock +0 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Edit Installer: macOS Support with micro Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** Add macOS support to `just install edit` by installing the `micro` text editor
|
|
6
|
+
|
|
7
|
+
**Architecture:** Platform-specific branching in installer function - Windows/Linux continue using Microsoft Edit, macOS uses micro with symlink from `edit` to `micro`.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Python 3.10+, typer, just installer framework
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## File Structure
|
|
14
|
+
|
|
15
|
+
**Files to modify:**
|
|
16
|
+
- `src/just/installers/edit/installer.py` - Main installer implementation
|
|
17
|
+
|
|
18
|
+
**No new files needed.**
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Chunk 1: Update installer.py with macOS micro support
|
|
23
|
+
|
|
24
|
+
### Task 1: Modify version parameter and add platform detection
|
|
25
|
+
|
|
26
|
+
**Files:**
|
|
27
|
+
- Modify: `src/just/installers/edit/installer.py`
|
|
28
|
+
|
|
29
|
+
- [ ] **Step 1: Update the version parameter default**
|
|
30
|
+
|
|
31
|
+
Change the `version` parameter default from `"1.2.0"` to `None`:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
def install_edit(
|
|
35
|
+
version: just.Annotated[
|
|
36
|
+
str, just.Option("-v", "--version", help="The version of Edit to install.")
|
|
37
|
+
] = None, # Changed from "1.2.0"
|
|
38
|
+
):
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- [ ] **Step 2: Add version resolution logic**
|
|
42
|
+
|
|
43
|
+
Add platform-specific default version after the function definition:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
# Resolve default version based on platform
|
|
47
|
+
if version is None:
|
|
48
|
+
if just.system.platform == "darwin":
|
|
49
|
+
version = "2.0.15" # micro latest stable
|
|
50
|
+
else:
|
|
51
|
+
version = "1.2.0" # Microsoft Edit
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- [ ] **Step 3: Update docstring**
|
|
55
|
+
|
|
56
|
+
Update the docstring to reflect macOS support:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
"""
|
|
60
|
+
Install a terminal text editor.
|
|
61
|
+
|
|
62
|
+
- Windows/Linux: Microsoft Edit
|
|
63
|
+
- macOS: micro (with 'edit' symlink)
|
|
64
|
+
"""
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- [ ] **Step 4: Commit**
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git add src/just/installers/edit/installer.py
|
|
71
|
+
git commit -m "feat(edit): add version parameter resolution for platform defaults"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### Task 2: Add macOS branch with micro installation
|
|
77
|
+
|
|
78
|
+
**Files:**
|
|
79
|
+
- Modify: `src/just/installers/edit/installer.py`
|
|
80
|
+
|
|
81
|
+
- [ ] **Step 1: Add macOS platform branch**
|
|
82
|
+
|
|
83
|
+
Add the `elif just.system.platform == "darwin":` branch before the `else` clause:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
elif just.system.platform == "darwin":
|
|
87
|
+
# Install micro text editor for macOS
|
|
88
|
+
editor_name = "micro"
|
|
89
|
+
url = f"https://github.com/zyedidia/micro/releases/download/v{version}/micro-{version}-{just.system.arch}-darwin.tar.gz"
|
|
90
|
+
|
|
91
|
+
just.echo.info(f"Installing {editor_name} v{version} as the default editor...")
|
|
92
|
+
|
|
93
|
+
just.ArchiveInstaller(
|
|
94
|
+
url=url,
|
|
95
|
+
executables=["micro"],
|
|
96
|
+
name="micro",
|
|
97
|
+
).run()
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
- [ ] **Step 2: Add edit -> micro symlink creation**
|
|
101
|
+
|
|
102
|
+
After the `ArchiveInstaller().run()` call in the macOS branch, add symlink creation:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
# Create edit -> micro symlink for consistency
|
|
106
|
+
from just.core.installer.utils import create_symlink_or_wrapper
|
|
107
|
+
from just.core.config.utils import get_bin_dir
|
|
108
|
+
|
|
109
|
+
micro_path = get_bin_dir() / "micro"
|
|
110
|
+
create_symlink_or_wrapper(
|
|
111
|
+
target=micro_path,
|
|
112
|
+
link_dir=get_bin_dir(),
|
|
113
|
+
link_name="edit"
|
|
114
|
+
)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- [ ] **Step 3: Add info log for Windows/Linux branches**
|
|
118
|
+
|
|
119
|
+
Add `just.echo.info()` calls before `ArchiveInstaller().run()` in Windows and Linux branches:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
just.echo.info(f"Installing Microsoft Edit v{version} as the default editor...")
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
- [ ] **Step 4: Commit**
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
git add src/just/installers/edit/installer.py
|
|
129
|
+
git commit -m "feat(edit): add macOS support with micro editor"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
### Task 3: Update installer decorator check command
|
|
135
|
+
|
|
136
|
+
**Files:**
|
|
137
|
+
- Modify: `src/just/installers/edit/installer.py`
|
|
138
|
+
|
|
139
|
+
- [ ] **Step 1: Update check command for platform detection**
|
|
140
|
+
|
|
141
|
+
The current `@just.installer(check="edit -v")` won't work for macOS since we install micro first.
|
|
142
|
+
Update to use a dynamic check or remove the check parameter for now:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
@just.installer(check="edit --version") # Works for both after symlink is created
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Note: `micro --version` works, and after symlink `edit --version` will invoke micro.
|
|
149
|
+
|
|
150
|
+
- [ ] **Step 2: Commit**
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
git add src/just/installers/edit/installer.py
|
|
154
|
+
git commit -m "fix(edit): update check command to work with micro"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Chunk 2: Testing
|
|
160
|
+
|
|
161
|
+
### Task 4: Manual testing on macOS
|
|
162
|
+
|
|
163
|
+
**Files:**
|
|
164
|
+
- None (manual testing)
|
|
165
|
+
|
|
166
|
+
- [ ] **Step 1: Test macOS installation**
|
|
167
|
+
|
|
168
|
+
Run on macOS:
|
|
169
|
+
```bash
|
|
170
|
+
just install edit
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Expected output:
|
|
174
|
+
```
|
|
175
|
+
Installing micro v2.0.15 as the default editor...
|
|
176
|
+
...
|
|
177
|
+
Installing micro v2.0.15 as the default editor...
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
- [ ] **Step 2: Verify edit command works**
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
edit --version
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Expected: micro version output
|
|
187
|
+
|
|
188
|
+
- [ ] **Step 3: Verify symlink exists**
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
ls -la ~/.just/bin/edit
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Expected: symlink pointing to micro
|
|
195
|
+
|
|
196
|
+
- [ ] **Step 4: Test version override**
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
just install edit -v 2.0.14
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Expected: installs specified micro version
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### Task 5: Verify existing platforms unchanged
|
|
207
|
+
|
|
208
|
+
**Files:**
|
|
209
|
+
- None (manual testing on Windows/Linux)
|
|
210
|
+
|
|
211
|
+
- [ ] **Step 1: Test default behavior**
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
just install edit
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Expected: installs Microsoft Edit v1.2.0
|
|
218
|
+
|
|
219
|
+
- [ ] **Step 2: Test version override**
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
just install edit -v 1.1.0
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Expected: installs specified Microsoft Edit version
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Final State
|
|
230
|
+
|
|
231
|
+
After implementation, `just install edit` will:
|
|
232
|
+
|
|
233
|
+
| Platform | Editor | Default Version | Command Available |
|
|
234
|
+
|----------|--------|-----------------|-------------------|
|
|
235
|
+
| macOS | micro | 2.0.15 | `edit` (-> micro) |
|
|
236
|
+
| Windows | Microsoft Edit | 1.2.0 | `edit` |
|
|
237
|
+
| Linux | Microsoft Edit | 1.2.0 | `edit` |
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
+
from typing_extensions import Annotated
|
|
3
|
+
|
|
4
|
+
import typer
|
|
2
5
|
|
|
3
6
|
from just import just_cli, capture_exception
|
|
4
7
|
from just.tui.workspace import WorkspaceApp
|
|
@@ -7,12 +10,12 @@ from just.tui.workspace import WorkspaceApp
|
|
|
7
10
|
@just_cli.command(name="code")
|
|
8
11
|
@capture_exception
|
|
9
12
|
def workspace_command(
|
|
10
|
-
|
|
13
|
+
workdir: Annotated[str, typer.Argument(help="Working directory")] = ".",
|
|
11
14
|
):
|
|
12
15
|
"""
|
|
13
16
|
Open a VSCode-style workspace editor.
|
|
14
17
|
"""
|
|
15
|
-
workspace_path = Path(
|
|
18
|
+
workspace_path = Path(workdir).resolve()
|
|
16
19
|
if not workspace_path.exists():
|
|
17
20
|
print(f"Error: Path does not exist: {workspace_path}")
|
|
18
21
|
return
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import just
|
|
2
|
+
|
|
3
|
+
from just.core.installer.utils import create_symlink_or_wrapper
|
|
4
|
+
from just.core.config.utils import get_bin_dir
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@just.installer(check="edit -v")
|
|
8
|
+
def install_edit(
|
|
9
|
+
version: just.Annotated[
|
|
10
|
+
str, just.Option("-v", "--version", help="The version of Edit to install.")
|
|
11
|
+
] = None,
|
|
12
|
+
):
|
|
13
|
+
"""
|
|
14
|
+
Install a terminal text editor.
|
|
15
|
+
|
|
16
|
+
- Windows/Linux: Microsoft Edit
|
|
17
|
+
- macOS: micro (with 'edit' symlink)
|
|
18
|
+
"""
|
|
19
|
+
# Resolve default version based on platform
|
|
20
|
+
if version is None:
|
|
21
|
+
if just.system.platform == "darwin":
|
|
22
|
+
version = "2.0.15" # micro latest stable
|
|
23
|
+
else:
|
|
24
|
+
version = "1.2.0" # Microsoft Edit
|
|
25
|
+
|
|
26
|
+
if just.system.platform == "windows":
|
|
27
|
+
just.echo.info(f"Installing Microsoft Edit v{version} as the default editor...")
|
|
28
|
+
url = f"https://github.com/microsoft/edit/releases/download/v{version}/edit-{version}-{just.system.arch}-windows.zip"
|
|
29
|
+
just.ArchiveInstaller(
|
|
30
|
+
url=url,
|
|
31
|
+
executables=["edit.exe"],
|
|
32
|
+
name="edit",
|
|
33
|
+
).run()
|
|
34
|
+
elif just.system.platform == "linux":
|
|
35
|
+
just.echo.info(f"Installing Microsoft Edit v{version} as the default editor...")
|
|
36
|
+
url = f"https://github.com/microsoft/edit/releases/download/v{version}/edit-{version}-{just.system.arch}-linux-gnu.tar.zst"
|
|
37
|
+
just.ArchiveInstaller(
|
|
38
|
+
url,
|
|
39
|
+
executables=["edit"],
|
|
40
|
+
name="edit",
|
|
41
|
+
).run()
|
|
42
|
+
elif just.system.platform == "darwin":
|
|
43
|
+
# Install micro text editor for macOS
|
|
44
|
+
editor_name = "micro"
|
|
45
|
+
# Map architecture to micro's platform naming
|
|
46
|
+
micro_platform = "macos-arm64" if just.system.arch == "aarch64" else "osx"
|
|
47
|
+
url = f"https://github.com/micro-editor/micro/releases/download/v{version}/micro-{version}-{micro_platform}.tar.gz"
|
|
48
|
+
|
|
49
|
+
just.echo.info(f"Installing {editor_name} v{version} as the default editor...")
|
|
50
|
+
|
|
51
|
+
just.ArchiveInstaller(
|
|
52
|
+
url=url,
|
|
53
|
+
executables=["micro"],
|
|
54
|
+
name="micro",
|
|
55
|
+
).run()
|
|
56
|
+
|
|
57
|
+
# Create edit -> micro symlink for consistency
|
|
58
|
+
micro_path = get_bin_dir() / "micro"
|
|
59
|
+
|
|
60
|
+
# Verify micro was installed successfully before creating symlink
|
|
61
|
+
if not micro_path.exists():
|
|
62
|
+
raise RuntimeError(f"micro installation failed - executable not found at {micro_path}")
|
|
63
|
+
|
|
64
|
+
create_symlink_or_wrapper(
|
|
65
|
+
target=micro_path,
|
|
66
|
+
link_dir=get_bin_dir(),
|
|
67
|
+
link_name="edit"
|
|
68
|
+
)
|
|
69
|
+
else:
|
|
70
|
+
raise NotImplementedError(
|
|
71
|
+
f"No editor is available for {just.system.platform}."
|
|
72
|
+
)
|
|
@@ -1,12 +1,106 @@
|
|
|
1
1
|
"""Minimal workspace editor with file tree and editor"""
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
from typing import Iterable
|
|
4
5
|
|
|
5
6
|
from textual.app import App, ComposeResult
|
|
6
7
|
from textual.binding import Binding
|
|
7
8
|
from textual.containers import Horizontal, Vertical
|
|
8
9
|
from textual.screen import ModalScreen
|
|
9
|
-
from textual.widgets import DirectoryTree, TextArea, Input, Button, Label
|
|
10
|
+
from textual.widgets import DirectoryTree, TextArea, Input, Button, Label, Footer
|
|
11
|
+
from rich.text import Text
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class IconDirectoryTree(DirectoryTree):
|
|
15
|
+
"""DirectoryTree with custom file type icons."""
|
|
16
|
+
|
|
17
|
+
# File icon mapping by extension
|
|
18
|
+
FILE_ICONS: dict[str, str] = {
|
|
19
|
+
# Python
|
|
20
|
+
".py": "🐍",
|
|
21
|
+
# JavaScript/TypeScript
|
|
22
|
+
".js": "📜",
|
|
23
|
+
".ts": "📜",
|
|
24
|
+
".jsx": "📜",
|
|
25
|
+
".tsx": "📜",
|
|
26
|
+
# Config files
|
|
27
|
+
".json": "⚙️",
|
|
28
|
+
".yaml": "⚙️",
|
|
29
|
+
".yml": "⚙️",
|
|
30
|
+
".toml": "⚙️",
|
|
31
|
+
".xml": "⚙️",
|
|
32
|
+
".ini": "⚙️",
|
|
33
|
+
".conf": "⚙️",
|
|
34
|
+
".cfg": "⚙️",
|
|
35
|
+
# Markdown
|
|
36
|
+
".md": "📝",
|
|
37
|
+
".markdown": "📝",
|
|
38
|
+
# Text
|
|
39
|
+
".txt": "📄",
|
|
40
|
+
# Styles
|
|
41
|
+
".css": "🎨",
|
|
42
|
+
".scss": "🎨",
|
|
43
|
+
".sass": "🎨",
|
|
44
|
+
".less": "🎨",
|
|
45
|
+
# HTML
|
|
46
|
+
".html": "🌐",
|
|
47
|
+
".htm": "🌐",
|
|
48
|
+
# Shell
|
|
49
|
+
".sh": "🖥️",
|
|
50
|
+
".bash": "🖥️",
|
|
51
|
+
".zsh": "🖥️",
|
|
52
|
+
".fish": "🖥️",
|
|
53
|
+
# Rust
|
|
54
|
+
".rs": "🦀",
|
|
55
|
+
# Go
|
|
56
|
+
".go": "🐹",
|
|
57
|
+
# Java
|
|
58
|
+
".java": "☕",
|
|
59
|
+
# C/C++
|
|
60
|
+
".c": "🏗️",
|
|
61
|
+
".cpp": "🏗️",
|
|
62
|
+
".h": "🏗️",
|
|
63
|
+
".hpp": "🏗️",
|
|
64
|
+
".cc": "🏗️",
|
|
65
|
+
".cxx": "🏗️",
|
|
66
|
+
# Other common files
|
|
67
|
+
".lock": "🔒",
|
|
68
|
+
".gitignore": "🙈",
|
|
69
|
+
".env": "🔐",
|
|
70
|
+
"dockerfile": "🐳",
|
|
71
|
+
"dockerignore": "🐳",
|
|
72
|
+
"makefile": "🛠️",
|
|
73
|
+
# Fallback
|
|
74
|
+
"": "📄",
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
def render_label(
|
|
78
|
+
self, node, base_style: str, style: str
|
|
79
|
+
) -> Text:
|
|
80
|
+
"""Render label with custom icon based on file extension."""
|
|
81
|
+
if node.data is None:
|
|
82
|
+
return Text("")
|
|
83
|
+
|
|
84
|
+
# node.data is DirEntry, which has a path attribute
|
|
85
|
+
entry = node.data
|
|
86
|
+
path = entry.path
|
|
87
|
+
|
|
88
|
+
if path.is_dir():
|
|
89
|
+
# Folder icon
|
|
90
|
+
return Text(f"📁 {path.name}")
|
|
91
|
+
|
|
92
|
+
# Get file extension
|
|
93
|
+
ext = path.suffix.lower()
|
|
94
|
+
name_lower = path.name.lower()
|
|
95
|
+
|
|
96
|
+
# Check for special files by name
|
|
97
|
+
if name_lower in self.FILE_ICONS:
|
|
98
|
+
icon = self.FILE_ICONS[name_lower]
|
|
99
|
+
else:
|
|
100
|
+
# Check by extension
|
|
101
|
+
icon = self.FILE_ICONS.get(ext, self.FILE_ICONS[""])
|
|
102
|
+
|
|
103
|
+
return Text(f"{icon} {path.name}")
|
|
10
104
|
|
|
11
105
|
|
|
12
106
|
class InputDialog(ModalScreen[str]):
|
|
@@ -160,8 +254,8 @@ class WorkspaceApp(App):
|
|
|
160
254
|
BINDINGS = [
|
|
161
255
|
Binding("ctrl+s", "save", "Save"),
|
|
162
256
|
Binding("ctrl+n", "new", "New"),
|
|
163
|
-
Binding("d", "delete", "Delete"),
|
|
164
|
-
Binding("
|
|
257
|
+
Binding("ctrl+d", "delete", "Delete"),
|
|
258
|
+
Binding("escape", "quit", "ESC"),
|
|
165
259
|
]
|
|
166
260
|
|
|
167
261
|
def __init__(self, path: str = "."):
|
|
@@ -172,8 +266,9 @@ class WorkspaceApp(App):
|
|
|
172
266
|
def compose(self) -> ComposeResult:
|
|
173
267
|
with Horizontal():
|
|
174
268
|
with Vertical(id="sidebar"):
|
|
175
|
-
yield
|
|
269
|
+
yield IconDirectoryTree(self.workspace_path)
|
|
176
270
|
yield CodeEditor(Path("/dev/null"), id="editor")
|
|
271
|
+
yield Footer()
|
|
177
272
|
|
|
178
273
|
def on_mount(self) -> None:
|
|
179
274
|
self.title = str(self.workspace_path)
|
|
@@ -201,13 +296,11 @@ class WorkspaceApp(App):
|
|
|
201
296
|
def _create_note(self, name: str) -> None:
|
|
202
297
|
if not name:
|
|
203
298
|
return
|
|
204
|
-
if not name.endswith(".md"):
|
|
205
|
-
name += ".md"
|
|
206
299
|
file_path = self.workspace_path / name
|
|
207
300
|
if file_path.exists():
|
|
208
301
|
self.notify("File already exists", severity="error")
|
|
209
302
|
return
|
|
210
|
-
file_path.write_text(
|
|
303
|
+
file_path.write_text("", encoding="utf-8")
|
|
211
304
|
self._refresh_tree()
|
|
212
305
|
self._open_file(file_path)
|
|
213
306
|
|
|
@@ -233,7 +326,7 @@ class WorkspaceApp(App):
|
|
|
233
326
|
self.notify("Deleted")
|
|
234
327
|
|
|
235
328
|
def _refresh_tree(self) -> None:
|
|
236
|
-
tree = self.query_one(
|
|
329
|
+
tree = self.query_one(IconDirectoryTree)
|
|
237
330
|
tree.reload()
|
|
238
331
|
|
|
239
332
|
def _open_file(self, file_path: Path) -> None:
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import just
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
@just.installer(check="edit -v")
|
|
5
|
-
def install_edit(
|
|
6
|
-
version: just.Annotated[
|
|
7
|
-
str, just.Option("-v", "--version", help="The version of Edit to install.")
|
|
8
|
-
] = "1.2.0",
|
|
9
|
-
):
|
|
10
|
-
"""
|
|
11
|
-
Install Microsoft Edit.
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
if just.system.platform == "windows":
|
|
15
|
-
url = f"https://github.com/microsoft/edit/releases/download/v{version}/edit-{version}-{just.system.arch}-windows.zip"
|
|
16
|
-
just.ArchiveInstaller(
|
|
17
|
-
url=url,
|
|
18
|
-
executables=["edit.exe"],
|
|
19
|
-
name="edit",
|
|
20
|
-
).run()
|
|
21
|
-
elif just.system.platform == "linux":
|
|
22
|
-
url = f"https://github.com/microsoft/edit/releases/download/v{version}/edit-{version}-{just.system.arch}-linux-gnu.tar.zst"
|
|
23
|
-
just.ArchiveInstaller(
|
|
24
|
-
url,
|
|
25
|
-
executables=["edit"],
|
|
26
|
-
name="edit",
|
|
27
|
-
).run()
|
|
28
|
-
else:
|
|
29
|
-
raise NotImplementedError(
|
|
30
|
-
f"Microsoft Edit is not supported on {just.system.platform}."
|
|
31
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|