Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2025 Bryan A. Jones.
# Copyright (C) 2026 Bryan A. Jones.
#
# This file is part of the CodeChat Editor.
#
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2025 Bryan A. Jones.
# Copyright (C) 2026 Bryan A. Jones.
#
# This file is part of the CodeChat Editor.
#
Expand Down
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2025 Bryan A. Jones.
# Copyright (C) 2026 Bryan A. Jones.
#
# This file is part of the CodeChat Editor.
#
Expand Down
11 changes: 9 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (C) 2025 Bryan A. Jones.
Copyright (C) 2026 Bryan A. Jones.

This file is part of the CodeChat Editor.

Expand All @@ -22,7 +22,14 @@ Changelog
[Github master](https://github.com/bjones1/CodeChat_Editor)
-----------------------------------------------------------

* No changes yet.
* No changes.

Version 0.2.3 -- 2026-Sep-09
----------------------------

* Alpha: added support for <xref ref="cc-TRCKclsxwW"></xref> and <xref ref="cc-swJ6a-FiK3"></xref>.
* Improved Client editing experience -- fewer places exist where starting a new
heading, list item, etc. is removed immediately after creation.

Version 0.2.2 -- 2026-Aug-28
----------------------------
Expand Down
168 changes: 160 additions & 8 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,21 @@ blocks may consist entirely of a comment, as illustrated below.
A doc block consists of a comment (inline or block) optionally preceded by
whitespace and optionally succeeded by whitespace. At least one whitespace
character must separate the opening comment delimiter from the doc block text.
Doc blocks are differentiated by their indent: the whitespace characters
preceding the opening comment delimiter. Adjacent doc blocks with identical
indents are combined into a single, larger doc block.
Doc blocks are differentiated by their indent -- the whitespace characters
preceding the opening comment delimiter -- and by the opening comment delimiter
itself. Adjacent doc blocks are combined into a single, larger doc block only
when both their indent and their delimiter match.

```c
// This is all one doc block, since only the preceding
// whitespace (there is none) matters, not the amount of
// whitespace following the opening comment delimiters.
// This is the beginning of a different doc
// block, since the indent is different.
// Here's a third doc block; inline and block comments
/* combine as long as the whitespace preceding the comment
delimiters is identical. Whitespace inside the comment doesn't affect
the classification. */
// Here's a third doc block.
/* And here's a fourth: a different opening delimiter starts a new doc
block even at an identical indent. Whitespace inside the comment
doesn't affect the classification. */
// These are two separate doc blocks,
void foo();
// since they are separated by a code block.
Expand All @@ -34,13 +35,164 @@ void foo();
Architecture
------------

A Visual Studio Code extension in `extensions/VSCode` exchanges messages with the CodeChat Editor Server, located in `server/` (also terms the Server), which also exchanges message with the CodeChat Editor Client (also termed the Client) located in `client/`.
A Visual Studio Code extension in `extensions/VSCode` exchanges messages with
the CodeChat Editor Server, located in `server/` (also termed the Server), which
also exchanges messages with the CodeChat Editor Client (also termed the Client)
located in `client/`.

Project build
-------------

All build commands must be executed from the `server/` directory.

* To build the entire project, execute `./bt build`.
* To format and lint the entire project, execute `./bt flint`.
* To build (bundle) only the Client, execute `./bt client-build`.
* To run tests, execute `cargo test`.

Commenting guide
----------------

This program uses a literate programming approach: comments are prose meant to
be read from top to bottom alongside the code, not annotations bolted onto
individual statements.

`docs/style_guide.cpp` is the project's canonical, reader-facing style guide;
this section is a digest of it aimed at the Rust and TypeScript in this repo.
When asked to change "the style guide", edit that file, and keep the two
consistent.

### What to comment

* Use meaningful, descriptive names for variables, classes, functions, etc. Code
should be as self-documenting as possible.

* Avoid comments when possible. Comments must describe current code, not its
history. Only add comments which supply what self-documenting code cannot.

* Comments must satisfy at least one of these criteria:

1. Document a connection which cannot easily be determined by inspection --
for example, the relationship between a web client HTTP request and the
Server endpoint which handles it.
2. Record behavior discoverable only by running or debugging the code: a
third-party library quirk, a browser workaround, an ordering constraint.
Behavior which can be derived directly from the code should not produce a
comment.
3. Capture design choices, requirements, etc. which specify the overall
purpose of the code at a higher level than the implementation.
4. Link to an external reference (a manual, specification, etc.) which
explains a subtle design choice.
* Do not restate the code. Say what the item does, then add what the reader
cannot derive from the signature:

```rust
// Bad -- the signature already says this.
/// Set the file's contents to the given string.
fn set_contents(&mut self, contents: String);

// Good -- keeps the summary, adds the constraint.
/// Replace the file's contents. The Client autosaves, so this runs on every
/// pause in typing; keep it cheap and idempotent.
fn set_contents(&mut self, contents: String);
```

* Scale a comment's length to its altitude instead of aiming for uniform
brevity: file- and section-level comments carry the design narrative and may
run for dozens of lines (see `server/src/processing/cache.rs`), while a
comment on a single statement is a line or two.

* In new work, mark deferred work with `TODO:` followed by both the task and the
condition which will resolve it, so a later reader knows when it may be
removed. Many existing `TODO`s predate this rule; leave them alone unless you
are already editing that code.

* When implementing equations, place a comment giving the formula, along with an
explanation of the terms used, before the code implementing it. Use
LaTeX-style syntax: $x^2$.

### Where to place comments

Place documentation before the code it describes. In new and edited code,
comment each function parameter individually, and document the return value with
a comment placed immediately before the return type -- including in Rust, where
rustdoc renders neither. Many existing signatures are not yet annotated this
way; add annotations to signatures you touch rather than sweeping the tree:

```rust
/// Phase 1 of hydration: parse the HTML, walk the DOM, then commit the
/// collected facts to the cache.
fn hydrate_dom(
// The HTML to hydrate.
html: &str,
// The cache for the project containing this file.
cache: &Arc<Mutex<Cache>>,
// The parsed, patched DOM plus the walk results needed by later phases.
) -> io::Result<(Rc<Node>, WalkContext)> {
```

### Doc block constraints

Because comments become doc blocks, these mechanical rules apply:

* Hold the indent *and* the delimiter constant across a comment's lines, and
match the indent to that of the code being described.
* Denote paragraphs using an empty comment (`//` or `///`), not an empty line.
* A comment on the same line as code is never a doc block; it stays part of the
code block.

### File structure

Source files follow this template (a few predate it; match it in new files):

1. Crate-level attributes (Rust only).
2. The GPL copyright and license block, copied verbatim from a neighboring file
rather than retyped. In Rust it uses plain `//`, so it stays a doc block
separate from the title which follows it.
3. A single level-1 heading titling the file: the file name in a monospaced font
-- matching the file's actual name -- then `--`, then a short description.
4. The file-level design narrative, if the file needs one.
5. A `Modules` section, if the file has submodules, then an `Imports` section.
In Rust its subsections are `### Standard library`, `### Third-party`, and
`### Local`; the Client and the VSCode extension use their own names, so
follow the file you are editing.
6. The code, organized under further headings which outline the file. Don't skip
heading levels.

Employ Markdown syntax throughout. Use setext underlines (`====` and `----`) for
heading levels 1 and 2, and ATX markers (`###`, `####`) for level 3 and below;
underline the full width of the heading text. Use asterisks for bullets,
emphasis, and strong emphasis. Wrap lines at 80 characters; if the indent
exceeds column 40, wrap at 40 columns past the indent instead of at column 80.

```rust
//! `cache.rs` -- Keep a cache used to store all targets in a project
//! =================================================================
//!
//! The cache stores the location and contents of every target in a project...

// Imports
// -------
//
// ### Standard library
use std::collections::HashMap;
```

### Rust specifics

* Write file-level prose -- the title heading and the design narrative -- with
`//!`, so that it documents the module.
* Use `///` where allowed by rustdoc (functions, structs, enums, traits, and
macros); use `//` otherwise.

### TypeScript specifics

* Use `//` tags instead of `/**` blocks.
* Document parameters as described above instead of using `@param` tags.

### Editing existing comments

Comments describe the code as it now stands. When changing code inside a
documented region, revise the surrounding prose so that it still reads as a
continuous narrative: do not append a new comment beside text which the change
has made stale, and delete comments describing code which no longer exists.
100 changes: 89 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ Switching documents in the IDE likewise switches the document shown in the
CodeChat Editor. Likewise, following hyperlinks in the CodeChat Editor to a
local file loads that file in the IDE, as well as showing it in the Editor.

<h2 id="cc-DscjSxRZHF">Projects</h2>

The CodeChat Editor can either display a single file, or a project. In a
project, the table of contents is displayed on the left, while a file within the
project is displayed on the right. To create a project, simply place a file
named `toc.md` at the root of your project [\[2\]](#notes); its contents define
the table of contents. See the
[new project template](https://github.com/bjones1/CodeChat_Editor/tree/main/new-project-template)
for a simple example.

References to other files
-------------------------

Expand All @@ -129,6 +139,49 @@ docs/
monitor.png
```

<h3 id="cc-TRCKclsxwW">Cross-references</h3>

Any HTML element with an id can be the target of either a hyperlink or a
cross-reference. If the id resides in a file within a [project](#cc-DscjSxRZHF),
then any file in that same project can refer to that id using a hyperlink or
cross-reference. For example:

| Source | Rendered |
| ----------------------------------- | --------------------------------- |
| `[Style guide](#cc-nNZ6Gs2uWD)` | [Style guide](#cc-nNZ6Gs2uWD) |
| `<xref ref="cc-nNZ6Gs2uWD"></xref>` | <xref ref="cc-nNZ6Gs2uWD"></xref> |

In projects, each id must be unique throughout the entire project. To simplify
the creation of unique ids, items assigned an `id="*"` with be replaced with a
unique id, such as `id=cc-DscjSxRZHF`. This autogenerated id isn't automatically
saved; you must make an edit to its containing file in the Client to save the
resulting id.

<h3 id="cc-swJ6a-FiK3">Gathering fragments</h3>

Often, closely-related routines must be scattered across the source tree. For
example, a client's HTTP request and the corresponding server-side endpoint
which responds to that request are usually placed in separate files, even though
these are tightly coupled. The CodeChat Editor therefore supports gathering
these scattered fragments into one central location to better explain the code.
To do so:

1. In a doc block preceding a code fragment to gather, add a `<fragment
id="some_unique_id"></fragment>`. Do this for each fragment to gather. By
default, a fragment includes the doc block it was placed in along with the
next code/doc block. To include additional content, add the `following`
attribute: `<fragment id="some_unique_id"
following="number_of_following_code/doc_blocks_to_include"></fragment>`. For
example, the starting ID for the websocket connection between the CodeChat
Server (written in Rust) and the CodeChat Client (written in TypeScript) both
have `<fragment>` tags.
2. In a doc block or a Markdown file, place an HTML element with both an id and
a `data-gather` attribute, such as `<h4 id="another_unique_id"
data-gather="some_unique_id1 some_unique_id2 ...">Gathered code</h4>`. Below
the the result of a gather tag for these fragments:

<h4 data-gather="cc-kK31yjXjJd cc-Vk22aRyJ3s" id="cc-4YrLCPA4-S">Starting websocket ID</h4>

Images
------

Expand All @@ -144,17 +197,6 @@ The CodeChat Editor disallows drag-and-drop of images, the result is a mess --
the image data is embedded directly in the source file. Avoid this; instead,
place images in a separate file, then reference them as shown above.

Projects
--------

The CodeChat Editor can either display a single file, or a project. In a
project, the table of contents is displayed on the left, while a file within the
project is displayed on the right. To create a project, simply place a file
named `toc.md` at the root of your project [\[2\]](#notes); its contents define
the table of contents. See the
[new project template](https://github.com/bjones1/CodeChat_Editor/tree/main/new-project-template)
for a simple example.

Mathematics
-----------

Expand Down Expand Up @@ -268,6 +310,42 @@ can be directly edited by that package:

![](docs/sample_diagram.drawio.svg)

Research capture
----------------

The VS Code extension can record dissertation study capture events when a
participant explicitly opts in. A participant first registers in the capture
portal, which emails a capture token. In VS Code, run **Manage CodeChat Editor
Capture** or **CodeChat Editor: Enter Capture Token** from the command palette,
paste the token, then turn on consent and recording from the same capture
manager.

The token is imported through the VS Code UI and persisted only in VS Code
SecretStorage. It is never written to workspace settings, repository files, or a
JSON configuration file. The extension asks CaptureWebService for token status;
the status item and capture manager show whether the token is accepted,
rejected, unavailable, or disabled by the portal. The participant ID used in
events comes from that status response, not from the token text.

CodeChat no longer connects directly to the remote capture database and no
longer reads or stores database credentials. The old local JSON database-secret
configuration path has been removed. Capture events now leave CodeChat only by
calling CaptureWebService with the portal-issued bearer token; any database
writer role remains inside the service deployment.

Events are sanitized, written to a durable local FIFO spool in VS Code's global
extension storage, then uploaded to CaptureWebService. Spooled events carry only
a non-secret token hash/service identity so events from an old token are not
uploaded under a new token. Offline recording is allowed only after the same
token and service URL have previously been verified as capture-enabled; a token
disabled by the portal remains disabled while the service is unavailable. If the
network or service is unavailable after the token has been accepted at least
once, queued events remain in the spool and upload as soon as the matching token
and service are available again. The capture service endpoint can be changed in
the user-level `CodeChatEditor.Capture.ServiceBaseUrl` setting; workspace values
are ignored for this token-bearing endpoint. Token-bearing requests require
HTTPS except for localhost development endpoints.

<a id="supported-languages"></a>Supported languages
---------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion builder/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2025 Bryan A. Jones.
# Copyright (C) 2026 Bryan A. Jones.
#
# This file is part of the CodeChat Editor.
#
Expand Down
Loading
Loading