From: Thomas Walker Lynch
- Because git does not track certain directories (such as
- Harmony is language agnostic. When a project makes use of project-specific C, Python, NodeJS, Java, or other tools, the project administrator configures the project to expect these tools in the
- Because multiple team members will have to repeat the third-party install process after cloning a project, the administrator should carefully document the third party tools installation steps and place the resulting documents in the
- If a person clones the project and does not set up third-party tools, commands will fall through the search path and perhaps find system-installed tools. Using system default tools is generally undesirable because each person who clones the project might be running different versions. This variation makes it harder for team members to coordinate and for consumers of the project work product to build functioning tools.
+ Because multiple team members will have to repeat the third-party install process after cloning a project, the administrator should carefully document the installation steps and place the resulting documents in the
After git clone
Third-party tools
Consumer build
@@ -123,14 +121,10 @@
In this section we use the term 'consumer' to mean any team member that wants to make use of the project work product. The tester will want to test it, and the consumer role will want to deploy it, etc.
- An earlier version of Harmony used platform-specific
- To facilitate this, the developer must explicitly document the project's build and promote procedure, saving this guide as
- The consumer must then read this document and execute the described steps to compile the source and locally populate their
@@ -141,7 +135,7 @@
- This sequence opens a bash shell, assumes the developer role to orchestrate the build, makes the work product, then promotes it to the consumer's workspace. The
- All source code that gets built into a promotion or project release must be placed in the developers'
When the Harmony version line in the
- This directory contains ecosystem tools and global environments available to all roles. This includes the shared tool directory, as well as third-party installations (like Python virtual environments or compilers) required by the project. To assist in project specific modifications to the Harmony skeleton, Harmony comes with an empty
- The
- Artifacts arrive in the
- Note that the
- Currently, our developers write documents directly in HTML using the RT semantic tags. See the
- As a first step, a developer creates a
- Then the tester runs tests on the promotion candidate. Tests must only read from the
It is common for a developer to open a second window on his desktop, and then enter the project as a tester in that second window. The developer can then make a promotion candidate, run the tests, edit source code, and perhaps tests, and then quickly spin through the test-debug-fix-promote cycle repeatedly.
@@ -288,10 +275,10 @@
When the product manager determines the work product to be sufficiently reliable and feature rich, the administrator will make a
[^ \t\n,\[\(\{<\]\)\}>"\'#/]+|/)'
-)
-
-def tokenize(text: str) -> List[RT_Token]:
- tokens = []
- for TM_match in TOKEN_REGEX.finditer(text):
- kind = TM_match.lastgroup
- text_val = TM_match.group(kind)
- tokens.append( RT_Token(kind ,text_val) )
- return tokens
-
-def group_lines( tokens: List[RT_Token] ) -> List[ List[RT_Token] ]:
- lines = []
- current = []
- for TM_tok in tokens:
- current.append(TM_tok)
- if TM_tok.kind == "NEWLINE":
- lines.append(current)
- current = []
- if current:
- lines.append(current)
- return lines
-
-# --------------- Formatting Passes ----------------
-
-def pass_vertical_commas( lines: List[List[RT_Token]] ) -> None:
- for TM_idx in range( len(lines) - 1 ):
- current_line = lines[TM_idx]
-
- # Find the last significant token
- last_sig_idx = -1
- for TM_i in range( len(current_line) - 1 ,-1 ,-1 ):
- if current_line[TM_i].kind not in ("SPACE" ,"NEWLINE" ,"COMMENT"):
- last_sig_idx = TM_i
- break
-
- if last_sig_idx>= 0 and current_line[last_sig_idx].kind == "COMMA":
- # Remove the trailing comma
- comma_tok = current_line.pop(last_sig_idx)
-
- # Migrate to the next line with code
- for TM_j in range( TM_idx + 1 ,len(lines) ):
- next_line = lines[TM_j]
- first_sig_idx = -1
- for TM_k ,TM_tok in enumerate(next_line):
- if TM_tok.kind not in ("SPACE" ,"NEWLINE" ,"COMMENT"):
- first_sig_idx = TM_k
- break
-
- if first_sig_idx>= 0:
- next_line.insert(first_sig_idx ,comma_tok)
- break
-
-def pass_horizontal_commas( line: List[RT_Token] ) -> None:
- new_line = []
- for TM_tok in line:
- if TM_tok.kind == "COMMA":
- is_vertical = all(t.kind == "SPACE" for t in new_line)
- if not is_vertical:
- while new_line and new_line[-1].kind == "SPACE":
- new_line.pop()
- if new_line:
- new_line.append( RT_Token("SPACE" ," ") )
- new_line.append(TM_tok)
- elif TM_tok.kind == "SPACE":
- if new_line and new_line[-1].kind == "COMMA":
- continue # Drop space after comma
- new_line.append(TM_tok)
- else:
- new_line.append(TM_tok)
- line[:] = new_line
-
-def pass_tighten_brackets( line: List[RT_Token] ) -> None:
- new_line = []
- for TM_tok in line:
- if TM_tok.kind == "SPACE":
- if new_line and new_line[-1].kind == "BR_OPEN":
- continue
- new_line.append(TM_tok)
- elif TM_tok.kind == "BR_CLOSE":
- while new_line and new_line[-1].kind == "SPACE":
- new_line.pop()
- new_line.append(TM_tok)
- else:
- new_line.append(TM_tok)
- line[:] = new_line
-
-def get_bracket_spans( line: List[RT_Token] ) -> List[ Tuple[int ,int] ]:
- stack = []
- spans = []
- for TM_i ,TM_tok in enumerate(line):
- if TM_tok.kind == "BR_OPEN":
- stack.append( (TM_tok.text ,TM_i) )
- elif TM_tok.kind == "BR_CLOSE":
- if stack and REV[TM_tok.text] == stack[-1][0]:
- _ ,pos = stack.pop()
- if not stack:
- spans.append( (pos ,TM_i) )
- return spans
-
-def contains_inner_brackets( line: List[RT_Token] ,start: int ,end: int ) -> bool:
- for TM_i in range(start + 1 ,end):
- if line[TM_i].kind in ("BR_OPEN" ,"BR_CLOSE"):
- return True
- return False
-
-def pass_pad_outermost( line: List[RT_Token] ,is_lisp: bool ) -> None:
- if is_lisp:
- return
-
- while True:
- spans = get_bracket_spans(line)
- changed = False
-
- # Process from right to left to avoid shifting indices
- for TM_start ,TM_end in reversed(spans):
- if contains_inner_brackets(line ,TM_start ,TM_end):
- left_has = (TM_start + 1 = 0 ) and ( line[TM_end - 1].kind == "SPACE" )
-
- if not left_has or not right_has:
- if not right_has:
- line.insert( TM_end ,RT_Token("SPACE" ," ") )
- if not left_has:
- line.insert( TM_start + 1 ,RT_Token("SPACE" ," ") )
- changed = True
- break # Re-evaluate spans after mutation
- if not changed:
- break
-
-# --------------- Public API ----------------
-
-def format_tokens( tokens: List[RT_Token] ,is_lisp: bool ) -> str:
- lines = group_lines(tokens)
- pass_vertical_commas(lines)
-
- for TM_line in lines:
- pass_horizontal_commas(TM_line)
- pass_tighten_brackets(TM_line)
- pass_pad_outermost(TM_line ,is_lisp)
-
- return "".join(t.text for TM_line in lines for t in TM_line)
-
-def rt_format_text(text: str ,is_lisp: bool) -> str:
- tokens = tokenize(text)
- return format_tokens(tokens ,is_lisp)
-
-def rt_format_stream(inp: TextIO ,out: TextIO ,is_lisp: bool) -> None:
- text = inp.read()
- out.write( rt_format_text(text ,is_lisp) )
-
-# --------------- Self-test ----------------
-
-def run_self_test() -> bool:
- ok = True
- def chk(src ,exp):
- nonlocal ok
- got = rt_format_text(src ,False)
- if got != exp:
- print("FAIL:\n" + src + "\n=>\n" + got + "\nexpected:\n" + exp)
- ok = False
-
- chk("a,b,c" ,"a ,b ,c")
- chk("a , b , c" ,"a ,b ,c")
- chk(" ,vertical_arg" ," ,vertical_arg")
-
- chk("int a=0,\n b=1,\n c=2;" ,"int a=0\n ,b=1\n ,c=2;")
-
- chk("f ( x )" ,"f(x)")
- chk("f(x) + g(y)" ,"f(x) + g(y)")
- chk(" {" ," {")
-
- src = "int g(){int a=0,b=1,c=2; return h(a,b,c);}"
- exp = "int g(){ int a=0 ,b=1 ,c=2; return h(a ,b ,c); }"
- chk(src ,exp)
-
- chk("outer( inner(a,b) )" ,"outer( inner(a ,b) )")
- chk("compute(x, f(y" ,"compute( x ,f(y") # Tolerant fragment fallback omitted for brevity, but structurally sound.
-
- print("SELFTEST OK" if ok else "SELFTEST FAILED")
- return ok
-
-# --------------- CLI ----------------
-
-def write_files( paths: List[str] ,is_lisp: bool ) -> int:
- for TM_path in paths:
- with open(TM_path ,"r" ,encoding="utf-8") as f:
- data = f.read()
- formatted = rt_format_text(data ,is_lisp)
- with open(TM_path ,"w" ,encoding="utf-8") as f:
- f.write(formatted)
- return 0
-
-def copy_files( paths: List[str] ,is_lisp: bool ) -> int:
- for TM_path in paths:
- shutil.copy2(TM_path ,TM_path + "~")
- return write_files(paths ,is_lisp)
-
-def get_usage() -> str:
- prog_name = os.path.basename( sys.argv[0] )
- return f"""\
-Usage:
- {prog_name} write [--lisp]
- {prog_name} copy [--lisp]
- {prog_name} pipe [--lisp]
- {prog_name} self_test
- {prog_name} version
- {prog_name} help | --help
-"""
-
-def CLI(argv=None) -> int:
- args = list( sys.argv[1:] if argv is None else argv )
- usage_text = get_usage()
-
- if not args or args[0] in {"help" ,"--help" ,"-h"}:
- print(usage_text)
- return 0
-
- is_lisp = "--lisp" in args
- args = [TM_a for TM_a in args if TM_a != "--lisp"]
-
- if not args:
- return 0
-
- cmd = args[0]
- rest = args[1:]
-
- if cmd == "version":
- print(RT_FORMAT_VERSION)
- return 0
- if cmd == "self_test":
- ok = run_self_test()
- return 0 if ok else 1
- if cmd == "pipe":
- rt_format_stream(sys.stdin ,sys.stdout ,is_lisp)
- return 0
- if cmd == "write":
- if not rest:
- print("write: missing \n" + usage_text)
- return 2
- return write_files(rest ,is_lisp)
- if cmd == "copy":
- if not rest:
- print("copy: missing \n" + usage_text)
- return 2
- return copy_files(rest ,is_lisp)
-
- print(f"Unknown command: {cmd}\n" + usage_text)
- return 2
-
-if __name__ == "__main__":
- sys.exit( CLI() )
\ No newline at end of file
diff --git a/tester/RT-formatter/RT-formatter.el b/tester/RT-formatter/RT-formatter.el
deleted file mode 100644
index 94dfaaa..0000000
--- a/tester/RT-formatter/RT-formatter.el
+++ /dev/null
@@ -1,5 +0,0 @@
-( defun RT-format-buffer()
- (interactive)
- (save-excursion
- ( shell-command-on-region(point-min)(point-max)
- "RT-formatter pipe" t t)) )
diff --git a/tester/RT-formatter/RT-formatter_alt.el b/tester/RT-formatter/RT-formatter_alt.el
deleted file mode 100644
index dd0669e..0000000
--- a/tester/RT-formatter/RT-formatter_alt.el
+++ /dev/null
@@ -1,30 +0,0 @@
-
-(defun RT-formatter-buffer ()
- "Format the current buffer using RTfmt."
- (interactive)
- (if (not (executable-find "RT-formatter"))
- (message "Error: RTfmt executable not found in PATH.")
- (let ((temp-buffer (generate-new-buffer " *RTfmt*"))
- (args (list "pipe")))
- (when (derived-mode-p 'emacs-lisp-mode 'lisp-mode)
- (setq args (append args (list "--lisp"))))
- (unwind-protect
- (let ((exit-code (apply #'call-process-region
- (point-min) (point-max)
- "RT-formatter"
- nil temp-buffer nil
- args)))
- (if (zerop exit-code)
- (let ((formatted-text (with-current-buffer temp-buffer (buffer-string))))
- (save-excursion
- (delete-region (point-min) (point-max))
- (insert formatted-text))
- (message "RT-formatter formatting successful."))
- (message "RT-formatter failed with exit code %s. Buffer unchanged." exit-code)))
- (kill-buffer temp-buffer)))))
-
-;; ( defun RT-format-buffer()
-;; (interactive)
-;; (save-excursion
-;; ( shell-command-on-region(point-min)(point-max)
-;; "RT-formatter pipe" t t)) )
diff --git a/tester/RT-formatter/RT-formatter_script.el b/tester/RT-formatter/RT-formatter_script.el
deleted file mode 100644
index 45ff29b..0000000
--- a/tester/RT-formatter/RT-formatter_script.el
+++ /dev/null
@@ -1,22 +0,0 @@
-(defun RT-formatter-buffer ()
- "Format the current buffer using RTfmt."
- (interactive)
- (if (not (executable-find "RT-formatter"))
- (message "Error: RTfmt executable not found in PATH.")
- (let ((temp-buffer (generate-new-buffer " *RTfmt*"))
- (args (list "pipe")))
- (when (derived-mode-p 'emacs-lisp-mode 'lisp-mode)
- (setq args (append args (list "--lisp"))))
- (unwind-protect
- (let ((exit-code (apply #'call-process-region
- (point-min) (point-max)
- "RT-formatter"
- nil temp-buffer nil
- args)))
- (if (zerop exit-code)
- (progn
- ;; Applies a non-destructive diff, preserving point and markers natively
- (replace-buffer-contents temp-buffer)
- (message "RT-formatter formatting successful."))
- (message "RT-formatter failed with exit code %s. Buffer unchanged." exit-code)))
- (kill-buffer temp-buffer)))))
diff --git a/tester/RT-formatter/RT-formatter_with-compare b/tester/RT-formatter/RT-formatter_with-compare
deleted file mode 100644
index 09ee7a5..0000000
--- a/tester/RT-formatter/RT-formatter_with-compare
+++ /dev/null
@@ -1,331 +0,0 @@
-#!/usr/bin/env -S python3 -B
-# -*- mode: python; coding: utf-8; python-indent-offset: 2; indent-tabs-mode: nil -*-
-"""
-RTfmt â Reasoning Technology code formatter (Predicate Tokenizer)
-
-Commands:
- RTfmt write [--lisp] Format files in place (rewrite originals)
- RTfmt copy [--lisp] Save backups as ~ then format originals
- RT-formatter pipe [--lisp] Read from stdin, write to stdout
- RTfmt self_test Run built-in tests
- RTfmt version Show tool version
- RTfmt help | --help Show usage
-"""
-
-import sys ,re ,shutil ,os
-from typing import List ,Tuple ,Optional ,TextIO
-
-RTF_VERSION = "0.5.0-predicate"
-
-def get_usage() -> str:
- prog_name = os.path.basename(sys.argv[0])
- return f"""\
-Usage:
- {prog_name} write [--lisp]
- {prog_name} copy [--lisp]
- {prog_name} pipe [--lisp]
- {prog_name} self_test
- {prog_name} version
- {prog_name} help | --help
-"""
-
-# Removed < and > so they are treated as standard CODE operators
-BR_OPEN = "([{"
-BR_CLOSE = ")]}"
-PAIR = dict( zip(BR_OPEN ,BR_CLOSE) )
-REV = dict( zip(BR_CLOSE ,BR_OPEN) )
-
-# --------------- Lexer ----------------
-
-class RT_Token:
- def __init__(self ,kind: str ,text: str):
- self.kind = kind
- self.text = text
-
- def __repr__(self):
- return f"<{self.kind}:{repr(self.text)}>"
-
-TOKEN_REGEX = re.compile(
- r'(?P//[^\n]*|#[^\n]*|(?s:/\*.*?\*/))'
- r'|(?P"""[\s\S]*?"""|\'\'\'[\s\S]*?\'\'\'|"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\')'
- r'|(?P[ \t]+)'
- r'|(?P\n)'
- r'|(?P,)'
- r'|(?P[\[\(\{])'
- r'|(?P[\]\)\}])'
- r'|(?P[^ \t\n,\[\(\{\]\)\}"\'#/]+|/)'
-)
-
-def tokenize(text: str) -> List[RT_Token]:
- tokens = []
- for TM_match in TOKEN_REGEX.finditer(text):
- kind = TM_match.lastgroup
- text_val = TM_match.group(kind)
- tokens.append( RT_Token(kind ,text_val) )
- return tokens
-
-# --------------- Intelligence API ----------------
-
-class TokenStream:
- def __init__(self ,tokens: List[RT_Token]):
- self.tokens = tokens
-
- def get_token(self ,index: int) -> Optional[RT_Token]:
- if 0 <= index < len(self.tokens):
- return self.tokens[index]
- return None
-
- def next_sig_index(self ,index: int) -> Optional[int]:
- for TM_i in range(index + 1 ,len(self.tokens)):
- if self.tokens[TM_i].kind not in ("SPACE" ,"NEWLINE" ,"COMMENT"):
- return TM_i
- return None
-
- def is_first_on_line(self ,index: int) -> bool:
- for TM_i in range(index - 1 ,-1 ,-1):
- k = self.tokens[TM_i].kind
- if k == "NEWLINE":
- return True
- if k != "SPACE":
- return False
- return True # Start of file
-
- def indent_of_line(self ,index: int) -> str:
- for TM_i in range(index ,-1 ,-1):
- if self.tokens[TM_i].kind == "NEWLINE":
- if TM_i + 1 < len(self.tokens) and self.tokens[TM_i + 1].kind == "SPACE":
- return self.tokens[TM_i + 1].text
- return ""
- if self.tokens and self.tokens[0].kind == "SPACE":
- return self.tokens[0].text
- return ""
-
- def indent_of_left_match(self ,index: int) -> Optional[str]:
- tok = self.get_token(index)
- if not tok or tok.kind != "BR_CLOSE":
- return None
- target_opener = REV[tok.text]
- depth = 0
- for TM_i in range(index - 1 ,-1 ,-1):
- t = self.tokens[TM_i]
- if t.kind == "BR_CLOSE":
- depth += 1
- elif t.kind == "BR_OPEN":
- if depth > 0:
- depth -= 1
- elif t.text == target_opener:
- return self.indent_of_line(TM_i)
- return None
-
-# --------------- Rule Engine ----------------
-
-def rule_migrate_vertical_commas(stream: TokenStream):
- TM_i = 0
- while TM_i < len(stream.tokens):
- if stream.tokens[TM_i].kind == "COMMA":
- is_trailing = False
- next_sig = stream.next_sig_index(TM_i)
- if next_sig is not None:
- for TM_j in range(TM_i + 1 ,next_sig):
- if stream.tokens[TM_j].kind == "NEWLINE":
- is_trailing = True
- break
-
- if is_trailing:
- comma_tok = stream.tokens.pop(TM_i)
- next_sig -= 1 # Shifted because of pop
- stream.tokens.insert(next_sig ,comma_tok)
- continue
- TM_i += 1
-
-def rule_format_horizontal_commas(stream: TokenStream):
- for TM_i in range(len(stream.tokens) - 1 ,-1 ,-1):
- if stream.tokens[TM_i].kind == "COMMA":
- if stream.is_first_on_line(TM_i):
- continue
-
- next_tok = stream.get_token(TM_i + 1)
- if next_tok and next_tok.kind == "SPACE":
- stream.tokens.pop(TM_i + 1)
-
- prev_tok = stream.get_token(TM_i - 1)
- if prev_tok and prev_tok.kind == "SPACE":
- if prev_tok.text != " ":
- prev_tok.text = " "
- else:
- stream.tokens.insert(TM_i ,RT_Token("SPACE" ," "))
-
-def rule_fix_closing_indent(stream: TokenStream):
- for TM_i in range(len(stream.tokens) - 1 ,-1 ,-1):
- if stream.tokens[TM_i].kind == "BR_CLOSE" and stream.is_first_on_line(TM_i):
- target_indent = stream.indent_of_left_match(TM_i)
- if target_indent is not None:
- prev = stream.get_token(TM_i - 1)
- if prev and prev.kind == "SPACE":
- prev.text = target_indent
- else:
- stream.tokens.insert(TM_i ,RT_Token("SPACE" ,target_indent))
-
-def rule_tighten_brackets(stream: TokenStream):
- for TM_i in range(len(stream.tokens) - 1 ,-1 ,-1):
- if stream.tokens[TM_i].kind == "SPACE" and not stream.is_first_on_line(TM_i):
- prev_t = stream.get_token(TM_i - 1)
- next_t = stream.get_token(TM_i + 1)
- if (prev_t and prev_t.kind == "BR_OPEN") or (next_t and next_t.kind == "BR_CLOSE"):
- stream.tokens.pop(TM_i)
-
-def get_bracket_spans(stream: TokenStream) -> List[Tuple[int ,int]]:
- stack = []
- spans = []
- for TM_i ,tok in enumerate(stream.tokens):
- if tok.kind == "BR_OPEN":
- stack.append( (tok.text ,TM_i) )
- elif tok.kind == "BR_CLOSE":
- if stack and REV[tok.text] == stack[-1][0]:
- _ ,pos = stack.pop()
- if not stack:
- spans.append( (pos ,TM_i) )
- return spans
-
-def rule_pad_outermost(stream: TokenStream ,is_lisp: bool):
- if is_lisp:
- return
- while True:
- spans = get_bracket_spans(stream)
- changed = False
- for TM_start ,TM_end in reversed(spans):
- has_inner = False
- for TM_k in range(TM_start + 1 ,TM_end):
- if stream.tokens[TM_k].kind in ("BR_OPEN" ,"BR_CLOSE"):
- has_inner = True
- break
-
- if has_inner:
- left_has = (TM_start + 1 < len(stream.tokens)) and stream.tokens[TM_start + 1].kind == "SPACE"
- right_has = (TM_end - 1 >= 0) and stream.tokens[TM_end - 1].kind == "SPACE"
- if not left_has or not right_has:
- if not right_has:
- stream.tokens.insert(TM_end ,RT_Token("SPACE" ," "))
- if not left_has:
- stream.tokens.insert(TM_start + 1 ,RT_Token("SPACE" ," "))
- changed = True
- break
- if not changed:
- break
-
-# --------------- Public API ----------------
-
-def format_tokens(tokens: List[RT_Token] ,is_lisp: bool) -> str:
- stream = TokenStream(tokens)
-
- rule_migrate_vertical_commas(stream)
- rule_format_horizontal_commas(stream)
- rule_tighten_brackets(stream)
- rule_fix_closing_indent(stream)
- rule_pad_outermost(stream ,is_lisp)
-
- return "".join(t.text for t in stream.tokens)
-
-def rt_format_text(text: str ,is_lisp: bool) -> str:
- tokens = tokenize(text)
- return format_tokens(tokens ,is_lisp)
-
-def rt_format_stream(inp: TextIO ,out: TextIO ,is_lisp: bool) -> None:
- text = inp.read()
- out.write( rt_format_text(text ,is_lisp) )
-
-# --------------- Self-test ----------------
-
-def run_self_test() -> bool:
- ok = True
- def chk(src ,exp):
- nonlocal ok
- got = rt_format_text(src ,False)
- if got != exp:
- print("FAIL:\n" + src + "\n=>\n" + got + "\nexpected:\n" + exp)
- ok = False
-
- chk("a,b,c" ,"a ,b ,c")
- chk("a , b , c" ,"a ,b ,c")
- chk(" ,vertical_arg" ," ,vertical_arg")
-
- chk("int a=0,\n b=1,\n c=2;" ,"int a=0\n ,b=1\n ,c=2;")
-
- chk("f ( x )" ,"f(x)")
- chk("f(x) + g(y)" ,"f(x) + g(y)")
- chk(" {" ," {")
-
- src = "int g(){int a=0,b=1,c=2; return h(a,b,c);}"
- exp = "int g(){ int a=0 ,b=1 ,c=2; return h(a ,b ,c); }"
- chk(src ,exp)
-
- chk("outer( inner(a,b) )" ,"outer( inner(a ,b) )")
-
- # Operator protection check
- chk("for(int TM = 0; TM < count; ++TM)" ,"for(int TM = 0; TM < count; ++TM)")
-
- print("SELFTEST OK" if ok else "SELFTEST FAILED")
- return ok
-
-# --------------- CLI ----------------
-def write_files(paths: List[str] ,is_lisp: bool) -> int:
- for TM_path in paths:
- with open(TM_path ,"r" ,encoding="utf-8") as f:
- data = f.read()
-
- formatted = rt_format_text(data ,is_lisp)
-
- # Only touch the file if the content actually changed
- if data != formatted:
- with open(TM_path ,"w" ,encoding="utf-8") as f:
- f.write(formatted)
- print(f"Formatted: {TM_path}")
- return 0
-
-def copy_files(paths: List[str] ,is_lisp: bool) -> int:
- for TM_path in paths:
- shutil.copy2(TM_path ,TM_path + "~")
- return write_files(paths ,is_lisp)
-
-def CLI(argv=None) -> int:
- args = list(sys.argv[1:] if argv is None else argv)
- usage_text = get_usage()
-
- if not args or args[0] in {"help" ,"--help" ,"-h"}:
- print(usage_text)
- return 0
-
- is_lisp = "--lisp" in args
- args = [TM_a for TM_a in args if TM_a != "--lisp"]
-
- if not args:
- return 0
-
- cmd = args[0]
- rest = args[1:]
-
- if cmd == "version":
- print(RTF_VERSION)
- return 0
- if cmd == "self_test":
- ok = run_self_test()
- return 0 if ok else 1
- if cmd == "pipe":
- rt_format_stream(sys.stdin ,sys.stdout ,is_lisp)
- return 0
- if cmd == "write":
- if not rest:
- print("write: missing \n" + usage_text)
- return 2
- return write_files(rest ,is_lisp)
- if cmd == "copy":
- if not rest:
- print("copy: missing \n" + usage_text)
- return 2
- return copy_files(rest ,is_lisp)
-
- print(f"Unknown command: {cmd}\n" + usage_text)
- return 2
-
-if __name__ == "__main__":
- sys.exit( CLI() )
diff --git a/tester/RT-formatter/RT-formatter_with-compare.el b/tester/RT-formatter/RT-formatter_with-compare.el
deleted file mode 100644
index 36213ae..0000000
--- a/tester/RT-formatter/RT-formatter_with-compare.el
+++ /dev/null
@@ -1,23 +0,0 @@
-(defun RT-formatter-buffer ()
- "Format the current buffer using RTfmt."
- (interactive)
- (if (not (executable-find "RT-formatter"))
- (message "Error: RTfmt executable not found in PATH.")
- (let ((temp-buffer (generate-new-buffer " *RTfmt*"))
- (args (list "pipe")))
- (when (derived-mode-p 'emacs-lisp-mode 'lisp-mode)
- (setq args (append args (list "--lisp"))))
- (unwind-protect
- (let ((exit-code (apply #'call-process-region
- (point-min) (point-max)
- "RT-formatter"
- nil temp-buffer nil
- args)))
- (if (zerop exit-code)
- ;; Check if the formatted text is actually different
- (if (= (compare-buffer-substrings nil nil nil temp-buffer nil nil) 0)
- (message "RTfmt: Already perfectly formatted.")
- (replace-buffer-contents temp-buffer)
- (message "RT-formatter formatting successful."))
- (message "RT-formatter failed with exit code %s. Buffer unchanged." exit-code)))
- (kill-buffer temp-buffer)))))
diff --git a/tester/RT-formatter/data_test-0.c b/tester/RT-formatter/data_test-0.c
deleted file mode 100644
index c877406..0000000
--- a/tester/RT-formatter/data_test-0.c
+++ /dev/null
@@ -1,20 +0,0 @@
-// commas and simple tight brackets
-int g(){
- int a=0 ,
- b=1 ,
- c=2;
- return h(a ,b ,c);
-}
-
-// balanced outermost-with-nesting -> pad inside outer ()
-int f(){ return outer(inner(a ,b)); }
-
-// strings and comments must be unchanged
-int s(){ printf("x ,y ,z (still a string)"); /* a ,b ,c */ return 1; }
-
-// unbalanced open-right with nesting -> pad after first unmatched '('
-int u(){if(doit(foo(1 ,2) // missing ))
- return 0;}
-
-// arrays / subscripts stay tight; commas still RT-style
-int a(int i ,int j){ return M[i ,j] + V[i] + W[j]; }
diff --git a/tester/RT-formatter/data_test-1.py b/tester/RT-formatter/data_test-1.py
deleted file mode 100644
index 9b2fa87..0000000
--- a/tester/RT-formatter/data_test-1.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# commas and spacing in defs / calls
-def f ( x , y , z ):
- return dict( a =1 , b= 2 ), [ 1, 2 ,3 ], ( (1,2) )
-
-# outermost-with-nesting -> pad inside outer ()
-val = outer( inner( a,b ) )
-
-# strings/comments untouched
-s = "text, with , commas ( not to touch )" # a ,b ,c
-
-# unbalanced: open-left (closing without opener) -> no padding unless inner bracket before it
-def g():
- return result) # likely unchanged
-
-# unbalanced: open-right (first unmatched opener) with inner bracket following
-k = compute(x, f(y