Skip to content

Commit

Permalink
Merge branch 'release/0.2.0' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
chvolkmann committed Feb 15, 2021
2 parents 6204af8 + d39db23 commit 4836d15
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 199 deletions.
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.2.0] - 2021-02-15

### Changed

- `source` was used to make `code` available through `code_connect.py`, which only output a shell string.

Now, `code_connect.py` is a direct wrapper around `code` and calls it as a subprocess. Thus, `code_connect.py` can ne be used as an alias for `code`. No need to `activate` anything first.

- Scanning for a valid IPC socket is now done any time `code` is called.

### Fixed

- `code` doesn't use stale IPC sockets anymore.

## [0.1.1] - 2021-02-14

### Fixed
Expand All @@ -19,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Initial release of `code-connect` and the corresponding fish plugin

[unreleased]: https://github.com/chvolkmann/code-connect/compare/v0.1.1...HEAD
[unreleased]: https://github.com/chvolkmann/code-connect/compare/v0.2.0...HEAD
[0.2.0]: https://github.com/chvolkmann/code-connect/compare/v0.1.1...v0.2.0
[0.1.1]: https://github.com/chvolkmann/code-connect/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/chvolkmann/code-connect/releases/tag/v0.1.0
81 changes: 17 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@ Open a file in your locally running Visual Studio Code instance from arbitrary t

## Motivation

VS Code supports opening files with the terminal using `code /path/to/file`. While this is possible in [WSL sessions](https://code.visualstudio.com/docs/remote/wsl) and [remote SSH sessions](https://code.visualstudio.com/docs/remote/ssh) if the integrated terminal is used, it is currently not possible for arbitrary terminals.
VS Code supports opening files with the terminal using `code /path/to/file`. While this is possible in [WSL sessions](https://code.visualstudio.com/docs/remote/wsl) and [remote SSH sessions](https://code.visualstudio.com/docs/remote/ssh) if the integrated terminal is used, it is currently not possible for arbitrary terminal sessions.

Say, you have just SSH'd into a remote server using your favorite terminal and would like to open a webserver config file in your local VS Code instance. So you type `code nginx.conf`, which doesn't work in this terminal. If you try to run `code nginx.conf` in the integrated terminal however, VS Code opens it the file just fine.

The aim of this project is to make the `code` cli available to _any_ terminal, not only to VS Code's integrated terminal.

## Installation
## Prerequisites

### Prerequisites
- **Linux** - we make assumptions on where VS Code stores it data based on Linux

> Macs could also support everything out of the box, confirmation needed. Please don't hesitate to come into contact if you have any information to share.
- a **Linux machine** you want to run `code-connect` on
- **Python 3** - _tested under Python 3.8, but slightly older versions should work fine_
- **socat** - used for pinging UNIX sockets
```bash
Expand All @@ -26,63 +27,27 @@ The aim of this project is to make the `code` cli available to _any_ terminal, n
You need to set up VS Code Server before using this utility. For this, [connect to your target in a remote SSH session](https://code.visualstudio.com/docs/remote/ssh).
Afterwards, you should have a folder `.vscode-server` in your home directory.

### Shell Integration

If you are familiar with `virtualenv`, `conda`, etc., this will be familiar.

#### Bash

Execute this and place it in your `.bashrc`

```bash
source activate.sh
```

#### Fish

Fish users can alternatively install an accompanying [fish plugin](https://github.com/chvolkmann/code-connect-fish-plugin).

```fish
fisher install chvolkmann/code-connect-fish-plugin
```

If you want to do it manually, execute this and place it in your `config.fish`

```fish
source activate.fish
```

## Usage

First, run
Set up an alias for `code`, pointing to `code_connect.py` by placing the following line in your shell's rcfile. That's it, you can now use `code` the usual way.

```bash
code-connect
alias code="/path/to/code_connect.py"
```

This will provide you with the `code` command from your server's VS Code Server installation. It also sets the environment variable `VSCODE_IPC_HOOK_CLI` to a valid IPC socket.

Then you're free to use

```bash
code /path/to/file
```
- For **bash**, use `~/.bashrc`.

Note that you need to have an active instance of VS Code running.
- For **fish**, use `~/.config/fish/config.fish`.

### Deactivating
Fish users can alternatively install a [plugin](https://github.com/chvolkmann/code-connect-fish-plugin) with the [fisher plugin manager](https://github.com/jorgebucaran/fisher).

To unlink the `code` executable and unset the environment variable, use

```bash
code-disconnect
```
```bash
fisher install chvolkmann/code-connect-fish-plugin
```

And to disable `code-connect` and unset the aliases, use
## Changelog

```bash
deactivate
```
See [CHANGELOG.md](./CHANGELOG.md)

## How it works

Expand Down Expand Up @@ -115,16 +80,8 @@ socat -u OPEN:/dev/null UNIX-CONNECT:/path/to/socket

This returns `0` if and only if there's something listening.

The script `code_connect.py` does all of the above steps and outputs a string to stdout. Currently, output for **bash** and **fish** is supported.

Sample output (bash):

```bash
export VSCODE_IPC_HOOK_CLI="/run/user/1000/vscode-ipc-dd85cff3-04c7-4ca6-9c06-229acd73008c.sock"
alias code="/home/user/.vscode-server/bin/622cb03f7e070a9670c94bae1a45d78d7181fbd4/bin/code"
```

`code-connect` is an alias sourcing the output of `code_connect.py` into the current shell session.
The script `code_connect.py` performs all of the above steps and runs the VS Code `code` executable
as a child process with `VSCODE_IPC_HOOK_CLI` set properly.

## [Contributing](./CONTRIBUTING.md)

Expand All @@ -133,10 +90,6 @@ alias code="/home/user/.vscode-server/bin/622cb03f7e070a9670c94bae1a45d78d7181fb
- Create a pull request
_Please make sure that [edits to your pull request are permitted](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork)._

## Changelog

See [CHANGELOG.md](./CHANGELOG.md)

## Credit

- Based on an [answer on StackOverflow](https://stackoverflow.com/a/60949722) by [stabledog](https://stackoverflow.com/users/237059/Stabledog)
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.1
0.2.0
51 changes: 0 additions & 51 deletions activate.fish

This file was deleted.

50 changes: 0 additions & 50 deletions activate.sh

This file was deleted.

58 changes: 26 additions & 32 deletions code_connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from distutils.spawn import find_executable
from typing import Iterable, List, Tuple
from pathlib import Path
import sys

MAX_IDLE_TIME = 4 * 60 * 60

Expand Down Expand Up @@ -40,22 +41,12 @@ def next_open_socket(socks: Iterable[Path]) -> Path:
)

def check_for_binaries():
if find_executable('socat') is None:
if not find_executable('socat'):
fail(
'"socat" not found in $PATH, but is required for code-connect'
)

def main(shell: str = None, max_idle_time: int = MAX_IDLE_TIME):
check_for_binaries()

# Determine shell for outputting the proper format
if not shell:
shell = os.getenv('SHELL', 'bash')
shell_path = Path(shell)
if shell_path.exists():
# Just get the name of the binary
shell = shell_path.name

def get_code_binary() -> Path:
# Every entry in ~/.vscode-server/bin corresponds to a commit id
# Pick the most recent one
code_repos = sort_by_access_timestamp(Path.home().glob('.vscode-server/bin/*'))
Expand All @@ -68,11 +59,11 @@ def main(shell: str = None, max_idle_time: int = MAX_IDLE_TIME):
)

_, code_repo = code_repos[0]
return code_repo / 'bin' / 'code'

code_binary = code_repo / 'bin' / 'code'

def get_ipc_socket(max_idle_time: int = MAX_IDLE_TIME) -> Path:
# List all possible sockets for the current user
# Some of these are obsolete and not listening
# Some of these are obsolete and not actively listening anymore
uid = os.getuid()
socks = sort_by_access_timestamp(Path(f'/run/user/{uid}/').glob('vscode-ipc-*.sock'))

Expand All @@ -81,23 +72,26 @@ def main(shell: str = None, max_idle_time: int = MAX_IDLE_TIME):
socks = [sock for ts, sock in socks if now - ts <= max_idle_time]

# Find the first socket that is open, most recently accessed first
ipc_sock = next_open_socket(socks)

# Output a shell string to stdout
if shell == 'fish':
source_lines = [
f'# fish usage: ./code_connect.py | source',
f'export VSCODE_IPC_HOOK_CLI="{ipc_sock}"',
f'alias code="{code_binary}"'
]
else:
source_lines = [
f'# bash usage: ./code_connect.py | eval',
f'export VSCODE_IPC_HOOK_CLI="{ipc_sock}"',
f'alias code="{code_binary}"'
]

print('\n'.join(source_lines))
return next_open_socket(socks)

def main(max_idle_time: int = MAX_IDLE_TIME):
check_for_binaries()

# Fetch the path of the "code" executable
# and determine an active IPC socket to use
code_binary = get_code_binary()
ipc_socket = get_ipc_socket()

args = sys.argv.copy()
args[0] = str(code_binary)
os.environ['VSCODE_IPC_HOOK_CLI'] = str(ipc_socket)

# run the "code" executable with the proper environment variable set
# stdout/stderr remain connected to the current process
proc = sp.run(args)

# return the same exit code as the wrapped process
exit(proc.returncode)

if __name__ == '__main__':
main()

0 comments on commit 4836d15

Please sign in to comment.