diff --git a/README.md b/README.md
index f7b8518..ba7d9fb 100644
--- a/README.md
+++ b/README.md
@@ -182,7 +182,7 @@ Console.WriteLine(document.Target); // Session
```
You write C# and tmux receives tmux: `Session.Name` goes on the wire as
-`session_name`, and `Client.IsControlClient` as `client_control`. The catalog
+`session_name`, and `Client.IsControlClient` as `client_control_mode`. The catalog
carries that pair for all twelve queryable fields, and it is closed — a field
outside it throws `UnsupportedQueryExpressionException` rather than falling
back, so an expression that translates is one tmux can answer.
diff --git a/src/LibTmux.Generators/FieldCatalogGenerator.cs b/src/LibTmux.Generators/FieldCatalogGenerator.cs
index 1c14625..02ad8ec 100644
--- a/src/LibTmux.Generators/FieldCatalogGenerator.cs
+++ b/src/LibTmux.Generators/FieldCatalogGenerator.cs
@@ -16,13 +16,13 @@ public sealed class FieldCatalogGenerator : IIncrementalGenerator
/// The closed catalog, and where each field lives on its entity.
///
/// Wire name and property are declared explicitly because the mapping is
- /// not systematic (client_control → IsControlClient, and two
+ /// not systematic (client_control_mode → IsControlClient, and two
/// fields have no property at all).
///
private static readonly (string WireName, string Target, bool Relation, string? Property)[]
Fields =
{
- ("client_control", "Client", false, "IsControlClient"),
+ ("client_control_mode", "Client", false, "IsControlClient"),
("client_id", "Client", false, null),
("client_name", "Client", false, "Name"),
("pane_command", "Pane", false, null),
diff --git a/src/LibTmux.Query.Json/README.md b/src/LibTmux.Query.Json/README.md
index 293e413..8266786 100644
--- a/src/LibTmux.Query.Json/README.md
+++ b/src/LibTmux.Query.Json/README.md
@@ -82,7 +82,7 @@ Console.WriteLine($"depth {QueryJsonLimits.V1.MaximumDepth}, nodes {QueryJsonLim
`session_name`, `session_attached`, `session_id`, `session_windows`,
`window_name`, `window_id`, `window_panes`, `pane_id`, `pane_command`,
-`client_id`, `client_name`, `client_control`.
+`client_id`, `client_name`, `client_control_mode`.
You write these as the properties they are — `Session.Name`,
`Client.IsControlClient` — and the wire carries the tmux spelling.
diff --git a/src/LibTmux.Query.Json/libtmux-query-v1.schema.json b/src/LibTmux.Query.Json/libtmux-query-v1.schema.json
index adf694e..98a4dbc 100644
--- a/src/LibTmux.Query.Json/libtmux-query-v1.schema.json
+++ b/src/LibTmux.Query.Json/libtmux-query-v1.schema.json
@@ -50,7 +50,7 @@
"target": { "$ref": "#/$defs/target" },
"wireName": {
"enum": [
- "client_control",
+ "client_control_mode",
"client_id",
"client_name",
"pane_command",
@@ -99,7 +99,7 @@
"properties": {
"target": { "const": "client" },
"wireName": {
- "enum": ["client_control", "client_id", "client_name"]
+ "enum": ["client_control_mode", "client_id", "client_name"]
}
}
}
@@ -112,7 +112,7 @@
{ "$ref": "#/$defs/field" },
{
"properties": {
- "wireName": { "enum": ["client_control", "session_attached"] }
+ "wireName": { "enum": ["client_control_mode", "session_attached"] }
}
}
]
diff --git a/src/LibTmux/Client.Administration.cs b/src/LibTmux/Client.Administration.cs
index 58b669e..4589295 100644
--- a/src/LibTmux/Client.Administration.cs
+++ b/src/LibTmux/Client.Administration.cs
@@ -41,7 +41,7 @@ internal Client(
public string? Tty => ReadSnapshot("client_tty");
/// Gets whether the client speaks tmux's control protocol.
- public bool IsControlClient => ReadSnapshot("client_control") == "1";
+ public bool IsControlClient => ReadSnapshot("client_control_mode") == "1";
/// Gets the session the client was attached to when it was read.
///
diff --git a/src/LibTmux/Query/QueryTranslator.cs b/src/LibTmux/Query/QueryTranslator.cs
index 7e16a1a..26cc4d2 100644
--- a/src/LibTmux/Query/QueryTranslator.cs
+++ b/src/LibTmux/Query/QueryTranslator.cs
@@ -213,7 +213,7 @@ private static QueryNode TranslateOperand(
private static FieldNode FieldFor(MemberInfo member)
{
// What tmux calls a field is not a transformation of what C# calls
- // it -- Client.IsControlClient is client_control, not
+ // it -- Client.IsControlClient is client_control_mode, not
// is_control_client. The catalog carries that pairing; an unknown
// type is a caller's own row, whose property names are wire names already.
string wireName =
diff --git a/src/LibTmux/README.md b/src/LibTmux/README.md
index a732a7e..009741b 100644
--- a/src/LibTmux/README.md
+++ b/src/LibTmux/README.md
@@ -213,7 +213,7 @@ QueryDocument document = QueryExtensions.Translate(
You write C# and tmux receives tmux. The catalog carries the pair for all
twelve queryable fields — `Session.Name` is `session_name`,
-`Client.IsControlClient` is `client_control` — and it is closed:
+`Client.IsControlClient` is `client_control_mode` — and it is closed:
| Session | Window | Pane | Client |
|---|---|---|---|
diff --git a/tests/LibTmux.IntegrationTests/Clients/ClientAdministrationTests.cs b/tests/LibTmux.IntegrationTests/Clients/ClientAdministrationTests.cs
index 9327d0c..0095080 100644
--- a/tests/LibTmux.IntegrationTests/Clients/ClientAdministrationTests.cs
+++ b/tests/LibTmux.IntegrationTests/Clients/ClientAdministrationTests.cs
@@ -72,6 +72,29 @@ await Assert.ThrowsAsync(
}
}
+ [Fact(
+ Skip = "Requires a Unix process environment.",
+ SkipType = typeof(UnixTestEnvironment),
+ SkipUnless = nameof(UnixTestEnvironment.IsUnix))]
+ public async Task Control_client_reads_back_as_one()
+ {
+ await using RawTmuxTestContext raw = await RawTmuxTestContext.StartAsync(
+ TestContext.Current.CancellationToken);
+ CancellationToken token = TestContext.Current.CancellationToken;
+ Server server = await ConnectAsync(raw, token);
+
+ await using ControlModeClientScope control = await ControlModeClientScope.StartAsync(
+ raw,
+ token);
+
+ // The only assertion in the suite a broken read cannot satisfy: every
+ // other client test attaches a terminal, for which false is the right
+ // answer whether or not the field resolves.
+ Client client = await WaitForClientAsync(server, token);
+ Assert.Equal(control.ClientName, client.Name);
+ Assert.True(client.IsControlClient);
+ }
+
[Fact(
Skip = "Requires a Unix process environment.",
SkipType = typeof(UnixTestEnvironment),
diff --git a/tests/LibTmux.UnitTests/Query/QuerySemanticsTests.cs b/tests/LibTmux.UnitTests/Query/QuerySemanticsTests.cs
index 669c896..306cbf5 100644
--- a/tests/LibTmux.UnitTests/Query/QuerySemanticsTests.cs
+++ b/tests/LibTmux.UnitTests/Query/QuerySemanticsTests.cs
@@ -24,7 +24,7 @@ public void An_entity_translates_through_the_name_tmux_uses_for_the_field()
// The one that a naming rule would never produce.
Assert.Equal(
- "client_control",
+ "client_control_mode",
Field(QueryExtensions.Translate(client => client.IsControlClient)));
}