Skip to content

Conversation

@ltratt
Copy link
Contributor

@ltratt ltratt commented Oct 22, 2025

This allows the command run to be passed context about which terminal the hint has been run from.

For example in my shell, I set the title of the terminal to:

[<user>@<host> <running command> <cwd>]

with:

chpwd() {
  [[ -t 1 ]] || return
  print -Pn "\e]2;[%n@%m %~]\a"
}

so whenever I change directory, the terminal title is changed.

When I click on a hint, that title is sent to the hint command. I then extract the cwd to find out what directory that terminal was in (replacing ~ with $HOME because %~ in the shell above pretty prints $HOME as ~:

term_dir=$(echo "$ALACRITTY_TERM_TITLE" | sed -E "s/.* (.*)\]/\\1/g" | sed -E "s|^~|${HOME}|g")

With that knowledge, I can then do things like drive different neovims based on $term_dir/.nvim_server. Specifically, I have a hint which matches file:line:col, so when I click on an error in a backtrace, the right neovim switches to file (at line:col), even if I have multiple neovims running in different directories across my machine. The script I execute (eliding boring details) looks roughly as follows:

term_dir=$(echo "$ALACRITTY_TERM_TITLE" | sed -E "s/.* (.*)\]/\\1/g" | sed -E "s|^~|${HOME}|g")
if [ -e "$term_dir/.nvim_server" ]; then
  cd $term_dir
  path=$(echo "$1" | cut -d ":" -f 1)
  line=$(echo "$1" | cut -d ":" -f 2)
  col=$(echo "$1" | cut -d ":" -f 3)
  nvim --server .nvim_server --remote-tab "${path}"
  nvim --server .nvim_server --remote-send ":call cursor(${line},${col})<CR>"
fi

This allows the command run to be passed context about which terminal
the hint has been run from.

For example in my shell, I set the title of the terminal to:

```
[<user>@<host> <running command> <cwd>]
```

with:

```
chpwd() {
  [[ -t 1 ]] || return
  print -Pn "\e]2;[%n@%m %~]\a"
}
```

so whenever I change directory, the terminal title is changed.

When I click on a hint, that title is sent to the hint command. I then
extract the cwd to find out what directory that terminal was in
(replacing `~` with `$HOME` because `%~` in the shell above pretty
prints `$HOME` as `~`:

```
term_dir=$(echo "$ALACRITTY_TERM_TITLE" | sed -E "s/.* (.*)\]/\\1/g" | sed -E "s|^~|${HOME}|g")
```

With that knowledge, I can then do things like drive different neovims
based on `$term_dir/.nvim_server`. Specifically, I have a hint which
matches `file:line:col`, so when I click on an error in a backtrace,
the right neovim switches to `file` (at `line:col`), even if I have
multiple neovims running in different directories across my machine.
The script I execute (eliding boring details) looks roughly as follows:

```
term_dir=$(echo "$ALACRITTY_TERM_TITLE" | sed -E "s/.* (.*)\]/\\1/g" | sed -E "s|^~|${HOME}|g")
if [ -e "$term_dir/.nvim_server" ]; then
  cd $term_dir
  path=$(echo "$1" | cut -d ":" -f 1)
  line=$(echo "$1" | cut -d ":" -f 2)
  col=$(echo "$1" | cut -d ":" -f 3)
  nvim --server .nvim_server --remote-tab "${path}"
  nvim --server .nvim_server --remote-send ":call cursor(${line},${col})<CR>"
fi
```
@chrisduerr chrisduerr closed this Oct 22, 2025
@ltratt
Copy link
Contributor Author

ltratt commented Oct 22, 2025

@chrisduerr Is there an alternative that might be acceptable? This does solve a real problem, as I hope I proved above: there is no problem with the fact that alacritty is in daemon mode. It really does work!

@chrisduerr
Copy link
Member

This is a poor solution even to your problem.

@ltratt
Copy link
Contributor Author

ltratt commented Oct 22, 2025

@chrisduerr I welcome your thoughts as to a better solution!

@nixpulvis
Copy link
Contributor

I think the idea of setting some environment variables to identify the run is reasonable. I don't think putting the alacritty title in the env is though. I'd say the window ID would be good, but I'm not sure there's a good cross platform value for that...

@ltratt
Copy link
Contributor Author

ltratt commented Oct 23, 2025

@nixpulvis For me, the window ID would be more than sufficient. It would obviously have some platform-specific aspect, though I don't know if every platform has a concept of "window ID"; still, I guess such platforms would probably have another notion that could be used?

As a possible alternative, could one invent -- I don't think the existing ones are sufficient -- a new OSC sequence that would be something like "set terminal ID" where the shell could tell the terminal how it wants to be identified? In my case, I would set that ID to the current directory every time it's changed.

@j4james
Copy link

j4james commented Oct 23, 2025

As a possible alternative, could one invent -- I don't think the existing ones are sufficient -- a new OSC sequence that would be something like "set terminal ID" where the shell could tell the terminal how it wants to be identified?

If a simple numeric ID is sufficient for your needs, there's an existing sequence for that. The Tertiary Device Attributes report (DA3) returns a "terminal unit ID", which is an 8-digit hex value. And there's a corresponding update sequence, Set Terminal Unit ID (DECSTUI), which you can use to set that value.

On the original hardware terminals the ID wasn't generally intended to be changed, so the value would typically have been locked. But nobody relies on it being a unique identifier anymore, so some modern terminals do allow it be set with DECSTUI.

@kchibisov
Copy link
Member

. I'd say the window ID would be good,

It's already set, see ALACRITTY_WINDOW_ID.

@ltratt
Copy link
Contributor Author

ltratt commented Oct 23, 2025

@j4james An 8 digit hex value would be fine, and I'd be fine generating random IDs, setting them, and leaving a cookie per-ID in a directory of my choosing! I admit that my DA skills are a bit lacking, so I might not have got quite the right shell code to query + print out the ID. It looks right now that all Alacritty windows from the same process might return the same DECRPTUI and I'm not sure DECSTUI is supported? I might be very wrong about both points. If you have a simple way of printing that ID I am all ears!

@ltratt
Copy link
Contributor Author

ltratt commented Oct 23, 2025

@kchibisov When I do set in the process run by a hint I only see the following variables: ALACRITTY_LOG, ALACRITTY_SOCKET, and ALACRITTY_TERM_TITLE= set. But you're right that within a shell I see ALACRITTY_WINDOW_ID set. So perhaps I should recast this PR to fish out the window ID -- not its title -- and set that env var? It would have the virtue of consistency!

@kchibisov
Copy link
Member

Yeah, it's a variable used for our IPC. it's not set for the process itself, since it's rather confusing and not really present for the process itself, however, it could be set for the spawn subcommand.

Though, I believe that you can not use this ID outside of alacritty msg. I guess if you have nvim running and you can pass ID to it, it'll inherit ALACRITTY_WINDOW_ID.

Though, adding ALACRITTY_WINDOW_ID into the env for spawns is absolutely fine if it's not there.

@ltratt
Copy link
Contributor Author

ltratt commented Oct 23, 2025

Based on @kchibisov's suggestion I have force pushed a commit to my branch (ltratt@097ffd8; I suppose it doesn't show up here while the PR is set as closed) which sets ALACRITTY_WINDOW_ID for hint commands. It does exactly what I need on Xorg with xprop -id "$ALACRITTY_WINDOW_ID" WM_NAME!

@kchibisov
Copy link
Member

It does exactly what I need on Xorg with xprop -id "$ALACRITTY_WINDOW_ID" WM_NAME!

Yeah, but won't work on Wayland really, but it's not like there's a reason to hide this variable especially if one could want to run IPC from the spawned shell.

@ltratt
Copy link
Contributor Author

ltratt commented Oct 23, 2025

@kchibisov Personally, I will probably move to a "cookie" approach where I have ~/somedir/<windowid> and I update that file every time I change directory rather than rely on xprop, but it's been enough to prove the point for me. Presumably Wayland does at least give a u64 windowid, at which point that approach would work fine (and, judging by the code I can see, it looks like this should work OK on Windows too; I'm unsure about OS X).

If ltratt@097ffd8 is acceptable to folk, how would you like to proceed. Reopen this PR or a new PR or ... ?

@kchibisov
Copy link
Member

I was saying that there's nothing similar to xprop + WINDOW_ID combo here on wayland, since window_id is not really a thing on wayland, we just use pointer for example of window.

@chrisduerr
Copy link
Member

Yeah, but won't work on Wayland really, but it's not like there's a reason to hide this variable especially if one could want to run IPC from the spawned shell.

While this is accurate, the motivation behind this patch is certainly much less sensible and reliable. This is not a good mechanism to communicate hint data to neovim.

@ltratt
Copy link
Contributor Author

ltratt commented Oct 23, 2025

@chrisduerr Reasonable people can differ on such matters IMHO! Still, I hope that you can imagine use cases which you would find sensible and reliable based on my patch? If so, would reopening this PR or making a new one be most acceptable to the Alacritty maintainers?

@chrisduerr
Copy link
Member

Well this patch in its current form certainly won't be merged.

@j4james
Copy link

j4james commented Oct 23, 2025

@ltratt Sorry, I didn't mean to suggest that you could already use DA3/DECSTUI - Alacritty doesn't currently support either of them. But if you were planning to add additional functionality to Alacritty, it would be better to implement existing ops like these rather than inventing a whole new proprietary sequence. That said, I suspect the Alacritty maintainers wouldn't accept either option.

@ltratt
Copy link
Contributor Author

ltratt commented Oct 23, 2025

@chrisduerr Are you referring to ltratt@097ffd8 ? If that is unacceptable, can I ask you to explain what would be acceptable to you, bearing in mind that I'm an idiot and need things spelt out? In essence, all ltratt@097ffd8 does is set ALACRITTY_WINDOW_ID when running hint commands. My own personal motivations for doing so are not encoded in that patch.

@chrisduerr
Copy link
Member

Are you referring to ltratt/alacritty@097ffd8 ?

I was referring to the current state of the PR, but this patch isn't much better. It sets ALACRITTY_WINDOW_ID, but that's somewhat arbitrary to me. We also set WINDOWID for the shell env for the example, but that isn't inherited. There's also all the user-defined variables that are set for the shell but not for anything spawned by the window.

I get that this is a hacky workaround to fix your issue, but there isn't any system to it as far as I can tell. It's just a quick hack to get your script working, which is fine for a personal fork, but not fit for upstream.

@ltratt
Copy link
Contributor Author

ltratt commented Oct 23, 2025

@chrisduerr Would you prefer the commit to set WINDOWID instead of / as well as ALACRITTY_WINDOW_ID to keep it consistent with what the main shell sees (as both are set there)? I'm happy to do that.

I think, perhaps, I might not have explained my setup in a way that makes sense to you -- mea culpa! Let me try again. I'm running (various) neovim-qts. I run commands (in various ways) in various terminals e.g. various compilers. With the patch I've sent, I can click on filename:line:no from a compiler and have that open in the right neovim-qt -- provided I can tell which shell the hint command relates to. This seems rather principled to me. How that relation happens is another matter: basically there just needs to be a way for the shell and the hint command to be related to each other. If e.g. the hint command could tell me the PID of the shell in the window clicked on, that would also be perfectly acceptable. Does this make more sense?

@ltratt
Copy link
Contributor Author

ltratt commented Oct 30, 2025

FWIW, I have outlined in more detail (a) why such a feature is useful (b) how I now implement it (using cookie files rather than xprop) here https://tratt.net/laurie/blog/2025/what_context_can_bring_to_terminal_mouse_clicks.html. In retrospect, I didn't motivate or explain this very well -- mea culpa!

@chrisduerr
Copy link
Member

chrisduerr commented Oct 30, 2025

I'm not reading a blog post to understand why you want a feature, but your comment did remind me that commands spawned from a process inherit the current terminal's foreground process working directory.

If you just want the working directory, can't you just rely on that?

@ltratt
Copy link
Contributor Author

ltratt commented Oct 30, 2025

@chrisduerr AFAICS pwd in a hint command is set to $HOME, at least on my system, no matter what directory my interactive shell / foreground process is in.

@chrisduerr
Copy link
Member

AFAICS pwd in a hint command is set to $HOME, at least on my system, no matter what directory my interactive shell / foreground process is in.

The following works for me:

[[hints.enabled]]
regex = """(/?[^/ \"']*[a-zA-Z0-9][^/ \"':]*/([^/ \"']+/?)*)\
    |(/[^/ \"']*[a-zA-Z0-9][^/ \"']*)"""
command = {  program = "bash", args = ["-c", "echo $(pwd) > /tmp/test_pwd"] }
binding = { key = "P", mods = "Control|Shift" }

@ltratt
Copy link
Contributor Author

ltratt commented Oct 30, 2025

@chrisduerr Alas, even command = { program = "bash", args = ["-c", "echo $(pwd) > /tmp/test_pwd"] } only gives me $HOME (confirmed on master). There may be an OS difference at work here, perhaps obscured via Rust's Command?

@chrisduerr
Copy link
Member

Alas, even command = { program = "bash", args = ["-c", "echo $(pwd) > /tmp/test_pwd"] } only gives me $HOME (confirmed on master). There may be an OS difference at work here, perhaps obscured via Rust's Command?

I just checked your blog and it looks like Linux, that's what I use. Is this not the case? Do you have a working directory set in your config/cli to launch Alacritty?

@ltratt
Copy link
Contributor Author

ltratt commented Oct 31, 2025

@chrisduerr I'm using OpenBSD. You're right that the directory I'm seeing reflects the working directory at launch (I normally launch Alacritty from rofi; if I run from master then the directory I'm seeing with your command above is the source dir for Alacritty) -- it doesn't change based on what I do in my shell, and all the other terminal windows I launch (with Ctrl+Shift+N) share the same launch directory. AFAICS it doesn't matter what directory I change to within a terminal window?

@chrisduerr
Copy link
Member

I'm using OpenBSD

Ah okay I guess that explains it. See the code we use to do this:

/// Get working directory of controlling process.
#[cfg(not(windows))]
pub fn foreground_process_path(
master_fd: RawFd,
shell_pid: u32,
) -> Result<PathBuf, Box<dyn Error>> {
let mut pid = unsafe { libc::tcgetpgrp(master_fd) };
if pid < 0 {
pid = shell_pid as pid_t;
}
#[cfg(not(any(target_os = "macos", target_os = "freebsd")))]
let link_path = format!("/proc/{pid}/cwd");
#[cfg(target_os = "freebsd")]
let link_path = format!("/compat/linux/proc/{}/cwd", pid);
#[cfg(not(target_os = "macos"))]
let cwd = fs::read_link(link_path)?;
#[cfg(target_os = "macos")]
let cwd = macos::proc::cwd(pid)?;
Ok(cwd)
}

OpenBSD falls into the Linux case here, which I'd assume doesn't work. If you have an implementation that works, it should be a simple patch to get merged.

@ltratt
Copy link
Contributor Author

ltratt commented Oct 31, 2025

@chrisduerr You're right! Please see #8736.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

5 participants