Skip to content

Commit e0a276b

Browse files
authored
refactor: providers for terminal operations (#23)
* refactor: providers for terminal operations * fix: resolve symlink paths in InplaceProvider test for macOS * docs: update latest info
1 parent 5a4d602 commit e0a276b

18 files changed

Lines changed: 1543 additions & 425 deletions

docs/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Controls how `hypr` interacts with your terminal.
4444

4545
| Key | Type | Default | Description |
4646
| ------------ | ------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
47-
| `mode` | string | `"tab"` | Determines how `hypr` opens worktrees. <br> • `tab`: Open in a new tab (default). <br> • `window`: Open in a new window. <br> • `inplace`: Switch the current terminal to the worktree directory. <br> • `echo`: Output shell commands to stdout. <br> **ENV**: `HYPR_TERMINAL_MODE` <br> **CLI**: `--terminal <mode>` |
47+
| `mode` | string | `"window"` | Determines how `hypr` opens worktrees. <br> • `window`: Open in a new window (default). <br> • `tab`: Open in a new tab. <br> • `inplace`: Switch the current terminal to the worktree directory. <br> • `echo`: Output shell commands to stdout. <br> **ENV**: `HYPR_TERMINAL_MODE` <br> **CLI**: `--terminal <mode>` |
4848
| `always_new` | boolean | `false` | If `true`, always creates a new terminal session instead of switching to an existing one for a worktree. <br> **ENV**: `HYPR_TERMINAL_ALWAYS_NEW` <br> **CLI**: `--ignore-same-session` |
4949
| `program` | string | `null` | Force `hypr` to use a specific terminal program instead of auto-detecting one. <br> _Examples: `iterm2`, `terminal`, `tmux`_ <br> **ENV**: `HYPR_TERMINAL_PROGRAM` |
5050

docs/gettingstarted.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,35 @@ This guide will walk you through installing `hypr`, setting it up for a project,
66

77
Before you begin, make sure you have the following installed:
88

9-
- **Python 3.10+**: You can check your version with `python3 --version`.
10-
- **Git 2.5+**: `hypr` relies on modern git worktree functionality. Check your version with `git --version`. Git 2.5 was released in 2015, so this shouldn’t be a problem.
9+
- **Git 2.5+**: `hypr` relies on modern git worktree functionality. Check your version with `git --version`. Git 2.5 was released in 2015, so this shouldn't be a problem.
1110
- **A supported terminal (recommended)**: For the best experience, use a terminal with good tab and window management, like iTerm2 on macOS. See the [Terminal Support](terminalsupport.md) page for more details.
1211

1312
## Installation
1413

15-
### Pip
14+
### Homebrew (macOS)
1615

17-
First, `pip install hypr`. To verify the installation, run `hypr` in a git repository to see its status:
16+
```bash
17+
brew install stephanvs/tap/hypr
18+
```
19+
20+
### Scoop (Windows)
21+
22+
```bash
23+
scoop bucket add hypr https://github.com/Stephanvs/hypr
24+
scoop install hypr
25+
```
26+
27+
### AUR (Arch Linux)
28+
29+
```bash
30+
yay -S hypr-bin
31+
```
32+
33+
### Manual Download
34+
35+
Download the latest release for your platform from [GitHub Releases](https://github.com/Stephanvs/hypr/releases).
36+
37+
To verify the installation, run `hypr` in a git repository to see its status:
1838

1939
```txt
2040
Worktrees:

docs/terminalsupport.md

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,40 @@
22

33
## hypr automates your terminal by default
44

5-
`hypr`'s intended user experience is that it will open terminal tabs on your behalf. It uses [`automate-terminal`](https://github.com/irskep/automate-terminal) to accomplish this, so check that project out to find out if your terminal is supported.
5+
`hypr`'s intended user experience is that it will open terminal tabs or windows on your behalf. It natively supports the following terminals:
6+
7+
### macOS
8+
9+
- **iTerm2** - Full tab and window support
10+
- **Terminal.app** - Full tab and window support
11+
- **tmux** - When running inside a tmux session
12+
13+
### Windows
14+
15+
- **Windows Terminal** - Full tab and window support
16+
17+
### Linux
18+
19+
- **GNOME Terminal** - Full tab and window support
20+
- **tmux** - When running inside a tmux session
21+
22+
### All Platforms
23+
24+
- **VS Code** - Opens worktrees in VS Code (`--terminal=vscode`)
25+
- **Cursor** - Opens worktrees in Cursor (`--terminal=cursor`)
626

727
## What to do if your terminal isn't supported or you don't want this behavior
828

9-
Add this to your `.hypr.toml` or set it at the user level with `hypr config`:
29+
Add this to your `.hypr.json` or set it at the user level with `hypr config`:
1030

11-
```
12-
[terminal]
13-
mode = 'echo'
31+
```json
32+
{
33+
"Terminal": {
34+
"Mode": "echo"
35+
}
36+
}
1437
```
1538

1639
This will cause hypr to print commands to the console instead of having your terminal run them automatically. You can then manually run the printed commands to navigate to the worktree.
40+
41+
Alternatively, use `--terminal=inplace` to have hypr change the current terminal's directory directly.

src/Module.cs

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,73 @@
11
using Hypr.Configuration;
22
using Hypr.Hooks;
33
using Hypr.Services;
4+
using Hypr.Services.Terminals;
5+
using Hypr.Utils;
46
using Microsoft.Extensions.Configuration;
57
using Microsoft.Extensions.DependencyInjection;
68

79
namespace Hypr;
810

911
internal static class Module
1012
{
11-
internal static IServiceCollection AddServices(this IServiceCollection services, IConfiguration configuration) => services
12-
.Configure<TerminalConfig>(configuration.GetSection("terminal"))
13-
.Configure<WorktreeConfig>(configuration.GetSection("worktree"))
14-
.Configure<CleanupConfig>(configuration.GetSection("cleanup"))
15-
.Configure<ScriptsConfig>(configuration.GetSection("scripts"))
16-
.Configure<ConfirmationsConfig>(configuration.GetSection("confirmations"))
17-
.AddSingleton<StateService>()
18-
.AddSingleton<GitService>()
19-
.AddSingleton<GitHubService>()
20-
.AddSingleton<TerminalService>()
21-
.AddSingleton<VersionCheckService>()
22-
.AddSingleton<HookRunner>();
13+
internal static IServiceCollection AddServices(this IServiceCollection services, IConfiguration configuration) => services
14+
.Configure<TerminalConfig>(configuration.GetSection("terminal"))
15+
.Configure<WorktreeConfig>(configuration.GetSection("worktree"))
16+
.Configure<CleanupConfig>(configuration.GetSection("cleanup"))
17+
.Configure<ScriptsConfig>(configuration.GetSection("scripts"))
18+
.Configure<ConfirmationsConfig>(configuration.GetSection("confirmations"))
19+
.AddSingleton<StateService>()
20+
.AddSingleton<GitService>()
21+
.AddSingleton<GitHubService>()
22+
.AddSingleton<TerminalService>()
23+
.AddSingleton<VersionCheckService>()
24+
.AddSingleton<HookRunner>()
25+
.AddTerminalProviders();
26+
27+
private static IServiceCollection AddTerminalProviders(this IServiceCollection services)
28+
{
29+
var currentPlatform = GetCurrentPlatform();
30+
31+
// Use Scrutor to scan and register all terminal providers that support the current platform
32+
services.Scan(scan => scan
33+
.FromAssemblyOf<ITerminalProvider>()
34+
.AddClasses(classes => classes
35+
.AssignableTo<ITerminalProvider>()
36+
.Where(type => SupportsCurrentPlatform(type, currentPlatform)))
37+
.AsImplementedInterfaces()
38+
.WithSingletonLifetime());
39+
40+
return services;
41+
}
42+
43+
private static Platform GetCurrentPlatform()
44+
{
45+
if (PlatformUtils.IsWindows) return Platform.Windows;
46+
if (PlatformUtils.IsMacOS) return Platform.MacOS;
47+
if (PlatformUtils.IsLinux) return Platform.Linux;
48+
return Platform.None;
49+
}
50+
51+
private static bool SupportsCurrentPlatform(Type providerType, Platform currentPlatform)
52+
{
53+
return GetSupportedPlatformsForType(providerType).HasFlag(currentPlatform);
54+
}
55+
56+
private static Platform GetSupportedPlatformsForType(Type providerType)
57+
{
58+
// Map known provider types to their supported platforms
59+
return providerType.Name switch
60+
{
61+
nameof(WindowsTerminalProvider) => Platform.Windows,
62+
nameof(ITerm2Provider) => Platform.MacOS,
63+
nameof(TerminalAppProvider) => Platform.MacOS,
64+
nameof(GnomeTerminalProvider) => Platform.Linux,
65+
nameof(TmuxProvider) => Platform.Linux | Platform.MacOS,
66+
nameof(VSCodeProvider) => Platform.All,
67+
nameof(CursorProvider) => Platform.All,
68+
nameof(EchoProvider) => Platform.All,
69+
nameof(InplaceProvider) => Platform.All,
70+
_ => Platform.None
71+
};
72+
}
2373
}

0 commit comments

Comments
 (0)