From: Thomas Walker Lynch Date: Mon, 29 Jun 2026 16:00:28 +0000 (+0000) Subject: three state counter X-Git-Url: https://git.reasoningtechnology.com/RT-Manuscript_locator.js?a=commitdiff_plain;h=25d1132201074833d85d6deee129fd39adb24509;p=RT-Style three state counter --- diff --git a/developer/authored/Manuscript.copy/Element/counter.js b/developer/authored/Manuscript.copy/Element/counter.js index 08dd74f..f483927 100644 --- a/developer/authored/Manuscript.copy/Element/counter.js +++ b/developer/authored/Manuscript.copy/Element/counter.js @@ -1,6 +1,6 @@ /* - Processes tags. - Calculates numbering, maintains the stack, manages snapshots, and outputs values for read tags. + Processes tags. + Calculates numbering, maintains the explicit status machine, manages snapshots, and outputs values for read tags. */ (function() { @@ -18,26 +18,81 @@ RT.dict_instance = RT.dict_instance || {}; RT.dict_snapshot = RT.dict_snapshot || {}; - RT.Element.add( function() { - const debug = RT.Debug || { log: function(){} }; - if (debug.log) debug.log('counter', 'Processing counters'); + class CounterMachine { + constructor(first_step_val, style, separator, separator_placement) { + this.list = []; + this.status = 'empty'; // 'empty', 'preamble', 'between' + this.first_step_val = first_step_val; + this.style = style || 'NaturalNumber'; + this.separator = separator || '.'; + this.separator_placement = separator_placement || 'embedded'; + this.count = ''; + } - const root_node = document.documentElement; + enter() { + if (this.status === 'empty') { + this.list.push(this.first_step_val); + this.status = 'preamble'; + } else if (this.status === 'preamble') { + this.list.push(0); // indent appends 0 + this.status = 'preamble'; + } else if (this.status === 'between') { + this.list[this.list.length - 1] += 1; // inc last value + this.status = 'preamble'; + } + this.update_count_string(); + } - function clone_state(state) { - return { - counter: state.counter, - stack: [...state.stack], - empty: [...state.empty], - separator: state.separator, - 'separator-placement': state['separator-placement'], - style: state.style, - 'on-first-step': state['on-first-step'], - count: state.count - }; + exit() { + if (this.status === 'empty') { + console.error("RT-Manuscript Layout Error: Attempted to exit an empty counter scope."); + } else if (this.status === 'preamble') { + this.status = 'between'; + } else if (this.status === 'between') { + this.list.pop(); + this.status = 'between'; + } + this.update_count_string(); + } + + update_count_string() { + if (this.status === 'empty' || this.list.length === 0) { + this.count = ''; + return; + } + + const formatted_list = this.list.map((val, index) => + this.format_count(val, this.style, index) + ); + + let count_str = formatted_list.join(this.separator); + if (this.separator_placement === 'embedded-after') { + count_str += this.separator; + } + this.count = count_str; } - function to_roman(num) { + format_count(num, style, depth) { + if (style === 'roman') return this.to_roman(num).toLowerCase(); + if (style === 'Roman') return this.to_roman(num); + if (style === 'Alpha') return String.fromCharCode(64 + num); + if (style === 'alpha') return String.fromCharCode(96 + num); + + if (style === 'roman-outline') { + const levels = ['Roman', 'Alpha', 'CountingNumber', 'alpha', 'roman']; + const current_style = levels[depth % levels.length]; + return this.format_count(num, current_style, 0); + } + + if (style === 'CountingNumber') { + return (num + 1).toString(); + } + + // Default behavior maps to NaturalNumber + return num.toString(); + } + + to_roman(num) { if (num < 1) return num.toString(); const lookup = {M:1000, CM:900, D:500, CD:400, C:100, XC:90, L:50, XL:40, X:10, IX:9, V:5, IV:4, I:1}; let roman = ''; @@ -50,8 +105,21 @@ return roman; } - function parse_first_step(val_str, style, counter_name) { - if (!val_str) return 1; + clone() { + const copy = new CounterMachine( + this.first_step_val, + this.style, + this.separator, + this.separator_placement + ); + copy.list = [...this.list]; + copy.status = this.status; + copy.count = this.count; + return copy; + } + + static parse_first_step(val_str, style, counter_name) { + if (!val_str) return 0; // Defaulting to 0 to support preamble logic let num = NaN; @@ -88,97 +156,62 @@ } } - if (isNaN(num) || num < 1) { + if (isNaN(num) || num < 0) { console.error(`RT-Manuscript Layout Error: Type mismatch. Invalid 'on-first-step' value '${val_str}' for style '${style}' in counter '${counter_name}'.`); - return 1; + return 0; } return num; } + } - function format_count(num, style, depth) { - if (style === 'roman') return to_roman(num).toLowerCase(); - if (style === 'Roman') return to_roman(num); - if (style === 'Alpha') return String.fromCharCode(64 + num); - if (style === 'alpha') return String.fromCharCode(96 + num); - - if (style === 'roman-outline') { - const levels = ['Roman', 'Alpha', 'Natural', 'alpha', 'roman']; - const current_style = levels[depth % levels.length]; - return format_count(num, current_style, 0); - } - - return num.toString(); - } + RT.Element.add( function() { + const debug = RT.Debug || { log: function(){} }; + if (debug.log) debug.log('counter', 'Processing counters'); + + const root_node = document.documentElement; function walk(node) { if (node.nodeType !== Node.ELEMENT_NODE) return; const tag = node.tagName.toLowerCase(); - let pushed_name = null; + let machine_to_exit = null; if (tag === 'rt·counter·make') { const name = node.getAttribute('counter'); if (name) { - const style = node.getAttribute('style') || 'Natural'; + const style = node.getAttribute('style') || 'NaturalNumber'; const on_first_step_str = node.getAttribute('on-first-step'); + const separator = node.getAttribute('separator'); + const separator_placement = node.getAttribute('separator-placement'); - let first_step_int = parse_first_step(on_first_step_str, style, name); + let first_step_int = CounterMachine.parse_first_step(on_first_step_str, style, name); - RT.dict_instance[name] = { - counter: name, - stack: [0], - empty: [true], - separator: node.getAttribute('separator') || '.', - 'separator-placement': node.getAttribute('separator-placement') || 'embedded', - style: style, - 'on-first-step': on_first_step_str || '1', - on_first_step_int: first_step_int, - count: '' - }; - } - } else if (tag === 'rt·counter·indent') { - const name = node.getAttribute('counter'); - if (name && RT.dict_instance[name]) { - RT.dict_instance[name].stack.push(0); - RT.dict_instance[name].empty.push(true); - pushed_name = name; + RT.dict_instance[name] = new CounterMachine( + first_step_int, + style, + separator, + separator_placement + ); } } else if (tag === 'rt·counter·step') { const name = node.getAttribute('counter'); if (name && RT.dict_instance[name]) { - const state = RT.dict_instance[name]; - const depth = state.stack.length - 1; - - if (state.empty[depth]) { - state.stack[depth] = (depth === 0) ? state.on_first_step_int : 1; - state.empty[depth] = false; - } else { - state.stack[depth] += 1; - } - - const formatted_stack = state.stack.map((val, index) => - format_count(val, state.style, index) - ); - - let count_str = formatted_stack.join(state.separator); - if (state['separator-placement'] === 'embedded-after') { - count_str += state.separator; - } + const active_machine = RT.dict_instance[name]; - state.count = count_str; + active_machine.enter(); + machine_to_exit = active_machine; } } else if (tag === 'rt·counter·snapshot') { const counter_name = node.getAttribute('counter'); const snapshot_name = node.getAttribute('snapshot'); if (counter_name && snapshot_name && RT.dict_instance[counter_name]) { - const state = RT.dict_instance[counter_name]; - const depth = state.stack.length - 1; + const active_machine = RT.dict_instance[counter_name]; - if (state.empty[depth]) { - console.error(`RT-Manuscript Layout Error: Attempted to snapshot an empty counter '${counter_name}' at snapshot '${snapshot_name}'. A person must use before taking a snapshot.`); + if (active_machine.status === 'empty') { + console.error(`RT-Manuscript Layout Error: Attempted to snapshot an empty counter '${counter_name}' at snapshot '${snapshot_name}'. A step is required first.`); } else { - RT.dict_snapshot[snapshot_name] = clone_state(state); + RT.dict_snapshot[snapshot_name] = active_machine.clone(); } } } @@ -189,25 +222,25 @@ child = child.nextElementSibling; } - if (pushed_name) { - RT.dict_instance[pushed_name].stack.pop(); - RT.dict_instance[pushed_name].empty.pop(); + if (machine_to_exit) { + machine_to_exit.exit(); } } walk(root_node); - const reads = root_node.querySelectorAll('RT·Counter·read'); + const reads = root_node.querySelectorAll('RT·counter·read, rt·counter·read'); for (let i = 0; i < reads.length; i++) { const snapshot_name = reads[i].getAttribute('snapshot'); const key = reads[i].getAttribute('key') || 'count'; if (snapshot_name && RT.dict_snapshot[snapshot_name]) { - const value = RT.dict_snapshot[snapshot_name][key]; + const snapshot_machine = RT.dict_snapshot[snapshot_name]; + const value = snapshot_machine[key]; reads[i].innerHTML = (value !== undefined) ? value : `[Missing key: ${key}]`; } else { reads[i].innerHTML = `[Unknown snapshot: ${snapshot_name}]`; - console.error(`RT-Manuscript Layout Error: failed. No snapshot named '${snapshot_name}' found in the dictionary.`); + console.error(`RT-Manuscript Layout Error: failed. No snapshot named '${snapshot_name}' found.`); } } }); diff --git a/developer/authored/Manuscript.copy/Theme/inverse_wheat.js b/developer/authored/Manuscript.copy/Theme/inverse_wheat.js index daffde2..5c5c05a 100644 --- a/developer/authored/Manuscript.copy/Theme/inverse_wheat.js +++ b/developer/authored/Manuscript.copy/Theme/inverse_wheat.js @@ -1,4 +1,4 @@ -// Theme/inverse_wheat.js +// Theme/inverse_wheat_DS.js window.RT = window.RT || {}; window.RT.theme_library = window.RT.theme_library || {}; @@ -6,45 +6,45 @@ window.RT.theme_library = window.RT.theme_library || {}; window.RT.theme_library['inverse_wheat'] = { meta: { is_dark: true, - name: "inverse_wheat" + name: "inverse_wheat_DS" }, surface: { - 0: "oklch(0.15 0 0)", - 1: "oklch(0.18 0 0)", - 2: "oklch(0.21 0 0)", - 3: "oklch(0.24 0 0)", - input: "oklch(0.19 0 0)", - code: "oklch(0.17 0 0)", - select: "oklch(0.30 0.05 80)" + 0: "oklch(0.157 0 0)", + 1: "oklch(0.198 0 0)", + 2: "oklch(0.221 0 0)", + 3: "oklch(0.240 0 0)", + input: "oklch(0.210 0 0)", + code: "oklch(0.204 0 0)", + select: "oklch(0.358 0.073 88)" }, content: { - main: "oklch(0.85 0.05 90)", - muted: "oklch(0.70 0.03 90)", - subtle: "oklch(0.50 0.02 90)", - inverse: "oklch(0.15 0 0)" + main: "oklch(0.927 0.050 97)", + muted: "oklch(0.699 0.030 78)", + subtle: "oklch(0.522 0.022 82)", + inverse: "oklch(0.157 0 0)" }, brand: { - primary: "oklch(0.75 0.15 80)", - secondary: "oklch(0.65 0.12 70)", - tertiary: "oklch(0.60 0.10 60)", - link: "oklch(0.75 0.15 85)" + primary: "oklch(0.841 0.173 85)", + secondary: "oklch(0.827 0.135 78)", + tertiary: "oklch(0.795 0.081 66)", + link: "oklch(0.865 0.177 90)" }, border: { - faint: "oklch(0.25 0.01 90)", - regular: "oklch(0.35 0.02 90)", - strong: "oklch(0.45 0.03 90)" + faint: "oklch(0.280 0.018 78)", + regular: "oklch(0.386 0.028 82)", + strong: "oklch(0.533 0.041 77)" }, state: { - success: "oklch(0.60 0.12 130)", - warning: "oklch(0.65 0.15 50)", - error: "oklch(0.55 0.15 25)", - info: "oklch(0.60 0.10 240)" + success: "oklch(0.671 0.168 137)", + warning: "oklch(0.767 0.159 68)", + error: "oklch(0.591 0.172 24)", + info: "oklch(0.661 0.078 232)" }, syntax: { - keyword: "oklch(0.70 0.15 50)", - string: "oklch(0.75 0.10 130)", - func: "oklch(0.80 0.12 85)", - comment: "oklch(0.55 0.02 90)" + keyword: "oklch(0.825 0.146 72)", + string: "oklch(0.804 0.132 122)", + func: "oklch(0.756 0.134 39)", + comment: "oklch(0.573 0.035 78)" }, page: { width: "6.5in", diff --git a/developer/authored/Manuscript.copy/Theme/inverse_wheat_DS.js b/developer/authored/Manuscript.copy/Theme/inverse_wheat_DS.js deleted file mode 100644 index 13c70fd..0000000 --- a/developer/authored/Manuscript.copy/Theme/inverse_wheat_DS.js +++ /dev/null @@ -1,62 +0,0 @@ -// Theme/inverse_wheat_DS.js - -window.RT = window.RT || {}; -window.RT.theme_library = window.RT.theme_library || {}; - -window.RT.theme_library['inverse_wheat_DS'] = { - meta: { - is_dark: true, - name: "inverse_wheat_DS" - }, - surface: { - 0: "oklch(0.157 0 0)", - 1: "oklch(0.198 0 0)", - 2: "oklch(0.221 0 0)", - 3: "oklch(0.240 0 0)", - input: "oklch(0.210 0 0)", - code: "oklch(0.204 0 0)", - select: "oklch(0.358 0.073 88)" - }, - content: { - main: "oklch(0.927 0.050 97)", - muted: "oklch(0.699 0.030 78)", - subtle: "oklch(0.522 0.022 82)", - inverse: "oklch(0.157 0 0)" - }, - brand: { - primary: "oklch(0.841 0.173 85)", - secondary: "oklch(0.827 0.135 78)", - tertiary: "oklch(0.795 0.081 66)", - link: "oklch(0.865 0.177 90)" - }, - border: { - faint: "oklch(0.280 0.018 78)", - regular: "oklch(0.386 0.028 82)", - strong: "oklch(0.533 0.041 77)" - }, - state: { - success: "oklch(0.671 0.168 137)", - warning: "oklch(0.767 0.159 68)", - error: "oklch(0.591 0.172 24)", - info: "oklch(0.661 0.078 232)" - }, - syntax: { - keyword: "oklch(0.825 0.146 72)", - string: "oklch(0.804 0.132 122)", - func: "oklch(0.756 0.134 39)", - comment: "oklch(0.573 0.035 78)" - }, - page: { - width: "6.5in", - min_height: "9in", - padding: "0.5in 1in", - margin: "20px auto", - bg_color: "oklch(0.95 0.02 90)", - border_color: "oklch(0.85 0.02 90)", - text_color: "oklch(0.20 0.02 25)", - shadow: "0 4px 15px rgba(0,0,0,0.1)" - }, - custom_css: ` - img.rt-diagram { filter: invert(1) hue-rotate(180deg); } - ` -}; diff --git a/developer/authored/Manuscript.copy/Theme/manifest.js b/developer/authored/Manuscript.copy/Theme/manifest.js index 0b06378..2013296 100644 --- a/developer/authored/Manuscript.copy/Theme/manifest.js +++ b/developer/authored/Manuscript.copy/Theme/manifest.js @@ -5,7 +5,6 @@ window.RT = window.RT || {}; (function() { const themes = [ 'inverse_wheat' - ,'inverse_wheat_DS' ,'golden_wheat' ,'wheat' ]; diff --git a/developer/document/counter_status.txt b/developer/document/counter_status.txt new file mode 100644 index 0000000..951c56c --- /dev/null +++ b/developer/document/counter_status.txt @@ -0,0 +1,97 @@ + +-------------------------------------------------------------------------------- +2026-06-29 15:31:50 Z + + Mile marker counters count when they are found in the walk. They have no + scope, or at least that scope extends until the next step operation. + + In contract, scoped counters have a value that applies within a scope. + The problem is the 'between' scope areas, where the parent scope is + in effect. Sections in a document do not have in between areas, for example, + but code in a program does. + + This approach can do either. + + For mile markers, use the full length count. The scoping is only + necessary for indention, the between counts carry the count down to + the next count. + + For scoped count, when the state is 'between', drop the last + member of the list when reporting the count. If the list has + only one member, then dropping it leaves the status 'empty'. + + + make("A"){}: (empty,) + ^ scoped by name + + snapshot() -> (empty,) + + step("A"){ + + snapshot() == (preamble,[0]) + + step("A"){ + snapshot() == (preamble,[0,0]) + } + + snapshot() == (between,[0,0]) + + step("A"){ + snapshot() == (preamble,[0,1]) + } + + snapshot() == (between,[0,1]) + + } + + snapshot() == (between,[0]) + + step("A"){ : (rest,[1]) + + snapshot() == (preamble,[1]) + + step("A"){ + snapshot() == (preamble,[1,0]) + } + + snapshot() == (between,[1,0]) + + step("A"){ + snapshot() == (preamble,[1,1]) + } + + } + + snapshot() == (between,[1]) + + ---- + notes: + + -I use the word 'status' instead of 'state' so as to disambiguate other eventualities of state in the same context. (This was done when describing second order machines in TTCA) + + -'init' create the list and give it an initial value + -`inc` means to add one to the last counter position + -'indent` is to append a 0 + + keep a two status window [status_current, status_prior] or status_current + + make(): status -> empty, there is no list + + upon entry to step: + + empty: init + preamble: indent + between: inc + + status -> preamble + + continue with scoped code + + on step closing: + + empty: throw error + preamble: keep the counter value + between: drop last value from counter + + status -> between + diff --git a/tester/authored/Counter/test_0.html b/tester/authored/Counter/test_0.html index ee9c650..1abfa28 100644 --- a/tester/authored/Counter/test_0.html +++ b/tester/authored/Counter/test_0.html @@ -1,68 +1,216 @@ - + - Manuscript Counter Test Bench - + Counter Status Machine Diagnostics + + + + + + +
// Initialize scoped counter
+ +
make("A"){} :
+ +
// attempt to snapshot an empty counter will generate an error in the console
+
+ snapshot() -> ( + + , + [] + ) +
+ +
step("A"){
+ +
+
+ snapshot() == ( + + , + [] + ) + // Expected: ( preamble ,[0] ) +
+ +
step("A"){
+ +
+
+ snapshot() == ( + + , + [] + ) + // Expected: ( preamble ,[0 ,0] ) +
+
+
+
}
+ +
+ snapshot() == ( + + , + [] + ) + // Expected: ( between ,[0 ,0] ) +
+ +
step("A"){
+ +
+
+ snapshot() == ( + + , + [] + ) + // Expected: ( preamble ,[0 ,1] ) +
+
+
+
}
+ +
+ snapshot() == ( + + , + [] + ) + // Expected: ( between ,[0 ,1] ) +
+
+
+
}
+ +
+ snapshot() == ( + + , + [] + ) // Expected: ( between ,[0] ) +
+ +
step("A"){
+ +
+
+ snapshot() == ( + + , + [] + ) // Expected: ( preamble ,[1] ) +
+ +
step("A"){
+ +
+
+ snapshot() == ( + + , + [] + ) // Expected: ( preamble ,[1 ,0] ) +
+
+
+
}
+ +
+ snapshot() == ( + + , + [] + ) // Expected: ( between ,[1 ,0] ) +
+ +
step("A"){
+ +
+
+ snapshot() == ( + + , + [] + ) // Expected: ( preamble ,[1 ,1] ) +
+
+
+
}
+
+
+
}
- - -

Primary Analysis

-

- Observe the data in Figure - - - . -

- - -

- Detail view of the left quadrant: Figure - - - . -

- -

- Detail view of the right quadrant: Figure - - - . -

- - -

- Microscopic inspection: Figure - - - . -

-
-
- -

Secondary Analysis

-

- Proceeding to the next major component, shown in Figure - - - . -

- -
-

Forward Reference Validation

-

This text proves we can accurately call back to earlier elements.

-
    -
  • The primary analysis was Figure .
  • -
  • The left quadrant was Figure .
  • -
  • The microscopic view was Figure .
  • -
+
+ snapshot() == ( + + , + [] + ) // Expected: ( between ,[1] )