wip: feat: workspace tmux remove
This commit is contained in:
parent
e2d11a7ea4
commit
7ec81ffdc7
3 changed files with 118 additions and 51 deletions
2
justfile
2
justfile
|
|
@ -3,5 +3,5 @@ format:
|
||||||
uv run ruff format .
|
uv run ruff format .
|
||||||
|
|
||||||
check:
|
check:
|
||||||
uv run ruff check .
|
uv run ruff check . --fix
|
||||||
uv run ty check .
|
uv run ty check .
|
||||||
|
|
|
||||||
|
|
@ -31,3 +31,66 @@ dev = [
|
||||||
|
|
||||||
[tool.ruff.lint.isort]
|
[tool.ruff.lint.isort]
|
||||||
force-single-line = true
|
force-single-line = true
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
target-version = "py312"
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
ignore = [
|
||||||
|
"E501",
|
||||||
|
"COM812", # flake8-commas
|
||||||
|
]
|
||||||
|
select = [
|
||||||
|
"F", # Pyflakes
|
||||||
|
"E", # Error
|
||||||
|
"W", # Warning
|
||||||
|
# "C90", # mccabe
|
||||||
|
"I", # isort
|
||||||
|
"N", # pep8-naming
|
||||||
|
# "D", # pydocstyle
|
||||||
|
# "UP", # pyupgrade
|
||||||
|
"YTT", # flake8-2020
|
||||||
|
# "ANN", # flake8-annotations
|
||||||
|
# "S", # flake8-bandit
|
||||||
|
# "BLE", # flake8-blind-except
|
||||||
|
# "FBT", # flake8-boolean-trap
|
||||||
|
"B", # flake8-bugbear
|
||||||
|
"A", # flake8-builtins
|
||||||
|
"COM", # flake8-commas
|
||||||
|
"C4", # flake8-comprehensions
|
||||||
|
"DTZ", # flake8-datetimez
|
||||||
|
"T10", # flake8-debugger
|
||||||
|
"DJ", # flake8-django
|
||||||
|
"EM", # flake8-errmsg
|
||||||
|
"EXE", # flake8-executable
|
||||||
|
"ISC", # flake8-implicit-str-concat
|
||||||
|
"ICN", # flake8-import-conventions
|
||||||
|
"G", # flake8-logging-format
|
||||||
|
# "INP", # flake8-no-pep420
|
||||||
|
"PIE", # flake8-pie
|
||||||
|
"T20", # flake8-print
|
||||||
|
"PYI", # flake8-pyi
|
||||||
|
"PT", # flake8-pytest-style
|
||||||
|
"Q", # flake8-quotes
|
||||||
|
"RSE", # flake8-raise
|
||||||
|
"RET", # flake8-return
|
||||||
|
# "SLF", # flake8-self
|
||||||
|
# "SIM", # flake8-simplify
|
||||||
|
"TID", # flake8-tidy-imports
|
||||||
|
"TCH", # flake8-type-checking
|
||||||
|
# "INT", # flake8-gettext
|
||||||
|
# "ARG", # flake8-unused-arguments
|
||||||
|
"PTH", # flake8-use-pathlib
|
||||||
|
# "ERA", # eradicate
|
||||||
|
"PD", # pandas-vet
|
||||||
|
"PGH", # pygrep-hooks
|
||||||
|
# "PL", # Pylint
|
||||||
|
# "PLC", # Convention
|
||||||
|
"PLE", # Error
|
||||||
|
# "PLR", # Refactor
|
||||||
|
"PLW", # Warning
|
||||||
|
# "TRY", # tryceratops
|
||||||
|
"NPY", # NumPy-specific rules
|
||||||
|
# "RUF", # Ruff-specific rules
|
||||||
|
]
|
||||||
|
|
||||||
|
|
|
||||||
104
workspaces.py
104
workspaces.py
|
|
@ -11,25 +11,28 @@
|
||||||
# ///
|
# ///
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional, Tuple
|
from typing import List
|
||||||
|
from typing import Optional
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
import typer
|
import typer
|
||||||
|
|
||||||
from pydantic import Field
|
|
||||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
||||||
from rich.console import Console
|
|
||||||
from rich.table import Table
|
|
||||||
from rich.prompt import Prompt, Confirm
|
|
||||||
from rich.syntax import Syntax
|
|
||||||
from rich.panel import Panel
|
|
||||||
from iterfzf import iterfzf
|
from iterfzf import iterfzf
|
||||||
|
from pydantic import Field
|
||||||
|
from pydantic_settings import BaseSettings
|
||||||
|
from pydantic_settings import SettingsConfigDict
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.panel import Panel
|
||||||
|
from rich.prompt import Confirm
|
||||||
|
from rich.prompt import Prompt
|
||||||
|
from rich.syntax import Syntax
|
||||||
|
from rich.table import Table
|
||||||
|
|
||||||
app = typer.Typer(
|
app = typer.Typer(
|
||||||
help="Workspace management tool",
|
help="Workspace management tool",
|
||||||
|
|
@ -94,8 +97,8 @@ def resolve_paths(workspaces_name: Optional[str]) -> Tuple[Settings, Path, Path]
|
||||||
"""
|
"""
|
||||||
base_settings = Settings.from_env_and_override(workspaces_name)
|
base_settings = Settings.from_env_and_override(workspaces_name)
|
||||||
name = base_settings.workspaces_name
|
name = base_settings.workspaces_name
|
||||||
repos_dir = Path(os.path.expanduser(f"~/{name}")).resolve()
|
repos_dir = Path(f"~/{name}").expanduser().resolve()
|
||||||
workspaces_dir = Path(os.path.expanduser(f"~/{name}.workspaces")).resolve()
|
workspaces_dir = Path(f"~/{name}.workspaces").expanduser().resolve()
|
||||||
return base_settings, repos_dir, workspaces_dir
|
return base_settings, repos_dir, workspaces_dir
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -209,17 +212,17 @@ def find_workspace_dir(workspaces_dir: Path, workspace_name: Optional[str]) -> P
|
||||||
cwd = Path.cwd().resolve()
|
cwd = Path.cwd().resolve()
|
||||||
try:
|
try:
|
||||||
cwd.relative_to(workspaces_dir)
|
cwd.relative_to(workspaces_dir)
|
||||||
except ValueError:
|
except ValueError as e:
|
||||||
workspace_root = pick_workspace_with_iterfzf(list_workspaces(workspaces_dir))
|
workspace_root = pick_workspace_with_iterfzf(list_workspaces(workspaces_dir))
|
||||||
if workspace_root is None:
|
if workspace_root is None:
|
||||||
console.print("[red]No workspace selected. Exiting.[/red]")
|
console.print("[red]No workspace selected. Exiting.[/red]")
|
||||||
raise typer.Exit(code=1)
|
raise typer.Exit(code=1) from e
|
||||||
return workspace_root
|
return workspace_root
|
||||||
|
|
||||||
# The top-level workspace directory is the first component under workspaces_dir
|
# The top-level workspace directory is the first component under workspaces_dir
|
||||||
rel = cwd.relative_to(workspaces_dir)
|
rel = cwd.relative_to(workspaces_dir)
|
||||||
workspace_root = workspaces_dir / rel.parts[0]
|
workspace_root = workspaces_dir / rel.parts[0]
|
||||||
print(f"Using workspace: {workspace_root}")
|
console.print(f"Using workspace: {workspace_root}")
|
||||||
return workspace_root
|
return workspace_root
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1394,6 +1397,7 @@ def pick_project(base_dir: Path) -> Optional[str]:
|
||||||
["fzf", "--reverse", f"--header=Select project from {base_dir.name} >"],
|
["fzf", "--reverse", f"--header=Select project from {base_dir.name} >"],
|
||||||
input="\n".join(subdirs),
|
input="\n".join(subdirs),
|
||||||
text=True,
|
text=True,
|
||||||
|
check=False,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -1423,41 +1427,40 @@ def create_detached_session(
|
||||||
clear_tmux_env=True,
|
clear_tmux_env=True,
|
||||||
)
|
)
|
||||||
return r.returncode == 0
|
return r.returncode == 0
|
||||||
else:
|
r = run_tmux(
|
||||||
r = run_tmux(
|
["new-session", "-Ad", "-s", session_name, "-c", str(path_name)],
|
||||||
["new-session", "-Ad", "-s", session_name, "-c", str(path_name)],
|
clear_tmux_env=True,
|
||||||
clear_tmux_env=True,
|
)
|
||||||
)
|
if r.returncode != 0:
|
||||||
if r.returncode != 0:
|
return False
|
||||||
return False
|
|
||||||
|
|
||||||
r = run_tmux(
|
r = run_tmux(
|
||||||
[
|
[
|
||||||
"split-window",
|
"split-window",
|
||||||
"-vb",
|
"-vb",
|
||||||
"-t",
|
"-t",
|
||||||
session_name,
|
session_name,
|
||||||
"-c",
|
"-c",
|
||||||
str(path_name),
|
str(path_name),
|
||||||
"-p",
|
"-p",
|
||||||
"70",
|
"70",
|
||||||
],
|
],
|
||||||
clear_tmux_env=True,
|
clear_tmux_env=True,
|
||||||
)
|
)
|
||||||
if r.returncode != 0:
|
if r.returncode != 0:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
r = run_tmux(
|
r = run_tmux(
|
||||||
[
|
[
|
||||||
"send-keys",
|
"send-keys",
|
||||||
"-t",
|
"-t",
|
||||||
session_name,
|
session_name,
|
||||||
"nvim '+Telescope find_files'",
|
"nvim '+Telescope find_files'",
|
||||||
"Enter",
|
"Enter",
|
||||||
],
|
],
|
||||||
clear_tmux_env=True,
|
clear_tmux_env=True,
|
||||||
)
|
)
|
||||||
return r.returncode == 0
|
return r.returncode == 0
|
||||||
|
|
||||||
|
|
||||||
def create_if_needed_and_attach(
|
def create_if_needed_and_attach(
|
||||||
|
|
@ -1494,6 +1497,7 @@ def attach_to_first_session() -> None:
|
||||||
list_proc = subprocess.run(
|
list_proc = subprocess.run(
|
||||||
["tmux", "list-sessions", "-F", "#{session_name}"],
|
["tmux", "list-sessions", "-F", "#{session_name}"],
|
||||||
text=True,
|
text=True,
|
||||||
|
check=False,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
)
|
)
|
||||||
if list_proc.returncode != 0 or not list_proc.stdout.strip():
|
if list_proc.returncode != 0 or not list_proc.stdout.strip():
|
||||||
|
|
@ -1552,12 +1556,12 @@ def tmux_cli_attach(
|
||||||
console.print(f"[red]Workspace '{workspace}' does not exist at {ws_dir}[/red]")
|
console.print(f"[red]Workspace '{workspace}' does not exist at {ws_dir}[/red]")
|
||||||
raise typer.Exit(1)
|
raise typer.Exit(1)
|
||||||
# pick repo in workspace
|
# pick repo in workspace
|
||||||
repo = pick_repo_with_iterfzf([dir for dir in ws_dir.iterdir() if dir.is_dir()])
|
repo = pick_repo_with_iterfzf([directory for directory in ws_dir.iterdir() if directory.is_dir()])
|
||||||
if not repo:
|
if not repo:
|
||||||
console.print("[red]No repo selected. Exiting.[/red]")
|
console.print("[red]No repo selected. Exiting.[/red]")
|
||||||
raise typer.Exit(1)
|
raise typer.Exit(1)
|
||||||
session_name = f"ω|{ws_dir.name}|{repo.name}"
|
session_name = f"ω|{ws_dir.name}|{repo.name}"
|
||||||
print(f"Session name: {session_name}")
|
console.print(f"Session name: {session_name}")
|
||||||
create_if_needed_and_attach(session_name, repo, False)
|
create_if_needed_and_attach(session_name, repo, False)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue