profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/lilyball/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.
Lily Ballard lilyball San Leandro, CA 🏳️‍⚧️🏳️‍🌈 Rustacean 🦀. Open source contributor. Programming language aficionado. She/her.

apple/swift 57354

The Swift Programming Language

apple/swift-evolution 12745

This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.

apple/swift-package-manager 8501

The Package Manager for the Swift Programming Language

apple/swift-corelibs-foundation 4409

The Foundation Project, providing core utilities, internationalization, and OS independence

apple/swift-corelibs-libdispatch 2108

The libdispatch Project, (a.k.a. Grand Central Dispatch), for concurrency on multicore hardware

apple/swift-corelibs-xctest 930

The XCTest Project, A Swift core library for providing unit test support

apple/swift-llbuild 890

A low-level build system, used by Xcode and the Swift Package Manager

apple/swift-lldb 652

This is the version of LLDB that supports the Swift programming language & REPL.

issue openedasync-raft/async-raft

Raft shutdown doesn't wait for replication streams to shut down

When Raft is told to shutdown, it waits for its core to shut down. If it was in the leader state, it signals the replication streams to shut down too. But it doesn't actually wait for the replication streams to shut down. The effect of this is Raft can declare that it has shut down and return from the shutdown future while the replication streams are still alive and talking to other nodes.

Raft really needs to ensure all of its operations have shut down before it returns from the shutdown future.

created time in 2 days

issue openedasync-raft/async-raft

`LaggingState` potentially ignores state changes from some await operations

LaggingState, in its main loop, checks to make sure the target state is still Lagging, but then does multiple async operations (which may potentially change the state) without checking the state in between, and may even set the state to LineRate without ensuring it's still Lagging.

I don't have logs of this happening in practice, but the possibility concerns me.

created time in 2 days

issue commentasync-raft/async-raft

`LineRateState` won't ever handle shutdown as long as there's something in its outgoing buffer

On a related note, being told to shutdown doesn't interrupt the send_append_entries() calls. I feel like termination should probably be handled on a separate channel from the other events, such that send_append_entries() can watch that channel too (or any other async operation that might take a while to complete).

lilyball

comment created time in 2 days

issue openedasync-raft/async-raft

`LineRateState` won't ever handle shutdown as long as there's something in its outgoing buffer

While a replication stream is in LineRateState, it always prioritizes draining its buffers first. Unfortunately this means if it never manages to drain its buffers, it will also never check for events which means it will never handle a terminate event.

The practical effect of this is if the remote node goes down, the buffers will never drain, and the replication stream will stay alive as a zombie even after the raft core switches out of the leader state, and even after raft itself shuts down. As long as the tokio executor is running, the replication stream will continue shouting into the void, trying to contact a node that doesn't respond.

This is also exacerbated by the fact that raft shutdown doesn't actually wait for its replication streams to shut down, which means raft will declare that it's fully shutdown but the zombie replication streams will stay alive.

Sample log:

Sep 23 16:52:15.636  INFO main{id=5 cluster=LeaderElectionCluster}: async_raft::core: node has shutdown 
Sep 23 16:52:15.654 ERROR main{id=5 target=2 cluster=LeaderElectionCluster}:run{state="line-rate"}:send_append_entries: async_raft::replication: error sending AppendEntries RPC to target error=the Append Entries RPC failed 
Sep 23 16:52:15.677 ERROR main{id=5 target=1 cluster=LeaderElectionCluster}:run{state="line-rate"}:send_append_entries: async_raft::replication: timeout while sending AppendEntries RPC to target error=deadline has elapsed 
Sep 23 16:52:15.678 ERROR main{id=5 target=1 cluster=LeaderElectionCluster}:run{state="line-rate"}:send_append_entries: async_raft::replication: error sending AppendEntries RPC to target error=the Append Entries RPC failed 
Sep 23 16:52:15.686 ERROR main{id=5 target=2 cluster=LeaderElectionCluster}:run{state="line-rate"}:send_append_entries: async_raft::replication: error sending AppendEntries RPC to target error=the Append Entries RPC failed 

The log continues like this forever, with it failing to send to targets 1 and 2 over and over even though raft itself shutdown.

created time in 2 days

issue openedlwouis/alt-tab-macos

Space doesn't work to focus selected window if another app has

Describe the bug

A clear and concise description of what the bug is. What happened, and what you think should have happened.

Screenshots / video

Add screenshots to help explain your problem. You can also use Loom to easily record your screen to show the bug in action. That is really helpful!

Steps to reproduce the bug

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

created time in 4 days

issue commentnix-community/home-manager

bug: `programs.starship` shell init uses direct package path instead of path via profile

Here's what I get:

$ starship init bash | grep bin/starship | sed 's/^ *//'
source <(/etc/profiles/per-user/lily/bin/starship init bash --print-full-init)
source /dev/stdin <<<"$(/etc/profiles/per-user/lily/bin/starship init bash --print-full-init)"

(starship resolves to /etc/profiles/per-user/lily/bin/starship, and using the absolute path behaves the same)

If I resolve the symlink and run it from the nix store path, I get the bad version:

$ /nix/store/5adjlvmlhrxj2z9bdq4prw8sb9ngm91l-home-manager-path/bin/starship init bash | grep bin/starship | sed 's/^ *//'
source <(/nix/store/5adjlvmlhrxj2z9bdq4prw8sb9ngm91l-home-manager-path/bin/starship init bash --print-full-init)
source /dev/stdin <<<"$(/nix/store/5adjlvmlhrxj2z9bdq4prw8sb9ngm91l-home-manager-path/bin/starship init bash --print-full-init)"

From your output, I'm wondering if you have wrapper scripts in the mix somewhere? A single wrapper script is supposed to forward argv0, but if you have a wrapper script that executes a wrapper script that executes the binary, the argv0 forwarding doesn't work (last time I checked, bash ignores the input argv0 when a script is invoked via exec; I'm really not sure what's going on here, even just exec ./foo.sh causes $0 to be the absolute path to the script whereas running ./foo.sh causes $0 to be ./foo.sh).

lilyball

comment created time in 4 days

issue commentNixOS/nixpkgs

Deprecated aliases should be annotated somehow to be obvious in `nix search` output

I still care about this. Also, I suspect this should be labeled as 0.kind: enhancement instead.

lilyball

comment created time in 4 days

issue openedasync-raft/async-raft

`finalize_snapshot_installation` docs don't mention updating the state machine

The docs for RaftStorage::finalize_snapshot_installation talk about updating the log but don't talk about updating the state machine. Updating the state machine with the snapshot contents is a rather important part of finalizing a snapshot.

https://github.com/async-raft/async-raft/blob/bcc246ccf8fa2858baf8e07bf760ee6db4d85cf6/async-raft/src/storage.rs#L208-L228

created time in 4 days

issue commentasync-raft/async-raft

memstore saves wrong membership config in `finalize_snapshot_installation`

Those two commits look good (I didn't read the tests, but the code fixes look correct).

But a SnapshotPointer log will never be replicated, as far as I recall. It is a marker to indicate the leader to switch to Snapshotting state.

I'm not sure what you mean by this. A SnapshotPointer is just the results of either log compaction or receiving a snapshot from the leader. The existence of a SnapshotPointer log entry doesn't mean anything for the current snapshot state. AIUI the only time any node doesn't have a SnapshotPointer is when it's brand new and hasn't either done a log compaction or received a snapshot. Under normal operation every node in the cluster will end up having a SnapshotPointer permanently.

lilyball

comment created time in 4 days

issue commentlwouis/alt-tab-macos

Alt-tab'ing to the Preferences window doesn't focus it, and may cause crashes

I re-filed this as #1151 as it occurs on latest macOS 11 but this issue's description is a bit confusing.

jukrb0x

comment created time in 4 days

issue openedlwouis/alt-tab-macos

Alt-tab to preferences window moves it to the front but does not focus it

Describe the bug

If I use alt-tab to select the preferences window (or Feedback window), the window is moved to the front but does not have focus. At this point it appears that no window in any app has focus (e.g. pressing ⌘W just beeps at me). Oddly, clicking the window at this point does not give it focus either. I have to click to another app and back.

If I have both Preferences and Feedback open, even clicking between them doesn't give focus (it just moves the window to the front). Interestingly, even when one of the apps have focus, using Alt-tab to focus on the other doesn't visibly give it focus though it does become the first responder for events, and waiting a few seconds (and possibly touching the trackpad, this is somewhat inconsistent) will make the focus visually switch (though the text field in Send Feedback doesn't start flashing its insertion point until I interact with it).

Note that this is not an issue with apps that hide their dock icon in general. In particular, I can't reproduce this using Dash or Yoink.

This was reproduced on macOS 11.6 (20G165). Alt-tab preferences are mostly vanilla (just tweaked the minimized/hidden windows settings).

Screenshots / video

Screen recording showing this. When the Alt-tab preferences window moves in front of the Finder window, this was me pressing the alt-tab shortcut.

https://user-images.githubusercontent.com/714/134229452-462f247c-49bd-41dc-9930-2c5562d71b3b.mov

Steps to reproduce the bug

  1. Open the Alt-tab preferences window (or Send Feedback window)
  2. Move focus to a window from any other app (either clicking, cmd-tabbing, or alt-tabbing)
  3. Press your Alt-tab shortcut to move focus back to the Alt-tab preferences window
  4. See preferences window move to the front without taking focus.

created time in 4 days

issue commentasync-raft/async-raft

memstore saves wrong membership config in `finalize_snapshot_installation`

@drmingdrmer This ticket is about finalizing a snapshot installation, not about log compaction. The new snapshot that's being finalized already includes whatever membership config is applicable. In this case, a new node will start at

+-------------
0

And it will receive snapshot-pointer(config-1). But since it throws away the membership there, what it ends up with is

+--------------+
0              |
               |
               |
               `snapshot-pointer(new-initial)

Note how it's got the wrong membership config, it should have config-1 but it created a new initial config instead.

Or if we consider a lagging node that looks like the snippet you pasted, and then the node receives a snapshot that replaces eevrything with config-7 in it, it will end up keeping config-4 instead and throwing away config-7.

lilyball

comment created time in 4 days

startedserhii-londar/open-source-mac-os-apps

started time in 5 days

issue openedtokio-rs/tokio

Support for non-contiguous buffers in `tokio_util::codec::Encoder`

Is your feature request related to a problem? Please describe. tokio_util::codec::Encoder does not support zero-copy writes. It also makes it very awkward to support a variable-width length-prefixed frame when the size of the encoded data is not known prior to writing the data.

Today, the Encoder::encode() method takes a &mut BytesMut, which is a contiguous buffer. This means there's no way to add data to it without copying the data. In the variable-width length-prefixed scenario, this requires writing the data first in order to calculate the length (and therefore the size of the encoded length), so this also involves a copy (either writing to a side buffer, or writing to the BytesMut prior to shifting the data to fit the encoded length).

This is especially frustrating as the lower-level method that Framed uses to actually write out the data works with non-contiguous buffers, but Framed does not take advantage of that.

Describe the solution you'd like Change the type from BytesMut to something that supports non-contiguous buffers. I don't know offhand what existing type would work for this, but it's something that should support the same basic functionality of BytesMut while also allowing for non-contiguous buffers.

From the perspective of Framed, once the data has been written by the Encoder impl, Framed really only cares that it implements Buf. So this new type could perhaps support appending T where T: Buf + 'static, thus allowing it to take ownership of arbitrary chunks of data.

As for the variable-width length-prefixed scenario, where it makes sense to write into the existing allocated space if there is enough, what we'd like is to be able to write into the existing allocated space, then insert the length prefix before the written data. There are multiple possible APIs here, and I'm not sure what the best one is, but ultimately I want to write into the allocated space and then write the length without copying data unnecessarily. The buffer type could support various operations that split its data into separate chunks (without copying data) in order to insert or reorder them.

Incidentally, this would also help tokio_util::codec::length_delimited::LengthDelimitedCodec, which has to copy the data from the Bytes item into the buffer, but with this new approach it would just append it as a chunk.

Describe alternatives you've considered Instead of a new type, we could try changing the encode() API such that instead of being given a &mut BytesMut, it could be given a BytesMut and required to return a Result<Self::Buffer, Self::Error> where Self::Buffer is something like type Buffer: Buf and the documentation can suggest setting it to BytesMut in the simple case (existing encoders can just return the input BytesMut).

This approach also allows for preventing Encoders from altering previously-written data. The trait can instead guarantee that the input BytesMut has a len() == 0 (it being provided mostly as a container for existing allocated space). And it can be created by calling buffer.split_off(buffer.len()).

An upside here is when the buffer has to be extended, it doesn't have to copy all of the previously-written data, only the new frame.

A downside here is if the Encoder impl doesn't return the input BytesMut, then any additional reserved capacity in it will be thrown away.

Additional context AsyncWrite gained vectored writes in #3149, it's very annoying that tokio_util::codec doesn't support this.

created time in 5 days

issue commentasync-raft/async-raft

memstore saves wrong membership config in `finalize_snapshot_installation`

@drmingdrmer I filed #134 about do_log_compaction based on your comment.

lilyball

comment created time in 8 days

issue openedasync-raft/async-raft

memstore `do_log_compaction` needs to match `SnapshotPointer` as well

memstore's implementation of do_log_compaction only looks for ConfigChange and not SnapshotPointer

https://github.com/async-raft/async-raft/blob/bcc246ccf8fa2858baf8e07bf760ee6db4d85cf6/memstore/src/lib.rs#L286-L294

This suggests that maybe EntryPayload should have a helper .membership_config() -> Option<_> method so implementations don't have to remember to check both, they can instead just check the results of entry.payload.membership_config().


Yes it should check both ConfigChange log and SnapshotPointer log to extract the correct membership config.

The fix is simple and there is a test that reproduces this bug: https://github.com/datafuse-extras/async-raft/commit/dba24036cda834e8c970d2561b1ff435afd93165

Originally posted by @drmingdrmer in https://github.com/async-raft/async-raft/issues/133#issuecomment-921452876

created time in 8 days

issue commentasync-raft/async-raft

memstore saves wrong membership config in `finalize_snapshot_installation`

It should certainly do that during log compaction, that’s a good catch. In the referenced code here it shouldn’t search for a membership config at all though, the Snapshot contains one already.

lilyball

comment created time in 8 days

issue openedasync-raft/async-raft

memstore saves wrong membership config in `finalize_snapshot_installation`

In memstore, in the MemStore::finalize_snapshot_installation() method, it throws away the membership config contained in the snapshot, instead saving the membership config contained in its log up through index as though that were in the snapshot:

https://github.com/async-raft/async-raft/blob/bcc246ccf8fa2858baf8e07bf760ee6db4d85cf6/memstore/src/lib.rs#L348-L364

As best I can tell, this is a bug and that it should just be using the membership config stored in the snapshot. This code here is very nearly a copy&paste from MemStore::do_log_compaction(). It was introduced in 99ac1911f3f9af18a9edc02651f40d521e4c8d60 (part of #59). My best guess here is that the author forgot the snapshot contained a membership config.

Additional evidence for this being a bug is the fact that the code that calls finalize_snapshot_installation() then proceeds to request the current membership config from storage and apply it, and the protocol PDF also confirms that the final step to receiving a snapshot is "Reset state machine using snapshot contents (and load snapshot’s cluster configuration)" (Figure 13).

created time in 9 days

issue commentkovidgoyal/kitty

Option to never close a window on child death even with no background/disowned processes

Once the window has closed there is nothing there to launch from. I am guessing you mean once the child has died.

Exactly my point! This is what my whole issue is about!

Once the window has closed, there is no longer a container that was associated with a cwd, and therefore no way to open a new window with the same cwd.

If the window does not go away immediately, it can remember what the cwd was I can make a new window/tab using that. This is what e.g. Terminal.app does. If I exit my process, the window doesn't close immediately, and New Tab will create a new tab using the same cwd.

Having said that, experimentally right now using kitty --hold, kitty does not in fact use the cwd from the process that just exited. If I run kitty --hold, change directories, hit Ctrl-D to exit the shell, and then my hotkey for new_window_with_cwd, the new window has kitty's cwd rather than the cwd of the shell that just exited. I consider this a bug.

Already discussed to death. Find th proposal for it in terminal-wg

Found it. There's no clear consensus. One person (jerch) is very aggressively against this feature. Everyone else seems to be taking it more seriously.

Huh? This mechanism works with all shells, non-shells and any process at all, without it needing to do anything. The terminal uses the actual existing CWD of the process as the CWD of the window, without the process needing to do anything.

Of which process? If there's just one, sure. What if there's a tree of processes? Which one gets to determine the cwd to show in the terminal? It's typically the shell that you want, but what if there are multiple shells (or the terminal emulator doesn't know which process is the shell). Picking whatever seems to be the most recent interactive process doesn't work either (bash -c 'cd foo && less bar.txt' shouldn't cause less to define the cwd).

I dont what a proxy icon is, probably yet another poorly thought out Apple hack.

You literally have no idea what it is and yet you're declaring it to be a poorly-thought-out hack. I guess I shouldn't be surprised given how extremely antagonistic you have been to every single piece of feedback I have tried to give you.


Given how hostile you are to making any changes to behavior whatsoever, I give up. You win. I'll stop filing feedback (and just stop trying to use Kitty altogether). Congratulations, this is the second-worst OSS experience I've ever had. Give yourself a medal.

lilyball

comment created time in 10 days

issue commentkovidgoyal/kitty

Option to never close a window on child death even with no background/disowned processes

Can you please stop summarily closing my issues without actually understanding my problem?

--hold is a flag to the kitty binary. It is not a config option, and it only applies to the very first window opened using kitty --hold. This means it won't apply to any new windows/tabs created within the running Kitty instance. That means it won't apply to 99% of my Kitty windows.

I didn't know about this flag originally, so it does handle the specific case of kitty --hold env, but it does not handle the more general case of "the command I was running exited but I didn't want that to happen and now I've lost the whole window".

show_kitty_env_vars

This looks useful, thanks.

https://sw.kovidgoyal.net/kitty/launch/#cmdoption-launch-cwd

This does not solve my problem. I've already rebound keys to the _use_cwd variants. The problem I described was once the window has closed I no longer have the cwd to create new shells from.

Display the current directory in tab/window title without needing hacks like OSC 7

What makes OSC 7 a hack? If anything, "show the cwd by setting the window title" is the hack. Several issues:

  • If I'm running a command, I lose the display of my current directory because it's replaced by the command
  • Overriding shell RC files automatically is not great. I realize your docs have a "if you don't want this, here's how you set it up manually" but still.
  • That solution does not scale to any shells not explicitly supported by Kitty. OSC 7 is something any shell can start printing without requiring the terminal emulator to know about that shell.
  • OSC 7 takes a file:/// URI, which allows terminals to do things like show a proxy icon in the titlebar. Setting the window title to the path does not have any semantic meaning.
  • It overrides any existing fish_title I might have already configured. I can set no-title but then I'm back to not having the path in my window title.
  • It duplicates the fish truncated prompt into the window title, which may be either too verbose or not verbose enough. In apps like Terminal.app, besides the proxy icon it also means the window title contains just the current dir name but cmd-clicking will give me a dropdown with the full path (which is standard OS behavior for windows with proxy icons).
  • The use of a file:// URI qualified with hostname allows the proxy icon to even understand if this is a local path or a remote path.

Basically, OSC 7 is the right way to report the cwd, and the only thing hacky about it is the lack of proper feature detection (though is there even any downside to sending it to terminal emulators that don't handle it, assuming they handle OSC codes at all?).

This is rather orthogonal to this particular issue though.

lilyball

comment created time in 10 days

issue commentkovidgoyal/kitty

Option to never close a window on child death even with no background/disowned processes

Side note: Does Kitty even support the OSC 7 escape for telling the terminal what the current directory is? It doesn't show that info anywhere I can see, and Fish doesn't include Kitty in the list of terminals it sends OSC 7 to.

lilyball

comment created time in 10 days

issue openedkovidgoyal/kitty

Option to never close a window on child death even with no background/disowned processes

Is your feature request related to a problem? Please describe. If I run a program in a new Kitty window that prints output and immediately exits, Kitty will show the window, run the program, and immediately close the window. This happens regardless of close_on_child_death as that only keeps the window open if a disowned/background process is still kicking around.

This is frustrating because it means I can't quickly open a new window with the output of some command without wrapping it in a shell that waits for input before terminating. This is doubly frustrating if my intent is to run a command with precisely the initial terminal environment and don't want e.g. /bin/sh to change anything.

It also means if I accidentally kill a process (e.g. hit Ctrl-D in my shell when I didn't mean to) I immediately lose all scrollback, and I also lose the notion of "current directory" (e.g. I can't spawn a new shell).

Describe the solution you'd like I'd like an option to have windows stay open after their process died. They should be visibly marked as having no process, but should not close until I explicitly close them. I should be able to set this in kitty.conf, and perhaps override it with a flag when invoking kitty directly (e.g. if I'm opening a window to an editor, as ctrl+shift+f2 does, I may want it to close when the editor dies).

Precedent here is Apple Terminal, which does precisely this. When the last process in a window ends, the text [Process completed] is printed to the terminal and the window and tab titles are updated to remove the process name. Also, very importantly, the notion of "current directory" actually persists, so if I open a new tab, it keeps the same directory.

Describe alternatives you've considered There's room for subtlety here. Kitty could do something like "if the user hits Ctrl-D and that causes the process to terminate, go ahead and close the window", or "if the process was using alternate screen mode, it was likely interactive so go ahead and close the window" (this latter one makes things like kitty vim work nicely out of the box). I don't know what exact logic would go here, and maybe this is something that would want to also be configurable (e.g. let me say "be intelligent about it" versus "never close").

Additional context I don't know how this would handle splits. Apple Terminal doesn't have splits so it doesn't have to deal with that, it just has tabs and windows. It's certainly possible this could be handled as "splits will close immediately, but a tab or OS window won't close without using the keyboard shortcut for it", though that's a bit odd.

Ultimately, it's very surprising to me for a terminal window to just vanish. It's also very annoying that I can't run e.g. kitty env to see the initial shell environment (this is something I actually do in Apple Terminal more often than you'd think, mostly when mucking about with my shell initialization in order to verify what it sees on startup).

There's also a feature that could be unlocked with this functionality, which is a way to say "please respawn my shell", or rather "please rerun the command that was used to spawn this window in the first place". That itself has questions like "if we preserve the current directory, what if the command had a relative path as an argument?", but mostly it would just be a really quick way of saying "oops I didn't mean to exit my shell, please spawn a new shell in the current directory, ideally without losing my scrollback". Any customized shell environment would be lost, but it would still be quite useful.

created time in 10 days

issue commentzkat/supports-hyperlinks

Support env var to force hyperlinks on (or off)

For reference, I just found an NPM package called supports-hyperlinks which defines the FORCE_HYPERLINK var. The logic here appears to be "if FORCE_HYPERLINK exists, a value matching /^\s*0+(?!\d)/ means disable hyperlinks, anything else enables them", though I'm not sure they really meant for FORCE_HYPERLINK=0xF to mean disable hyperlinks, I suspect they actually just wanted to trim whitespace.

lilyball

comment created time in 10 days

issue commentkovidgoyal/kitty

set environment variable TERM_PROGRAM to "Kitty"

TERM_PROGRAM is not a standard, its just something Apple uses.

It's also used by Visual Studio Code (along with TERM_PROGRAM_VERSION). Searching online right now, I'm seeing that it's used as well by Hyper and FluentTerminal. I don't know offhand what other terminals to check.

Terminal developers long ago decided that environment variables with terminal name/version are not a good way to detect/query terminal features. Google the terminal-wg discussion on feature detection for an example of the latest.

I found this discussion which mentions TERM_PROGRAM in passing but I don't see anyone actually discussing the pros/cons of TERM_PROGRAM.

I certainly agree that we need a better solution for feature detection! But I don't expect that to happen any time soon. And in the meantime, there doesn't appear to be much downside to setting this.

And in this case TERM_PROGRAM provides no extra information over TERM. If TERM does not work for you, then neither will TERM_PROGRAM.

TERM doesn't have an equivalent for TERM_PROGRAM_VERSION though. In theory the terminfo file tells me what I need to know, except there are things not covered by it such as hyperlink support, information on handling of unicode text layout, etc. These are things that may require inspecting the version to handle. There's also a history of emulators reusing existing TERM names to say "I support everything that terminal does" (mostly because the existing one is in common terminfo databases) which means it's not fully reliable as a way to tell which terminal you're actually in. Heck, the inclusion of TERM_PROGRAM / TERM_PROGRAM_VERSION is worth it just to allow CLI programs to report the current terminal and version when generating bug reports.

As such I am not going to create digital noise chasing Apple's bad idea. They were too lazy to patch the shells on their systems to do proper terminal detection. So they came up with this kludge.

Using a custom TERM breaks a lot of things. It doesn't work over SSH (which is why Kitty needs to have its hacky kitty +kitten ssh wrapper that I need to manually alias in my shell). There are lots of programs out there that do string matching on TERM instead of reading the capabilities directly (I wonder how many CLI programs think Kitty doesn't even support 256 colors?).

I do not think Apple developers were "lazy". I think they did not want to break SSH and wanted tools that do string matching (e.g. on xterm-*, which is really common), and so they picked an existing TERM to target for compatibility.

Oh and for posterity, the proper way to do terminal name and version detection is to use the XTVERSION escape code.

Implementing bidirectional communication with the terminal is a pretty big ask for programs that just want to e.g. colorize their output. Heck, it's already hard enough convincing programs to use the terminfo capability strings for this instead of just hardcoding the xterm escapes.


At the very least, Kitty should remove any inherited TERM_PROGRAM and TERM_PROGRAM_VERSION env var, to avoid incorrect detection, and to make /etc/bashrc stop running the Apple Terminal initialization code when running kitty from a Terminal.app shell. I have worked around this locally by using env in my kitty.conf, but this doesn't help anyone else.

P.S. There appears to be no way to use kitty.conf to delete a variable. Writing env VAR will set VAR to the empty string. This means that my solution of

env TERM_PROGRAM
env TERM_PROGRAM_VERSION
env TERM_SESSION_ID

will actually add those three env vars even if they weren't set before, which is annoying noise. (The inclusion of TERM_SESSION_ID here is because, again, this is a variable Terminal.app sets that's unique for each terminal session and persists across relaunches. It's used by the /etc/bashrc_Apple_Terminal code for preserving session state across relaunches, which is rather neat and demonstrates again why this needs to know it's specifically Apple Terminal, so it knows that TERM_SESSION_ID represents a uuid unique to the session and preserved across relaunches).

It would be much better if env VAR would delete it and env VAR= would set it to the empty string.

reportaman

comment created time in 10 days

issue commentkovidgoyal/kitty

Dual text/emoji presentation characters change width with VS15 (U+FE0E) and VS16 (U+FE0F)

Oh hey, UAX #11 §2 Scope also says

Note: The East_Asian_Width property is not intended for use by modern terminal emulators without appropriate tailoring on a case-by-case basis. Such terminal emulators need a way to resolve the halfwidth/fullwidth dichotomy that is necessary for such environments, but the East_Asian_Width property does not provide an off-the-shelf solution for all situations. The growing repertoire of the Unicode Standard has long exceeded the bounds of East Asian legacy character encodings, and terminal emulations often need to be customized to support edge cases and for changes in typographical behavior over time.

So this is explicitly addressing the terminal emulator case as saying that the behavior I've described of other emulators is not necessarily wrong.

lilyball

comment created time in 10 days

issue commentkovidgoyal/kitty

Dual text/emoji presentation characters change width with VS15 (U+FE0E) and VS16 (U+FE0F)

And my goal with kitty is to move this shitshow of an ecosystem forward. And forward in this instance means getting terminal text rendering into the 21st century.

If you're deliberately attempting to influence the handling of emoji in terminals, then you really need to document the behavior Kitty has that's intentional, the behavior that is a bug (such as the incorrect layout of ZWJ sequences), the goal here (i.e. "Kitty behaves differently than other emulators for these reasons"), and the fact that you think other emulators should match Kitty. And then this document can be taken and presented to other terminal emulator developers (whether by you or by users who agree with you). In the absence of this document, it's impossible to tell where you've made a decision to behave differently versus what's a bug, it's rather difficult for other emulators to match Kitty.

All I can find right now is a FAQ entry that says

The number of cells a unicode character takes up are controlled by the unicode standard. All characters are rendered in a single cell unless the unicode standard says they should be rendered in two cells. When a symbol does not fit, it will either be rescaled to be smaller or truncated (depending on how much extra space it needs). This is often different from other terminals which just let the character overflow into neighboring cells, which is fine if the neighboring cell is empty, but looks terrible if it is not.

This isn't quite accurate. Unicode does not concern itself with layout in most cases, and does not concern itself with terminal cells either. AFAICT the only place it cares about actual horizontal text layout (as opposed to grapheme/word/line breaking) is UAX #‌11 East Asian Width, which defines the concept of "narrow" and "wide" characters for East Asian text.

Digging through this, I finally found the spot in UAXA #11 §5 Recommendations that says

  • [UTS51] emoji presentation sequences behave as though they were East Asian Wide, regardless of their assigned East_Asian_Width property value.

This is finally an explicit recommendation that says the sequence emoji_character emoji_presentation_selector should be treated as a Wide character! Though it's still just a recommendation, not an actual conformance requirement. This assumes of course that the terminal emulator treats East Asian Wide as 2 cells, though that does seem to be common practice.

In any case, a document as described above that explains the way in which Kitty handles layout for emoji and how it intentionally differs from existing terminals would be very much appreciated. This would not just be something that could be given to other terminal emulator developers, but also used by CLI tools (such as Fish) that need to measure string width.

lilyball

comment created time in 10 days

issue commentkovidgoyal/kitty

Some window decorations missing on macOS when window background_opacity < 1

GLFW appears to call [window setHasShadow:NO] when creating the NSWindow if the framebuffer config includes transparent. What happens if you just call [window setHasShadow:YES] again afterwards?

Personally, I really want semi-transparent terminal windows, I've been using that in Terminal.app for almost 2 decades, but losing the shadow is a dealbreaker. Terminal.app also supports blurring the background, which is something that would be extremely nice to have as well, but it's less obvious how to do that (which is to say, there are macOS APIs for producing blurred semi-transparent window backgrounds, but I don't know how to use those with a GLFW window as I believe they require setting up the content view hierarchy in a particular way).

evanheller

comment created time in 10 days

issue commentnix-community/home-manager

Mac Application launchers not symlinked on darwin

@malob I've heard of Raycast but haven't looked into it, since Alfred has been working wonderfully since forever. How do they find Nix applications, if the Nix store isn't indexed with Spotlight? Or does your setup actually allow Nix store indexing?

I haven't dug into it but I'm guessing it's the nobrowse mount option that also suppresses Spotlight. I do wonder if it's worth just removing that from fstab and marking the volume with Hidden flag instead, though that means a bunch of churn with spotlight indexing on every Nix store write, and I recall having issues in the past with Alfred/Spotlight surfacing a bunch of copies of MacVim because it doesn't know what the latest is.

starcraft66

comment created time in 10 days

issue commentnix-community/home-manager

Mac Application launchers not symlinked on darwin

The wrapper app idea is an interesting one. It would cause the weird behavior of "I try to launch the app, it bounces in the dock once before vanishing as a different copy of the app launches", but that's not awful. Still doesn't solve the Dock issue of course, but it seems like nothing does.

In theory it could copy the URL schemes from the main app, but I'm not sure we have to do that (what does LaunchServices do today with registered URL schemes? Surely LS will register the app when it's launched at least, I'm not sure about otherwise without spotlight indexing, but Nix means having a bunch of copies of the app lying around in the Nix store and I don't know quite how LS handles that). But what it definitely has to do is handle the request to open documents, as I can drag documents onto the app to open (or use open to do it), so it has to catch those and forward them to the underlying app. Which means it'll have to at least copy the Info.plist declaration for what documents it handles. Though on that note, I'm pretty sure I can use open to hand a URL to an app too, and it would have to forward those, though I don't think that approach needs copying the URL schemes (I think it just unconditionally hands the URL to the app).

starcraft66

comment created time in 10 days

issue commentnix-community/home-manager

Mac Application launchers not symlinked on darwin

You just have to configure Alfred to include aliases in its search results.

I hadn't explicitly done that, as it wasn't immediately obvious how, but one potential concern here is this will make Alfred show all aliases, not just aliases to apps. I am not in the habit of using aliases so maybe this is okay, except I don't know how often apps create aliases on disk behind the scenes for various things. For example, ~/Library/Containers/*/Data contains a bunch of aliases, though this is not part of Alfred's default search scope.

Still, with the ability to do this, it might be the best of a bad bunch of solutions. It's unfortunate that this doesn't solve the Dock problem though (the Dock won't add symlinks either, it adds the underlying app, so every time MacVim updates I have to add the new version to my Dock; thankfully I mostly launch that with mvim which will do the right thing, I even made an Alfred workflow to launch that for me, but that doesn't scale to adding more apps). I did consider making an activation script that would edit the Dock plist, but then I'd have to also restart the Dock, and I feel a bit weird about hand-editing the Dock's preferences and relaunching it.

starcraft66

comment created time in 10 days