Add macOS UI initial support - #58
Conversation
Signed-off-by: Francesco Bigiarini <francesco.bigiarini@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR adds initial macOS SwiftUI UI scaffolding for Mojibake while also renaming and redesigning the “display width” API into a stricter “terminal width” API (NFC-stable, grapheme-aware, emoji-aware, and control/multiline rejecting), updating generators, docs, CLI, WASM/TypeScript, C++ wrapper, fuzzing, and tests accordingly.
Changes:
- Replaced
mjb_display_width/mjb_width_contextwithmjb_terminal_width/mjb_terminal_width_profile, updating truncation helpers and all bindings/docs. - Updated CLI break JSON output (
display_width→terminal_width) and expanded terminal-width semantics and error reporting. - Added a new macOS SwiftUI app skeleton under
src/ui/with multiple feature views (codepoint, emoji, breaks, bidi, normalization, filtering, terminal width).
Reviewed changes
Copilot reviewed 48 out of 51 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| utils/generate/types.ts | Renames generated enum value lists to terminal-width profiles. |
| utils/generate/html-function.ts | Updates HTML generator to use mjb_terminal_width_profile selects. |
| utils/generate/functions.ts | Renames API section + updates function metadata/docs for terminal width + truncation width APIs. |
| utils/generate/commands/generate-site.ts | Renames the site section from Display width to Terminal width. |
| tests/test.h | Renames the test entry point declaration to test_terminal_width. |
| tests/test.c | Updates test runner registration from display to terminal_width. |
| tests/terminal-width.c | Adds dedicated C tests for mjb_terminal_width. |
| tests/shell/break-json.cmake | Updates expected JSON field name to terminal_width. |
| tests/segmentation.c | Updates truncate-width tests to use terminal width profiles and new behavior. |
| tests/ext/cpp/mojibake.cpp | Updates C++ wrapper tests for terminal_width. |
| tests/example.c | Updates generated API examples/tests to terminal-width names and constants. |
| tests/display.c | Removes old display-width tests. |
| tests/CMakeLists.txt | Removes display.c, adds terminal-width.c, updates CTest registration. |
| tests/break-word.c | Updates truncate-word-width tests to use terminal width profiles. |
| TESTS.md | Refreshes coverage totals and replaces displayWidth coverage entries with terminalWidth equivalents. |
| src/ui/Mojibake/Mojibake/TerminalWidthView.swift | Adds SwiftUI terminal-width UI + helpers. |
| src/ui/Mojibake/Mojibake/NormalizationView.swift | Adds SwiftUI normalization UI calling mjb_normalize. |
| src/ui/Mojibake/Mojibake/MojibakeApp.swift | Adds macOS app entry point and About panel. |
| src/ui/Mojibake/Mojibake/Mojibake-Bridging-Header.h | Adds bridging header to import Mojibake C API. |
| src/ui/Mojibake/Mojibake/FilterView.swift | Adds SwiftUI filter UI calling mjb_filter. |
| src/ui/Mojibake/Mojibake/EmojiView.swift | Adds SwiftUI emoji inspection UI using emoji APIs. |
| src/ui/Mojibake/Mojibake/ContentView.swift | Adds navigation shell for the macOS app. |
| src/ui/Mojibake/Mojibake/CodepointView.swift | Adds SwiftUI codepoint lookup UI using mjb_codepoint_info. |
| src/ui/Mojibake/Mojibake/CharacterDetailsView.swift | Adds SwiftUI codepoint details rendering + internal deep-linking. |
| src/ui/Mojibake/Mojibake/CharacterDetails.swift | Adds model builder for codepoint detail sections (encoding, normalization, properties, emoji). |
| src/ui/Mojibake/Mojibake/CaseView.swift | Adds SwiftUI case-mapping UI calling mjb_map_case. |
| src/ui/Mojibake/Mojibake/BreaksView.swift | Adds SwiftUI breaks UI calling segmentation iterators. |
| src/ui/Mojibake/Mojibake/BidiView.swift | Adds SwiftUI bidi visualization UI calling bidi APIs. |
| src/ui/Mojibake/Mojibake/Assets.xcassets/Contents.json | Adds Xcode asset catalog metadata. |
| src/ui/Mojibake/Mojibake/Assets.xcassets/AppIcon.appiconset/Contents.json | Adds AppIcon set metadata. |
| src/ui/Mojibake/Mojibake/Assets.xcassets/AccentColor.colorset/Contents.json | Adds AccentColor set metadata. |
| src/ui/Mojibake/Mojibake.xcodeproj/project.xcworkspace/contents.xcworkspacedata | Adds Xcode workspace metadata. |
| src/ui/Mojibake/Mojibake.xcodeproj/project.pbxproj | Adds Xcode project configuration for the macOS app. |
| src/terminal-width.c | Adds new core implementation of terminal-cell width estimation. |
| src/shell/commands/break.c | Updates CLI break output (JSON + plain) to use terminal width and report unsupported inputs. |
| src/segmentation.c | Updates grapheme width truncation to call mjb_terminal_width. |
| src/mojibake.h | Replaces width-context enum/API declarations with terminal-width equivalents. |
| src/display.c | Removes the old display-width implementation. |
| src/cpp/mojibake.hpp | Renames wrapper to terminal_width and updates truncate-width wrappers accordingly. |
| src/CMakeLists.txt | Removes display.c, adds terminal-width.c, updates WASM export list. |
| src/break-word.c | Updates word width truncation to call mjb_terminal_width. |
| src/api/tests/index.ts | Updates TS tests to terminalWidth and TerminalWidthProfile. |
| src/api/mojibake.d.ts | Updates WASM module typings to terminal-width exports and argument naming. |
| src/api/index.ts | Renames WidthContext → TerminalWidthProfile and displayWidth → terminalWidth in the TS API. |
| README.md | Updates feature list to “Terminal width” and new API names. |
| fuzz/fuzz.c | Updates fuzz harness to call terminal width + updated profile enum range. |
| CONFORMANCE_REQUIREMENTS.md | Updates conformance notes and evidence table for terminal-width policy. |
| CHANGELOG.md | Documents the rename and behavior changes (NFC stability, grapheme awareness, emoji handling, rejection rules). |
| API.md | Updates generated API docs for terminal width + truncation width functions. |
| AGENTS.md | Updates module list references from display.c to terminal-width.c. |
| .gitignore | Adds ignores for Xcode/Swift artifacts under src/ui/. |
Files not reviewed (1)
- src/ui/Mojibake/Mojibake.xcodeproj/project.xcworkspace/contents.xcworkspacedata: Generated file
Comments suppressed due to low confidence (9)
src/ui/Mojibake/Mojibake/TerminalWidthView.swift:606
- This
switchin a computed property doesn’t return aColorfrom each case, which will not compile. Add explicitreturnstatements.
src/ui/Mojibake/Mojibake/TerminalWidthView.swift:675 invisibleNameis declared to returnString, but theswitchcases don’t return anything, so this won’t compile. Add explicitreturnstatements for each case.
src/ui/Mojibake/Mojibake/FilterView.swift:43- This
switchin a computed property doesn’t return aStringfrom each case, so the getter won’t compile. Add explicitreturnstatements.
src/ui/Mojibake/Mojibake/CaseView.swift:40 - This
switchin a computed property doesn’t return aStringfrom each case, so the getter won’t compile. Add explicitreturnstatements.
var constantName: String {
switch self {
case .upper:
"MJB_CASE_UPPER"
case .lower:
src/ui/Mojibake/Mojibake/BidiView.swift:318
directionNameis declared to returnString, but theswitchcases don’t return anything, so this won’t compile. Add explicitreturnstatements.
private static func directionName(_ direction: mjb_direction) -> String {
switch direction {
case MJB_DIRECTION_LTR:
"Left-to-right"
case MJB_DIRECTION_RTL:
"Right-to-left"
src/ui/Mojibake/Mojibake/BreaksView.swift:69
- These
switchblocks in computed properties don’t return values from each case, so the getters won’t compile. Add explicitreturnstatements (here and in similar switch-based getters in this file).
var symbol: String {
switch self {
case .mandatory:
"!"
case .noBreak:
src/ui/Mojibake/Mojibake/BreaksView.swift:91
- This
switchin a computed property doesn’t return aColorfrom each case, so the getter won’t compile. Add explicitreturnstatements.
var color: Color {
switch self {
case .mandatory:
.orange
case .noBreak:
src/ui/Mojibake/Mojibake/BreaksView.swift:630
- This
switchis inside a computed property that returnsUInt32?, but the cases don’t return values, so it won’t compile. Add explicitreturnstatements for each case.
private var variationSelectorNumber: UInt32? {
switch scalar.value {
case 0xFE00 ... 0xFE0F:
scalar.value - 0xFE00 + 1
case 0xE0100 ... 0xE01EF:
src/ui/Mojibake/Mojibake/EmojiView.swift:172
qualificationNameis declared to returnString, but theswitchcases don’t return anything, so this won’t compile. Add explicitreturnstatements.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| var value: mjb_normalization { | ||
| switch self { | ||
| case .nfc: | ||
| MJB_NORMALIZATION_NFC | ||
| case .nfd: | ||
| MJB_NORMALIZATION_NFD | ||
| case .nfkc: | ||
| MJB_NORMALIZATION_NFKC | ||
| case .nfkd: | ||
| MJB_NORMALIZATION_NFKD | ||
| } | ||
| } | ||
|
|
||
| var description: String { | ||
| switch self { | ||
| case .nfc: | ||
| "Canonical decomposition followed by canonical composition" | ||
| case .nfd: | ||
| "Canonical decomposition" | ||
| case .nfkc: | ||
| "Compatibility decomposition followed by canonical composition" | ||
| case .nfkd: | ||
| "Compatibility decomposition" | ||
| } | ||
| } |
| var type: mjb_map_case_type { | ||
| switch self { | ||
| case .upper: | ||
| MJB_CASE_UPPER | ||
| case .lower: | ||
| MJB_CASE_LOWER | ||
| case .title: | ||
| MJB_CASE_TITLE | ||
| case .casefold: | ||
| MJB_CASE_CASEFOLD | ||
| case .casefoldSimple: | ||
| MJB_CASE_CASEFOLD_SIMPLE | ||
| } | ||
| } |
| var systemImage: String { | ||
| switch self { | ||
| case .codepoint: | ||
| "character.cursor.ibeam" | ||
| case .emoji: | ||
| "face.smiling" | ||
| case .case: | ||
| "textformat.abc" | ||
| case .breaks: | ||
| "text.word.spacing" | ||
| case .bidi: | ||
| "arrow.left.arrow.right" | ||
| case .terminalWidth: | ||
| "ruler" | ||
| case .normalize: | ||
| "textformat" | ||
| case .filter: | ||
| "line.3.horizontal.decrease" | ||
| } | ||
| } |
| private static func sequenceTypeName(_ type: mjb_emoji_sequence_type) -> String { | ||
| switch type { | ||
| case MJB_EMOJI_SEQUENCE_NONE: | ||
| "None" | ||
| case MJB_EMOJI_SEQUENCE_BASIC: | ||
| "Basic" | ||
| case MJB_EMOJI_SEQUENCE_KEYCAP: | ||
| "Keycap" | ||
| case MJB_EMOJI_SEQUENCE_FLAG: | ||
| "Flag" | ||
| case MJB_EMOJI_SEQUENCE_TAG: | ||
| "Tag" | ||
| case MJB_EMOJI_SEQUENCE_MODIFIER: | ||
| "Modifier" | ||
| case MJB_EMOJI_SEQUENCE_ZWJ: | ||
| "ZWJ" | ||
| case MJB_EMOJI_SEQUENCE_TEXT_VARIATION: | ||
| "Text variation" | ||
| case MJB_EMOJI_SEQUENCE_EMOJI_VARIATION: | ||
| "Emoji variation" | ||
| default: | ||
| "Unknown" | ||
| } | ||
| } |
No description provided.