removing pencils, was a nice idea ..
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Sun, 12 Oct 2025 10:39:28 +0000 (10:39 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Sun, 12 Oct 2025 10:39:28 +0000 (10:39 +0000)
137 files changed:
developer/Python3/gen_email [new file with mode: 0755]
developer/Python3/gen_passwd [new file with mode: 0755]
developer/Python3/gen_sig [new file with mode: 0755]
developer/Python3🖉/gen_email [deleted file]
developer/Python3🖉/gen_passwd [deleted file]
developer/Python3🖉/gen_sig [deleted file]
developer/bash/Z [new file with mode: 0755]
developer/bash/bashrc_example [new file with mode: 0644]
developer/bash/cat_w_fn [new file with mode: 0755]
developer/bash/deprecate [new file with mode: 0755]
developer/bash/env_administrator [new file with mode: 0644]
developer/bash/env_developer [new file with mode: 0644]
developer/bash/env_run [new file with mode: 0755]
developer/bash/env_tester [new file with mode: 0644]
developer/bash/githolder_to_empty_dirs [new file with mode: 0755]
developer/bash/make_project_skeleton.sh [new file with mode: 0644]
developer/bash/release_dir [new file with mode: 0755]
developer/bash/release_ls [new file with mode: 0755]
developer/bash/rm_tilda_files_tree [new file with mode: 0755]
developer/bash/test_env [new file with mode: 0755]
developer/bash/vl [new file with mode: 0755]
developer/bash/wipe_release [new file with mode: 0755]
developer/bash🖉/Z [deleted file]
developer/bash🖉/bashrc_example [deleted file]
developer/bash🖉/cat_w_fn [deleted file]
developer/bash🖉/deprecate [deleted file]
developer/bash🖉/env_administrator [deleted file]
developer/bash🖉/env_developer [deleted file]
developer/bash🖉/env_run [deleted file]
developer/bash🖉/env_tester [deleted file]
developer/bash🖉/githolder_to_empty_dirs [deleted file]
developer/bash🖉/release_dir [deleted file]
developer/bash🖉/release_ls [deleted file]
developer/bash🖉/rm_tilda_files_tree [deleted file]
developer/bash🖉/test_env [deleted file]
developer/bash🖉/vl [deleted file]
developer/bash🖉/wipe_release [deleted file]
developer/cc/home.cli.c [new file with mode: 0644]
developer/cc/is_authored_fs_obj.c [new file with mode: 0644]
developer/cc/remove.c [new file with mode: 0644]
developer/cc/unlink.lib.c [new file with mode: 0644]
developer/cc/user-stem.cli.c [new file with mode: 0644]
developer/cc/user-subu.cli.c [new file with mode: 0644]
developer/cc/user.cli.c [new file with mode: 0644]
developer/cc🖉/home.cli.c [deleted file]
developer/cc🖉/is_authored_fs_obj.c [deleted file]
developer/cc🖉/remove.c [deleted file]
developer/cc🖉/unlink.lib.c [deleted file]
developer/cc🖉/user-stem.cli.c [deleted file]
developer/cc🖉/user-subu.cli.c [deleted file]
developer/cc🖉/user.cli.c [deleted file]
developer/emacs/emacs_wrap.txt [new file with mode: 0644]
developer/emacs/for_dot_emacs.txt [new file with mode: 0644]
developer/emacs/jdbx.el [new file with mode: 0644]
developer/emacs🖉/emacs_wrap.txt [deleted file]
developer/emacs🖉/for_dot_emacs.txt [deleted file]
developer/emacs🖉/jdbx.el [deleted file]
developer/make/RT_0.h [new file with mode: 0644]
developer/make/environment_RT_0 [new file with mode: 0644]
developer/make/targets_developer [new file with mode: 0644]
developer/make/targets_tester [new file with mode: 0644]
developer/make🖉/RT_0.h [deleted file]
developer/make🖉/environment_RT_0 [deleted file]
developer/make🖉/targets_developer [deleted file]
developer/make🖉/targets_tester [deleted file]
developer/nautilus/Decrypt [new file with mode: 0644]
developer/nautilus/Encrypt [new file with mode: 0644]
developer/nautilus/README.md [new file with mode: 0644]
developer/nautilus🖉/Decrypt [deleted file]
developer/nautilus🖉/Encrypt [deleted file]
developer/nautilus🖉/README.md [deleted file]
developer/test/e/f/ff [new file with mode: 0644]
developer/test/e/f/g/gg [new file with mode: 0644]
developer/test/e/f🖉/ff [deleted file]
developer/test/e/f🖉/g/gg [deleted file]
developer/tool/env [new file with mode: 0644]
developer/tool/make [new file with mode: 0755]
developer/tool/makefile [new file with mode: 0644]
developer/tool/release [new file with mode: 0755]
developer/tool🖉/env [deleted file]
developer/tool🖉/make [deleted file]
developer/tool🖉/makefile [deleted file]
developer/tool🖉/release [deleted file]
document/#RT_code_format.org# [new file with mode: 0644]
document/#how_to_use_project_directory_structure.txt# [new file with mode: 0644]
document/Java_import_as_alternative.txt [new file with mode: 0644]
document/Pencil_Suffix.html [new file with mode: 0644]
document/RT_C_control_structure.html [new file with mode: 0644]
document/RT_code_format.org [new file with mode: 0644]
document/Workflow.org [new file with mode: 0644]
document/bash_name_of_script.txt [new file with mode: 0644]
document/bracketed_phrases_section.txt [new file with mode: 0644]
document/directory_naming.html [new file with mode: 0644]
document/directory_structure.org [new file with mode: 0644]
document/enclosure_old.org [new file with mode: 0644]
document/how_to_use_project_directory_structure.txt [new file with mode: 0644]
document/install_Eclipse.txt [new file with mode: 0644]
document/install_Emacs.txt [new file with mode: 0644]
document/install_IntelliJ_IDEA.txt [new file with mode: 0644]
document/install_Mosaic.txt [new file with mode: 0644]
document/install_jdk-23.txt [new file with mode: 0644]
document/running_IDE_and_jdb_in_test_environment.txt [new file with mode: 0644]
document/todo.txt [new file with mode: 0644]
document/variable_suffix_conventions.txt [new file with mode: 0644]
document🖉/#how_to_use_project_directory_structure.txt# [deleted file]
document🖉/Java_import_as_alternative.txt [deleted file]
document🖉/Pencil_Suffix.html [deleted file]
document🖉/RT_C_control_structure.html [deleted file]
document🖉/RT_code_format.org [deleted file]
document🖉/Workflow.org [deleted file]
document🖉/bash_name_of_script.txt [deleted file]
document🖉/directory_naming.html [deleted file]
document🖉/directory_structure.org [deleted file]
document🖉/enclosure_old.org [deleted file]
document🖉/how_to_use_project_directory_structure.txt [deleted file]
document🖉/install_Eclipse.txt [deleted file]
document🖉/install_Emacs.txt [deleted file]
document🖉/install_IntelliJ_IDEA.txt [deleted file]
document🖉/install_Mosaic.txt [deleted file]
document🖉/install_jdk-23.txt [deleted file]
document🖉/running_IDE_and_jdb_in_test_environment.txt [deleted file]
document🖉/todo.txt [deleted file]
document🖉/variable_suffix_conventions.txt [deleted file]
tool/env [new file with mode: 0644]
tool_shared/bespoke/cat_w_fn [new file with mode: 0755]
tool_shared/bespoke/env [new file with mode: 0644]
tool_shared/bespoke/githolder [new file with mode: 0755]
tool_shared/bespoke/version [new file with mode: 0755]
tool_shared/bespoke/vl [new file with mode: 0755]
tool_shared/bespoke🖉/cat_w_fn [deleted file]
tool_shared/bespoke🖉/env [deleted file]
tool_shared/bespoke🖉/githolder [deleted file]
tool_shared/bespoke🖉/version [deleted file]
tool_shared/bespoke🖉/vl [deleted file]
tool_shared/document/make_rm_na.txt [new file with mode: 0644]
tool_shared/document🖉/make_rm_na.txt [deleted file]
tool🖉/env [deleted file]

diff --git a/developer/Python3/gen_email b/developer/Python3/gen_email
new file mode 100755 (executable)
index 0000000..a1057d9
--- /dev/null
@@ -0,0 +1,99 @@
+#!/usr/bin/python3
+
+#--------------------------------------------------------------------------------
+# generate a random string length n of form
+#    "" | [A-Za-z^IloO] | [A-Za-z^IloO][0-9A-Za-z_-^IloO01]*[A-Za-z^IloO]
+#
+
+import sys
+import random
+
+# note missing IloO01.
+# period and comman might be difficult, light period might be missed
+# capital I in san-serif font looks like number 1.
+# email addresses are not case sensitive
+# these are not all the legal characters, but rather the ones we think are legal and legible
+legal_chars_end = "abcdefghijkmnpqrstuvwxz"
+legal_chars = "23456789abcdefghijkmnpqrstuvwxz"
+
+def index():
+  return random.randrange(0 ,len(legal_chars))
+
+def index_end():
+  return random.randrange(0 ,len(legal_chars_end))
+
+def char():
+  return legal_chars[index()]
+  
+def char_end():
+  return legal_chars_end[index_end()]
+
+def string(n=6):
+  if n < 0 : raise Exception("string called with negative length")
+  if n == 0 : return ""
+
+  result = char_end()
+  if  n == 1: return result
+
+  for _ in range(n-2): result += char()
+  result += char_end()
+
+  return result
+
+def  test_0():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char()
+  while c != '~' and i < limit:
+    i += 1
+    c = char()
+  print(i)
+  return i < limit
+
+def  test_1():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char()
+  while c != '0' and i < limit:
+    i += 1
+    c = char()
+  print(i)
+  return i < limit
+
+def  test_2():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char_end()
+  while c != 'z' and i < limit:
+    i += 1
+    c = char_end()
+  print(i)
+  return i < limit
+
+def  test_3 ():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char_end()
+  while c != 'A' and i < limit:
+    i += 1
+    c = char_end()
+  print(i)
+  return i < limit
+
+def  test_4():
+  s0 = string()
+  s1 = string(10)
+  s2 = string(100)
+
+  print(s0)
+  print(s1)
+  print(s2)
+
+  return len(s0)==6 and len(s1)==10 and len(s2)==100
+
+
+n=6
+if len(sys.argv) > 1:
+   n = int(sys.argv[1])
+print(string(n))
+
diff --git a/developer/Python3/gen_passwd b/developer/Python3/gen_passwd
new file mode 100755 (executable)
index 0000000..d7cc5d4
--- /dev/null
@@ -0,0 +1,96 @@
+#!/usr/bin/python3
+
+#--------------------------------------------------------------------------------
+# generate a random string length n of form
+#    "" | [A-Za-z^IloO] | [A-Za-z^IloO][0-9A-Za-z_-^IloO01]*[A-Za-z^IloO]
+#
+
+import sys
+import random
+
+#debug = True
+debug = False
+
+# note missing IloO01.
+# period and comman might be difficult, light period might be missed
+# capital I in san-serif font looks like number 1.
+# zero and oh of course
+# SNCF does not take an & as a special hmm.
+chars_alpha_small = "abcdefghijkmnpqrstuvwxz"
+chars_alpha_big = "ABCDEFGHJKLMNPQRSTUVWXYZ"
+chars_special = "+-_$.,;?"
+chars_numeric = "23456789"
+
+sets_leftmost=[chars_alpha_small ,chars_alpha_big]
+sets_standard=[chars_alpha_small ,chars_alpha_big ,chars_special ,chars_numeric]
+sets_rightmost=[chars_alpha_small ,chars_alpha_big ,chars_numeric]
+
+def set_psets(sets):
+  len_sum = sum(len(x) for x in sets)
+  psets = [len(x)/len_sum + 1e-7 for x in sets]
+  if debug: print("psets" ,psets ,"sum:" ,sum(psets))
+  return psets
+
+def choose_set(sets):
+  psets = set_psets(sets)
+  x = random.random()
+  if debug: print("x:" ,x)
+  if len(psets) == 0: return 0
+  p = psets[0]
+  choice = len(psets) - 1
+  i = 0
+  while i != len(psets) - 1:
+    if x <= p : 
+      choice = i
+      break
+    i += 1
+    p += psets[i]
+  if debug: print("choice:" ,choice)
+  return choice
+
+def get_char_set(set):
+  index = random.randrange(0 ,len(set))
+  return set[index]
+
+def get_char(sets):
+  set = sets[choose_set(sets)]
+  return get_char_set(set)
+  
+def get_string(n):
+  if n < 0 : raise Exception("string called with negative length")
+  if n == 0: return ""
+  if n == 1: return get_char_set(chars_alpha)
+
+  result = ""
+  result += get_char(sets_leftmost)
+  for _ in range(n-2): result += get_char(sets_standard)
+  result += get_char(sets_rightmost)
+
+  return result
+
+def get_passwd(n ,strict):
+  s = get_string(n)
+  while strict:
+    has_special = any(i in s for i in chars_special)
+    has_numeric = any(i in s for i in chars_numeric)
+    if debug: print("strict:" ,has_special ,has_numeric)
+    if has_special and has_numeric:
+      break
+    s = get_string(n)
+  return s
+
+strict = False
+n=9
+for arg in sys.argv[1:]:
+  if arg.isdigit(): n = int(arg)
+  if arg == "strict": strict = True
+
+if debug:
+  print("n:" ,n)
+  print("strict:" ,strict)
+  
+pw = get_passwd(n ,strict)
+print(pw)
+sys.exit(0)
+
+
diff --git a/developer/Python3/gen_sig b/developer/Python3/gen_sig
new file mode 100755 (executable)
index 0000000..c6b254b
--- /dev/null
@@ -0,0 +1,96 @@
+#!/usr/bin/python3
+
+#--------------------------------------------------------------------------------
+# generate a random string length n of form
+#
+
+import sys
+import random
+
+# note missing IloO01.
+# period and comman might be difficult, light period might be missed
+# capital I in san-serif font looks like number 1.
+legal_chars_end = "abcdefghjkmnpqrstuvwxz"
+legal_chars = "23456789abcdefghijkmnpqrstuvwxz"
+
+def index():
+  return random.randrange(0 ,len(legal_chars))
+
+def index_end():
+  return random.randrange(0 ,len(legal_chars_end))
+
+def char():
+  return legal_chars[index()]
+  
+def char_end():
+  return legal_chars_end[index_end()]
+
+def string(n=6):
+  if n < 0 : raise Exception("string called with negative length")
+  if n == 0 : return ""
+
+  result = char_end()
+  if  n == 1: return result
+
+  for _ in range(n-2): result += char()
+  result += char_end()
+
+  return result
+
+def  test_0():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char()
+  while c != '~' and i < limit:
+    i += 1
+    c = char()
+  print(i)
+  return i < limit
+
+def  test_1():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char()
+  while c != '0' and i < limit:
+    i += 1
+    c = char()
+  print(i)
+  return i < limit
+
+def  test_2():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char_end()
+  while c != 'z' and i < limit:
+    i += 1
+    c = char_end()
+  print(i)
+  return i < limit
+
+def  test_3 ():
+  limit = 1e7 # surely by then
+  i = 0
+  c = char_end()
+  while c != 'A' and i < limit:
+    i += 1
+    c = char_end()
+  print(i)
+  return i < limit
+
+def  test_4():
+  s0 = string()
+  s1 = string(10)
+  s2 = string(100)
+
+  print(s0)
+  print(s1)
+  print(s2)
+
+  return len(s0)==6 and len(s1)==10 and len(s2)==100
+
+
+n=16
+if len(sys.argv) > 1:
+   n = int(sys.argv[1])
+print(string(n))
+
diff --git a/developer/Python3🖉/gen_email b/developer/Python3🖉/gen_email
deleted file mode 100755 (executable)
index a1057d9..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/python3
-
-#--------------------------------------------------------------------------------
-# generate a random string length n of form
-#    "" | [A-Za-z^IloO] | [A-Za-z^IloO][0-9A-Za-z_-^IloO01]*[A-Za-z^IloO]
-#
-
-import sys
-import random
-
-# note missing IloO01.
-# period and comman might be difficult, light period might be missed
-# capital I in san-serif font looks like number 1.
-# email addresses are not case sensitive
-# these are not all the legal characters, but rather the ones we think are legal and legible
-legal_chars_end = "abcdefghijkmnpqrstuvwxz"
-legal_chars = "23456789abcdefghijkmnpqrstuvwxz"
-
-def index():
-  return random.randrange(0 ,len(legal_chars))
-
-def index_end():
-  return random.randrange(0 ,len(legal_chars_end))
-
-def char():
-  return legal_chars[index()]
-  
-def char_end():
-  return legal_chars_end[index_end()]
-
-def string(n=6):
-  if n < 0 : raise Exception("string called with negative length")
-  if n == 0 : return ""
-
-  result = char_end()
-  if  n == 1: return result
-
-  for _ in range(n-2): result += char()
-  result += char_end()
-
-  return result
-
-def  test_0():
-  limit = 1e7 # surely by then
-  i = 0
-  c = char()
-  while c != '~' and i < limit:
-    i += 1
-    c = char()
-  print(i)
-  return i < limit
-
-def  test_1():
-  limit = 1e7 # surely by then
-  i = 0
-  c = char()
-  while c != '0' and i < limit:
-    i += 1
-    c = char()
-  print(i)
-  return i < limit
-
-def  test_2():
-  limit = 1e7 # surely by then
-  i = 0
-  c = char_end()
-  while c != 'z' and i < limit:
-    i += 1
-    c = char_end()
-  print(i)
-  return i < limit
-
-def  test_3 ():
-  limit = 1e7 # surely by then
-  i = 0
-  c = char_end()
-  while c != 'A' and i < limit:
-    i += 1
-    c = char_end()
-  print(i)
-  return i < limit
-
-def  test_4():
-  s0 = string()
-  s1 = string(10)
-  s2 = string(100)
-
-  print(s0)
-  print(s1)
-  print(s2)
-
-  return len(s0)==6 and len(s1)==10 and len(s2)==100
-
-
-n=6
-if len(sys.argv) > 1:
-   n = int(sys.argv[1])
-print(string(n))
-
diff --git a/developer/Python3🖉/gen_passwd b/developer/Python3🖉/gen_passwd
deleted file mode 100755 (executable)
index d7cc5d4..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/python3
-
-#--------------------------------------------------------------------------------
-# generate a random string length n of form
-#    "" | [A-Za-z^IloO] | [A-Za-z^IloO][0-9A-Za-z_-^IloO01]*[A-Za-z^IloO]
-#
-
-import sys
-import random
-
-#debug = True
-debug = False
-
-# note missing IloO01.
-# period and comman might be difficult, light period might be missed
-# capital I in san-serif font looks like number 1.
-# zero and oh of course
-# SNCF does not take an & as a special hmm.
-chars_alpha_small = "abcdefghijkmnpqrstuvwxz"
-chars_alpha_big = "ABCDEFGHJKLMNPQRSTUVWXYZ"
-chars_special = "+-_$.,;?"
-chars_numeric = "23456789"
-
-sets_leftmost=[chars_alpha_small ,chars_alpha_big]
-sets_standard=[chars_alpha_small ,chars_alpha_big ,chars_special ,chars_numeric]
-sets_rightmost=[chars_alpha_small ,chars_alpha_big ,chars_numeric]
-
-def set_psets(sets):
-  len_sum = sum(len(x) for x in sets)
-  psets = [len(x)/len_sum + 1e-7 for x in sets]
-  if debug: print("psets" ,psets ,"sum:" ,sum(psets))
-  return psets
-
-def choose_set(sets):
-  psets = set_psets(sets)
-  x = random.random()
-  if debug: print("x:" ,x)
-  if len(psets) == 0: return 0
-  p = psets[0]
-  choice = len(psets) - 1
-  i = 0
-  while i != len(psets) - 1:
-    if x <= p : 
-      choice = i
-      break
-    i += 1
-    p += psets[i]
-  if debug: print("choice:" ,choice)
-  return choice
-
-def get_char_set(set):
-  index = random.randrange(0 ,len(set))
-  return set[index]
-
-def get_char(sets):
-  set = sets[choose_set(sets)]
-  return get_char_set(set)
-  
-def get_string(n):
-  if n < 0 : raise Exception("string called with negative length")
-  if n == 0: return ""
-  if n == 1: return get_char_set(chars_alpha)
-
-  result = ""
-  result += get_char(sets_leftmost)
-  for _ in range(n-2): result += get_char(sets_standard)
-  result += get_char(sets_rightmost)
-
-  return result
-
-def get_passwd(n ,strict):
-  s = get_string(n)
-  while strict:
-    has_special = any(i in s for i in chars_special)
-    has_numeric = any(i in s for i in chars_numeric)
-    if debug: print("strict:" ,has_special ,has_numeric)
-    if has_special and has_numeric:
-      break
-    s = get_string(n)
-  return s
-
-strict = False
-n=9
-for arg in sys.argv[1:]:
-  if arg.isdigit(): n = int(arg)
-  if arg == "strict": strict = True
-
-if debug:
-  print("n:" ,n)
-  print("strict:" ,strict)
-  
-pw = get_passwd(n ,strict)
-print(pw)
-sys.exit(0)
-
-
diff --git a/developer/Python3🖉/gen_sig b/developer/Python3🖉/gen_sig
deleted file mode 100755 (executable)
index c6b254b..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/python3
-
-#--------------------------------------------------------------------------------
-# generate a random string length n of form
-#
-
-import sys
-import random
-
-# note missing IloO01.
-# period and comman might be difficult, light period might be missed
-# capital I in san-serif font looks like number 1.
-legal_chars_end = "abcdefghjkmnpqrstuvwxz"
-legal_chars = "23456789abcdefghijkmnpqrstuvwxz"
-
-def index():
-  return random.randrange(0 ,len(legal_chars))
-
-def index_end():
-  return random.randrange(0 ,len(legal_chars_end))
-
-def char():
-  return legal_chars[index()]
-  
-def char_end():
-  return legal_chars_end[index_end()]
-
-def string(n=6):
-  if n < 0 : raise Exception("string called with negative length")
-  if n == 0 : return ""
-
-  result = char_end()
-  if  n == 1: return result
-
-  for _ in range(n-2): result += char()
-  result += char_end()
-
-  return result
-
-def  test_0():
-  limit = 1e7 # surely by then
-  i = 0
-  c = char()
-  while c != '~' and i < limit:
-    i += 1
-    c = char()
-  print(i)
-  return i < limit
-
-def  test_1():
-  limit = 1e7 # surely by then
-  i = 0
-  c = char()
-  while c != '0' and i < limit:
-    i += 1
-    c = char()
-  print(i)
-  return i < limit
-
-def  test_2():
-  limit = 1e7 # surely by then
-  i = 0
-  c = char_end()
-  while c != 'z' and i < limit:
-    i += 1
-    c = char_end()
-  print(i)
-  return i < limit
-
-def  test_3 ():
-  limit = 1e7 # surely by then
-  i = 0
-  c = char_end()
-  while c != 'A' and i < limit:
-    i += 1
-    c = char_end()
-  print(i)
-  return i < limit
-
-def  test_4():
-  s0 = string()
-  s1 = string(10)
-  s2 = string(100)
-
-  print(s0)
-  print(s1)
-  print(s2)
-
-  return len(s0)==6 and len(s1)==10 and len(s2)==100
-
-
-n=16
-if len(sys.argv) > 1:
-   n = int(sys.argv[1])
-print(string(n))
-
diff --git a/developer/bash/Z b/developer/bash/Z
new file mode 100755 (executable)
index 0000000..4cf0486
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+/usr/bin/date -u +"%Y-%m-%dT%H:%M:%SZ"
diff --git a/developer/bash/bashrc_example b/developer/bash/bashrc_example
new file mode 100644 (file)
index 0000000..0914cfc
--- /dev/null
@@ -0,0 +1,51 @@
+# ssh login will fail if .bashrc writes to stdout, so we write to "bash_error.txt"
+# set -x
+# in F37 something seems to be caching PATH, which can be annoying
+
+# If not running interactively, don't do anything
+  case $- in
+      *i*) ;;
+        *) return;;
+  esac
+
+# This should also be the default from login.defs, because gnome ignores 
+# .login, .profile, etc. and uses systemd to launch applications from the desktop,
+  umask 0077
+
+# - note the variable $PROMPT_DECOR, that is how the project name ends up in the prompt.
+# - without -i bash will clear PS1, just because, so we set PPS1, ,PPS2 to not lose the profit.
+# - use $(pwd) instead of \w or it will prefix '~' which confuses dirtrack when the
+#   user is changed using su
+  export PPS1='\n$($iseq/Z)[$PROMPT_DECOR]\n\u@\h§$(pwd)§\n> '
+  export PPS2='>> '
+  export PS1="$PPS1"
+  export PS2="$PPS2"
+
+# sort the output of printenv, show newlines as environment variable values as \n
+  alias printenv='printenv | awk '\''{gsub(/\n/, "\\n")}1'\'' | sort'
+
+# iso time in ls -l, show hidden files, human readable sizes
+  alias ls='ls -a -h --time-style=long-iso' 
+
+# iso time for all Linux programs, which they will all ignore, but at least we
+# tried, perhaps someday ...
+  export TZ=UTC
+  export TIME_STYLE=long-iso
+  export LC_ALL=en_DK.UTF-8
+
+# -l don't truncate long lins
+# -p show pids
+  alias pstree='pstree -lp'
+
+# - make bash gp to sleep, revealing the calling shell
+# - useful for job control of multiple bash shells from a controlling shell
+  alias zzz="kill -STOP \$\$"
+
+# The one true operating system.
+# Proof that an OS can be as small as an editor.
+  export EDITOR=emacs
+
+# check the window size after each command and, if necessary, update the values
+# of LINES and COLUMNS.
+  shopt -s checkwinsize
+
diff --git a/developer/bash/cat_w_fn b/developer/bash/cat_w_fn
new file mode 100755 (executable)
index 0000000..3308525
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# Check if at least one file is provided
+if [ $# -eq 0 ]; then
+  echo "Usage: $(script_fp) <filename1> [filename2] ..."
+  exit 1
+fi
+
+# Loop through all the provided files
+for file in "$@"; do
+  # Check if the file exists
+  if [ ! -f "$file" ]; then
+    echo "Error: File '$file' not found!"
+    continue
+  fi
+
+  # Print 80 dashes
+  printf '%.0s-' {1..80}
+  echo
+
+  # Print the filename and a colon
+  echo "$file:"
+
+  # Print the contents of the file
+  cat "$file"
+
+  # Print a newline for spacing between files
+  echo
+done
diff --git a/developer/bash/deprecate b/developer/bash/deprecate
new file mode 100755 (executable)
index 0000000..4713db5
--- /dev/null
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# cp subtree at <source> under file path <destination>, and make all the copied
+# files read-only. The intended use case is for moving files to a `deprecated`
+# directory. This helps prevent subsequent accidental editing.
+
+if [ "$#" -lt 2 ]; then
+  echo "Usage: $script_afp <source> <destination>"
+  exit 1
+fi
+SRC="$1"
+DEST="$2"
+
+mkdir -p "$DEST"
+mv "$SRC" "$DEST"
+
+# make stuff readonly
+cd "$DEST" || exit
+chmod -R u-w,go-rwx "$DEST"
diff --git a/developer/bash/env_administrator b/developer/bash/env_administrator
new file mode 100644 (file)
index 0000000..2f09f8a
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+  echo "$script_afp:: This script must be sourced, not executed."
+  exit 1
+fi
+
+source tool_shared/bespoke🖉/env
+source tool🖉/env
+
diff --git a/developer/bash/env_developer b/developer/bash/env_developer
new file mode 100644 (file)
index 0000000..3f3e1b5
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+  echo "$script_afp:: This script must be sourced, not executed."
+  exit 1
+fi
+
+source tool_shared/bespoke🖉/env
+source developer/tool🖉/env $@
+
diff --git a/developer/bash/env_run b/developer/bash/env_run
new file mode 100755 (executable)
index 0000000..e04b275
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+
+# Centralized environment executor. Typically used by IDEs to run developer/tool
+# or tester/tool commands in the correct environment. Shell users are encouraged
+# to source the appropriate environment file into their shell instead of
+# running commands through this executor.
+
+if [ "$#" -lt 2 ]; then
+    echo "Usage: $(basename $0) <env_script>[:args...] <command> [args...]"
+    echo "Example: $(basename $0) tester:developer Test_File0"
+    exit 1
+fi
+
+# Extract the env_script and optional arguments
+raw_env=$1
+shift
+command=$1
+shift
+command_args="$@"
+
+# Split the env_script and its arguments by colon
+IFS=":" read -r env_script env_args <<< "$raw_env"
+
+# Check if the env_script exists and is readable
+if [ ! -f "$env_script" ] || [ ! -r "$env_script" ]; then
+    echo "Error: Environment script '$env_script' not found or not readable."
+    exit 1
+fi
+
+# Split env_args into an array
+IFS=":" read -r -a env_args_array <<< "$env_args"
+
+# Source the script with the array of arguments
+source "$env_script" "${env_args_array[@]}"
+
+# Execute the command with its arguments
+exec "$command" $command_args
+
diff --git a/developer/bash/env_tester b/developer/bash/env_tester
new file mode 100644 (file)
index 0000000..919b789
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+  echo "$script_afp:: This script must be sourced, not executed."
+  exit 1
+fi
+
+source tool_shared/bespoke🖉/env
+source tester/tool🖉/env $@
diff --git a/developer/bash/githolder_to_empty_dirs b/developer/bash/githolder_to_empty_dirs
new file mode 100755 (executable)
index 0000000..49fb12b
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/env /bin/bash
+
+# Description: Descends from $1, or pwd, looking for empty directories and adds a `.githolder` to them.
+# does not descend into hidden directories.
+
+# examples:
+#   > git_holder
+#   > git_holder --dry-run
+
+set -e
+
+find_empty_dirs() {
+  local dir="$1"
+  local dry_run="$2"
+
+  # Skip `.git` specifically
+  if [[ "$(basename "$dir")" == ".git" ]]; then
+    return
+  fi
+
+  # Check if the directory is empty (including hidden files, excluding `.` and `..`)
+  if [[ -z $(find "$dir" -mindepth 1 -maxdepth 1 -print -quit) ]]; then
+    if [[ "$dry_run" == "true" ]]; then
+      echo "Dry-run: Would add .githolder in $dir"
+    else
+      echo "Adding .githolder to $dir"
+      touch "$dir/.githolder"
+    fi
+  else
+    # Recurse into subdirectories
+    for subdir in "$dir"/*/ "$dir"/.[!.]/; do
+      if [[ -d "$subdir" && "$subdir" != "$dir/.[!.]/" ]]; then
+        find_empty_dirs "$subdir" "$dry_run"
+      fi
+    done
+  fi
+}
+
+# Default parameters
+dry_run="false"
+target_dir="."
+
+# Parse arguments
+while [[ $# -gt 0 ]]; do
+  case "$1" in
+    --dry-run)
+      dry_run="true"
+      shift
+      ;;
+    *)
+      if [[ -d "$1" ]]; then
+        target_dir="$1"
+        shift
+      else
+        echo "Invalid argument: $1 is not a directory"
+        exit 1
+      fi
+      ;;
+  esac
+done
+
+# Run the function
+find_empty_dirs "$target_dir" "$dry_run"
diff --git a/developer/bash/make_project_skeleton.sh b/developer/bash/make_project_skeleton.sh
new file mode 100644 (file)
index 0000000..8404711
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+
+# this has never been run, but is the general idea ...  ROOT_DIR needs to be changed
+
+set -e
+
+ROOT_DIR="${1:-Harmony}"
+echo "Creating Harmony project skeleton in: $ROOT_DIR"
+
+# Create top-level structure
+mkdir -p "$ROOT_DIR"/{developer,release,tester,tmp,tool_shared/{bespoke🖉,customized,document🖉,third_party}}
+
+# Create env_<role> scripts as placeholders
+for role in developer tester toolsmith; do
+  touch "$ROOT_DIR/env_$role"
+done
+
+# Create LICENSE and README.md placeholders
+touch "$ROOT_DIR/LICENSE"
+touch "$ROOT_DIR/README.md"
+
+# Create git_holder in release/ and tester/
+touch "$ROOT_DIR/release/git_holder"
+touch "$ROOT_DIR/tester/git_holder"
+
+# Create .gitignore in tmp/ and third_party/
+cat > "$ROOT_DIR/tmp/.gitignore" <<EOF
+# Ignore all files
+*
+!.gitignore
+EOF
+
+cat > "$ROOT_DIR/tool_shared/third_party/.gitignore" <<EOF
+# Ignore all files
+*
+!.gitignore
+EOF
+
+# Add placeholder files in document🖉 and bespoke🖉
+touch "$ROOT_DIR/tool_shared/bespoke🖉/env"
+touch "$ROOT_DIR/tool_shared/bespoke🖉/version"
+touch "$ROOT_DIR/tool_shared/document🖉/README.org"
+
+# Feedback
+echo "✔ Project skeleton created."
+echo "   Remember to edit env_<role> scripts and LICENSE as needed."
diff --git a/developer/bash/release_dir b/developer/bash/release_dir
new file mode 100755 (executable)
index 0000000..67bdb42
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+  arch=$(uname -m)
+  os=$(source /etc/os-release && echo "$ID$VERSION_ID")
+  libc_version=$(ldd --version | head -n1 | awk '{print $NF}')  # glibc version
+  echo "$REPO_HOME/release/$arch/$os/glibc_$libc_version"
diff --git a/developer/bash/release_ls b/developer/bash/release_ls
new file mode 100755 (executable)
index 0000000..52550b6
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# before running this, make library is built and is in the scratchpad directory
+
+# input guards
+
+  env_must_be="developer/tool🖉/env"
+  if [ "$ENV" != "$env_must_be" ]; then
+    echo "$(script_fp):: error: must be run in the $env_must_be environment"
+    exit 1
+  fi
+
+  release_dir=$(release_dir)
+
+  if [ ! -d ${release_dir} ]; then
+    echo "$(script_fp):: no release directory: " ${release_dir}
+    exit 1
+  fi
+
+  ls $@ ${release_dir}
+
+
diff --git a/developer/bash/rm_tilda_files_tree b/developer/bash/rm_tilda_files_tree
new file mode 100755 (executable)
index 0000000..6ce67f5
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# rm_tilda_files_tree .
+#
+
+if [ ! -d "$1" ]; then
+  echo "expected first arg to be a directory where rm_tilda_files_tree is to be applied, but found: " "$1"
+  exit 1
+fi
+
+find "$1" -not -path '*/\.git/*' -name '*~' -exec rm {} \;
+
diff --git a/developer/bash/test_env b/developer/bash/test_env
new file mode 100755 (executable)
index 0000000..18d75f9
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# try both running and sourcing this test
+
+echo
+echo "--------------------------------------------------------------------------------"
+echo "from within test_shared/bespoke/test_env:"
+echo
+echo "REPO_HOME:" "$REPO_HOME"
+echo "PROJECT:" "$PROJECT"
+echo "script_afp:" "$script_afp"
+echo "script_adp:" "$(script_adp)"
+echo "script_fn:" "$(script_fn)"
+echo "script_fp:" "$(script_fp)"
+echo "script_dp:" "$(script_dp)"
+echo "ENV:" "$ENV"
+echo "-----------------------"
+echo "the BASH_SOURCE stack:"
+
+         top_index=$(( ${#BASH_SOURCE[@]} - 1 ))
+         for (( i=0; i<=top_index; i++ )); do
+           echo "$i: ${BASH_SOURCE[$i]}"
+         done
diff --git a/developer/bash/vl b/developer/bash/vl
new file mode 100755 (executable)
index 0000000..2c968d3
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+# vl 'vertical list'
+
+# Check if the command is provided
+if [ -z "$1" ]; then
+  echo "Usage: vl <command> [args...]"
+  exit 1
+fi
+
+# Capture the command and its arguments
+cmd=$1
+shift
+
+# Run the command with the remaining arguments and replace colons or spaces with newlines
+"$cmd" "$@" | tr ' :' '\n'
+
+exit 0
diff --git a/developer/bash/wipe_release b/developer/bash/wipe_release
new file mode 100755 (executable)
index 0000000..5bac0e7
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+# remove all files in the release directory
+set -e
+
+script_name=$(basename ${BASH_SOURCE[0]})
+if [ -z "$REPO_HOME" ]; then
+  echo "$script_name:: REPO_HOME is not set."
+  exit 1
+fi
+
+set -x
+cd "$REPO_HOME"
+rm -rf release/*
+set +x
+
+echo "$script_name done."
+
diff --git a/developer/bash🖉/Z b/developer/bash🖉/Z
deleted file mode 100755 (executable)
index 4cf0486..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-/usr/bin/date -u +"%Y-%m-%dT%H:%M:%SZ"
diff --git a/developer/bash🖉/bashrc_example b/developer/bash🖉/bashrc_example
deleted file mode 100644 (file)
index 0914cfc..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-# ssh login will fail if .bashrc writes to stdout, so we write to "bash_error.txt"
-# set -x
-# in F37 something seems to be caching PATH, which can be annoying
-
-# If not running interactively, don't do anything
-  case $- in
-      *i*) ;;
-        *) return;;
-  esac
-
-# This should also be the default from login.defs, because gnome ignores 
-# .login, .profile, etc. and uses systemd to launch applications from the desktop,
-  umask 0077
-
-# - note the variable $PROMPT_DECOR, that is how the project name ends up in the prompt.
-# - without -i bash will clear PS1, just because, so we set PPS1, ,PPS2 to not lose the profit.
-# - use $(pwd) instead of \w or it will prefix '~' which confuses dirtrack when the
-#   user is changed using su
-  export PPS1='\n$($iseq/Z)[$PROMPT_DECOR]\n\u@\h§$(pwd)§\n> '
-  export PPS2='>> '
-  export PS1="$PPS1"
-  export PS2="$PPS2"
-
-# sort the output of printenv, show newlines as environment variable values as \n
-  alias printenv='printenv | awk '\''{gsub(/\n/, "\\n")}1'\'' | sort'
-
-# iso time in ls -l, show hidden files, human readable sizes
-  alias ls='ls -a -h --time-style=long-iso' 
-
-# iso time for all Linux programs, which they will all ignore, but at least we
-# tried, perhaps someday ...
-  export TZ=UTC
-  export TIME_STYLE=long-iso
-  export LC_ALL=en_DK.UTF-8
-
-# -l don't truncate long lins
-# -p show pids
-  alias pstree='pstree -lp'
-
-# - make bash gp to sleep, revealing the calling shell
-# - useful for job control of multiple bash shells from a controlling shell
-  alias zzz="kill -STOP \$\$"
-
-# The one true operating system.
-# Proof that an OS can be as small as an editor.
-  export EDITOR=emacs
-
-# check the window size after each command and, if necessary, update the values
-# of LINES and COLUMNS.
-  shopt -s checkwinsize
-
diff --git a/developer/bash🖉/cat_w_fn b/developer/bash🖉/cat_w_fn
deleted file mode 100755 (executable)
index 3308525..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-
-# Check if at least one file is provided
-if [ $# -eq 0 ]; then
-  echo "Usage: $(script_fp) <filename1> [filename2] ..."
-  exit 1
-fi
-
-# Loop through all the provided files
-for file in "$@"; do
-  # Check if the file exists
-  if [ ! -f "$file" ]; then
-    echo "Error: File '$file' not found!"
-    continue
-  fi
-
-  # Print 80 dashes
-  printf '%.0s-' {1..80}
-  echo
-
-  # Print the filename and a colon
-  echo "$file:"
-
-  # Print the contents of the file
-  cat "$file"
-
-  # Print a newline for spacing between files
-  echo
-done
diff --git a/developer/bash🖉/deprecate b/developer/bash🖉/deprecate
deleted file mode 100755 (executable)
index 4713db5..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-
-# cp subtree at <source> under file path <destination>, and make all the copied
-# files read-only. The intended use case is for moving files to a `deprecated`
-# directory. This helps prevent subsequent accidental editing.
-
-if [ "$#" -lt 2 ]; then
-  echo "Usage: $script_afp <source> <destination>"
-  exit 1
-fi
-SRC="$1"
-DEST="$2"
-
-mkdir -p "$DEST"
-mv "$SRC" "$DEST"
-
-# make stuff readonly
-cd "$DEST" || exit
-chmod -R u-w,go-rwx "$DEST"
diff --git a/developer/bash🖉/env_administrator b/developer/bash🖉/env_administrator
deleted file mode 100644 (file)
index 2f09f8a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
-  echo "$script_afp:: This script must be sourced, not executed."
-  exit 1
-fi
-
-source tool_shared/bespoke🖉/env
-source tool🖉/env
-
diff --git a/developer/bash🖉/env_developer b/developer/bash🖉/env_developer
deleted file mode 100644 (file)
index 3f3e1b5..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
-  echo "$script_afp:: This script must be sourced, not executed."
-  exit 1
-fi
-
-source tool_shared/bespoke🖉/env
-source developer/tool🖉/env $@
-
diff --git a/developer/bash🖉/env_run b/developer/bash🖉/env_run
deleted file mode 100755 (executable)
index e04b275..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env bash
-
-# Centralized environment executor. Typically used by IDEs to run developer/tool
-# or tester/tool commands in the correct environment. Shell users are encouraged
-# to source the appropriate environment file into their shell instead of
-# running commands through this executor.
-
-if [ "$#" -lt 2 ]; then
-    echo "Usage: $(basename $0) <env_script>[:args...] <command> [args...]"
-    echo "Example: $(basename $0) tester:developer Test_File0"
-    exit 1
-fi
-
-# Extract the env_script and optional arguments
-raw_env=$1
-shift
-command=$1
-shift
-command_args="$@"
-
-# Split the env_script and its arguments by colon
-IFS=":" read -r env_script env_args <<< "$raw_env"
-
-# Check if the env_script exists and is readable
-if [ ! -f "$env_script" ] || [ ! -r "$env_script" ]; then
-    echo "Error: Environment script '$env_script' not found or not readable."
-    exit 1
-fi
-
-# Split env_args into an array
-IFS=":" read -r -a env_args_array <<< "$env_args"
-
-# Source the script with the array of arguments
-source "$env_script" "${env_args_array[@]}"
-
-# Execute the command with its arguments
-exec "$command" $command_args
-
diff --git a/developer/bash🖉/env_tester b/developer/bash🖉/env_tester
deleted file mode 100644 (file)
index 919b789..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
-  echo "$script_afp:: This script must be sourced, not executed."
-  exit 1
-fi
-
-source tool_shared/bespoke🖉/env
-source tester/tool🖉/env $@
diff --git a/developer/bash🖉/githolder_to_empty_dirs b/developer/bash🖉/githolder_to_empty_dirs
deleted file mode 100755 (executable)
index 49fb12b..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/bin/env /bin/bash
-
-# Description: Descends from $1, or pwd, looking for empty directories and adds a `.githolder` to them.
-# does not descend into hidden directories.
-
-# examples:
-#   > git_holder
-#   > git_holder --dry-run
-
-set -e
-
-find_empty_dirs() {
-  local dir="$1"
-  local dry_run="$2"
-
-  # Skip `.git` specifically
-  if [[ "$(basename "$dir")" == ".git" ]]; then
-    return
-  fi
-
-  # Check if the directory is empty (including hidden files, excluding `.` and `..`)
-  if [[ -z $(find "$dir" -mindepth 1 -maxdepth 1 -print -quit) ]]; then
-    if [[ "$dry_run" == "true" ]]; then
-      echo "Dry-run: Would add .githolder in $dir"
-    else
-      echo "Adding .githolder to $dir"
-      touch "$dir/.githolder"
-    fi
-  else
-    # Recurse into subdirectories
-    for subdir in "$dir"/*/ "$dir"/.[!.]/; do
-      if [[ -d "$subdir" && "$subdir" != "$dir/.[!.]/" ]]; then
-        find_empty_dirs "$subdir" "$dry_run"
-      fi
-    done
-  fi
-}
-
-# Default parameters
-dry_run="false"
-target_dir="."
-
-# Parse arguments
-while [[ $# -gt 0 ]]; do
-  case "$1" in
-    --dry-run)
-      dry_run="true"
-      shift
-      ;;
-    *)
-      if [[ -d "$1" ]]; then
-        target_dir="$1"
-        shift
-      else
-        echo "Invalid argument: $1 is not a directory"
-        exit 1
-      fi
-      ;;
-  esac
-done
-
-# Run the function
-find_empty_dirs "$target_dir" "$dry_run"
diff --git a/developer/bash🖉/release_dir b/developer/bash🖉/release_dir
deleted file mode 100755 (executable)
index 67bdb42..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-
-  arch=$(uname -m)
-  os=$(source /etc/os-release && echo "$ID$VERSION_ID")
-  libc_version=$(ldd --version | head -n1 | awk '{print $NF}')  # glibc version
-  echo "$REPO_HOME/release/$arch/$os/glibc_$libc_version"
diff --git a/developer/bash🖉/release_ls b/developer/bash🖉/release_ls
deleted file mode 100755 (executable)
index 52550b6..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-
-# before running this, make library is built and is in the scratchpad directory
-
-# input guards
-
-  env_must_be="developer/tool🖉/env"
-  if [ "$ENV" != "$env_must_be" ]; then
-    echo "$(script_fp):: error: must be run in the $env_must_be environment"
-    exit 1
-  fi
-
-  release_dir=$(release_dir)
-
-  if [ ! -d ${release_dir} ]; then
-    echo "$(script_fp):: no release directory: " ${release_dir}
-    exit 1
-  fi
-
-  ls $@ ${release_dir}
-
-
diff --git a/developer/bash🖉/rm_tilda_files_tree b/developer/bash🖉/rm_tilda_files_tree
deleted file mode 100755 (executable)
index 6ce67f5..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-#
-# rm_tilda_files_tree .
-#
-
-if [ ! -d "$1" ]; then
-  echo "expected first arg to be a directory where rm_tilda_files_tree is to be applied, but found: " "$1"
-  exit 1
-fi
-
-find "$1" -not -path '*/\.git/*' -name '*~' -exec rm {} \;
-
diff --git a/developer/bash🖉/test_env b/developer/bash🖉/test_env
deleted file mode 100755 (executable)
index 18d75f9..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-
-# try both running and sourcing this test
-
-echo
-echo "--------------------------------------------------------------------------------"
-echo "from within test_shared/bespoke/test_env:"
-echo
-echo "REPO_HOME:" "$REPO_HOME"
-echo "PROJECT:" "$PROJECT"
-echo "script_afp:" "$script_afp"
-echo "script_adp:" "$(script_adp)"
-echo "script_fn:" "$(script_fn)"
-echo "script_fp:" "$(script_fp)"
-echo "script_dp:" "$(script_dp)"
-echo "ENV:" "$ENV"
-echo "-----------------------"
-echo "the BASH_SOURCE stack:"
-
-         top_index=$(( ${#BASH_SOURCE[@]} - 1 ))
-         for (( i=0; i<=top_index; i++ )); do
-           echo "$i: ${BASH_SOURCE[$i]}"
-         done
diff --git a/developer/bash🖉/vl b/developer/bash🖉/vl
deleted file mode 100755 (executable)
index 2c968d3..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-# vl 'vertical list'
-
-# Check if the command is provided
-if [ -z "$1" ]; then
-  echo "Usage: vl <command> [args...]"
-  exit 1
-fi
-
-# Capture the command and its arguments
-cmd=$1
-shift
-
-# Run the command with the remaining arguments and replace colons or spaces with newlines
-"$cmd" "$@" | tr ' :' '\n'
-
-exit 0
diff --git a/developer/bash🖉/wipe_release b/developer/bash🖉/wipe_release
deleted file mode 100755 (executable)
index 5bac0e7..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-# remove all files in the release directory
-set -e
-
-script_name=$(basename ${BASH_SOURCE[0]})
-if [ -z "$REPO_HOME" ]; then
-  echo "$script_name:: REPO_HOME is not set."
-  exit 1
-fi
-
-set -x
-cd "$REPO_HOME"
-rm -rf release/*
-set +x
-
-echo "$script_name done."
-
diff --git a/developer/cc/home.cli.c b/developer/cc/home.cli.c
new file mode 100644 (file)
index 0000000..d990d96
--- /dev/null
@@ -0,0 +1,35 @@
+#define IFACE
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <string.h>
+#include <stdio.h>
+
+/*
+We return the home directory without a trailing slash.  Otherwise in bash scripts ~/... will
+expand out with two slashes.  Also, if we returned with a trailing slash, then rsync 
+would behave differently with ~ (specifying contents of home instead of home itself).
+
+I am not sure if pw_dir has always returned a trailing slash on the home directory, though with
+the latest upgrade is the first time I am noticing two slashes in transcripts.
+
+It is an error for pw_dir to be an empty string?  I suppose not, but rather it is assumed
+to be the root of the file system?  Perhaps that is why they added the slash, to make
+that clear.
+
+*/
+int main(){
+  struct passwd *pw = getpwuid(getuid());
+  const char *homedir = pw->pw_dir;
+
+  size_t n = strlen(homedir);
+  if( n == 0 ) return 1;
+  while(n > 1){
+    fputc(*homedir ,stdout);
+  --n;
+  ++homedir;
+  };
+  if(*homedir == '/') return 1;
+  fputc(*homedir ,stdout);
+  return 1;
+}
diff --git a/developer/cc/is_authored_fs_obj.c b/developer/cc/is_authored_fs_obj.c
new file mode 100644 (file)
index 0000000..1c82e9a
--- /dev/null
@@ -0,0 +1,56 @@
+#include <string.h>
+#include <stdbool.h>
+
+static bool is_authored_fs_obj(const char *path) {
+    if (!path || strlen(path) == 0) {
+        return false;
+    }
+
+    // Check if the last character is the pencil
+    size_t len = strlen(path);
+    return path[len - 1] == '🖉';
+}
+
+
+#include <stdlib.h>
+#include <libgen.h>
+#include <stdbool.h>
+#include <string.h>
+
+static bool is_authored(const char *path) {
+    if (!path || strlen(path) == 0) {
+        return false;
+    }
+
+    // Check the path itself
+    if (is_authored_fs_obj(path)) {
+        return true;
+    }
+
+    // Check each parent directory up to the root
+    char *path_copy = strdup(path);
+    if (!path_copy) {
+        return false; // Memory allocation failure
+    }
+
+    char *parent = path_copy;
+    bool authored = false;
+
+    while (true) {
+        parent = dirname(parent);
+
+        // Check if the current directory is authored
+        if (is_authored_fs_obj(parent)) {
+            authored = true;
+            break;
+        }
+
+        // If we reach the root, stop
+        if (strcmp(parent, "/") == 0) {
+            break;
+        }
+    }
+
+    free(path_copy);
+    return authored;
+}
diff --git a/developer/cc/remove.c b/developer/cc/remove.c
new file mode 100644 (file)
index 0000000..3ce98f9
--- /dev/null
@@ -0,0 +1,762 @@
+#include <config.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <string.h>
+#include <stdbool.h>
+
+static bool is_authored_fs_obj(const char *path) {
+    if (!path || strlen(path) == 0) {
+        return false;
+    }
+
+    // Check if the last character is the pencil (as a string)
+    const char *suffix = "🖉";
+    size_t len = strlen(path);
+    size_t suffix_len = strlen(suffix);
+
+    if (len < suffix_len) {
+        return false;
+    }
+
+    return strcmp(path + len - suffix_len, suffix) == 0;
+}
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <libgen.h>
+#include <limits.h>
+#include <unistd.h>
+
+static bool is_authored(const char *path) {
+    if (!path || strlen(path) == 0) {
+        fprintf(stderr, "DEBUG: Invalid path provided\n");
+        return false;
+    }
+
+    // Convert to an absolute path
+    char abs_path[PATH_MAX];
+    if (!realpath(path, abs_path)) {
+        fprintf(stderr, "DEBUG: Failed to resolve absolute path for: %s\n", path);
+        return false;
+    }
+
+    fprintf(stderr, "DEBUG: Starting check for path: %s (resolved: %s)\n", path, abs_path);
+
+    // Allocate and copy for safe modifications
+    char *current_path = strdup(abs_path);
+    if (!current_path) {
+        fprintf(stderr, "DEBUG: Memory allocation failed for current_path\n");
+        return false;
+    }
+
+    bool authored = false;
+    int iteration_count = 0;
+
+    while (true) {
+        fprintf(stderr, "DEBUG: Iteration %d, checking path: %s\n", iteration_count, current_path);
+
+        // Check if the current path is authored
+        if (is_authored_fs_obj(current_path)) {
+            fprintf(stderr, "DEBUG: Found authored path: %s\n", current_path);
+            authored = true;
+            break;
+        }
+
+        // Get parent directory
+        char *parent_path = strdup(current_path);
+        if (!parent_path) {
+            fprintf(stderr, "DEBUG: Memory allocation failed for parent_path\n");
+            break;
+        }
+        char *parent = dirname(parent_path);
+
+        // Stop condition: root or no change in path
+        if (strcmp(parent, "/") == 0 || strcmp(parent, current_path) == 0) {
+            fprintf(stderr, "DEBUG: Reached stop condition at parent: %s\n", parent);
+            free(parent_path);
+            break;
+        }
+
+        // Update current_path for the next iteration
+        free(current_path);
+        current_path = strdup(parent);
+        if (!current_path) {
+            fprintf(stderr, "DEBUG: Memory allocation failed while updating current_path\n");
+            free(parent_path);
+            break;
+        }
+
+        free(parent_path);
+        iteration_count++;
+
+        // Failsafe for infinite loops
+        if (iteration_count > 100) {
+            fprintf(stderr, "DEBUG: Too many iterations, exiting to avoid infinite loop\n");
+            break;
+        }
+    }
+
+    free(current_path);
+    return authored;
+}
+
+
+/* remove.c -- core functions for removing files and directories
+   Copyright (C) 1988-2024 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Extracted from rm.c, librarified, then rewritten twice by Jim Meyering.  */
+
+#include <config.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "system.h"
+#include "assure.h"
+#include "file-type.h"
+#include "filenamecat.h"
+#include "ignore-value.h"
+#include "remove.h"
+#include "root-dev-ino.h"
+#include "stat-time.h"
+#include "write-any-file.h"
+#include "xfts.h"
+#include "yesno.h"
+
+/* The prompt function may be called twice for a given directory.
+   The first time, we ask whether to descend into it, and the
+   second time, we ask whether to remove it.  */
+enum Prompt_action
+  {
+    PA_DESCEND_INTO_DIR = 2,
+    PA_REMOVE_DIR
+  };
+
+/* D_TYPE(D) is the type of directory entry D if known, DT_UNKNOWN
+   otherwise.  */
+#if ! HAVE_STRUCT_DIRENT_D_TYPE
+/* Any int values will do here, so long as they're distinct.
+   Undef any existing macros out of the way.  */
+# undef DT_UNKNOWN
+# undef DT_DIR
+# undef DT_LNK
+# define DT_UNKNOWN 0
+# define DT_DIR 1
+# define DT_LNK 2
+#endif
+
+/* Like fstatat, but cache on POSIX-compatible systems.  */
+static int
+cache_fstatat (int fd, char const *file, struct stat *st, int flag)
+{
+#if HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
+  /* If ST->st_atim.tv_nsec is -1, the status has not been gotten yet.
+     If less than -1, fstatat failed with errno == ST->st_ino.
+     Otherwise, the status has already been gotten, so return 0.  */
+  if (0 <= st->st_atim.tv_nsec)
+    return 0;
+  if (st->st_atim.tv_nsec == -1)
+    {
+      if (fstatat (fd, file, st, flag) == 0)
+        return 0;
+      st->st_atim.tv_nsec = -2;
+      st->st_ino = errno;
+    }
+  errno = st->st_ino;
+  return -1;
+#else
+  return fstatat (fd, file, st, flag);
+#endif
+}
+
+/* Initialize a fstatat cache *ST.  Return ST for convenience.  */
+static inline struct stat *
+cache_stat_init (struct stat *st)
+{
+#if HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
+  st->st_atim.tv_nsec = -1;
+#endif
+  return st;
+}
+
+/* Return 1 if FILE is an unwritable non-symlink,
+   0 if it is writable or some other type of file,
+   -1 and set errno if there is some problem in determining the answer.
+   Set *BUF to the file status.  */
+static int
+write_protected_non_symlink (int fd_cwd,
+                             char const *file,
+                             struct stat *buf)
+{
+  if (can_write_any_file ())
+    return 0;
+  if (cache_fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0)
+    return -1;
+  if (S_ISLNK (buf->st_mode))
+    return 0;
+  /* Here, we know FILE is not a symbolic link.  */
+
+  /* In order to be reentrant -- i.e., to avoid changing the working
+     directory, and at the same time to be able to deal with alternate
+     access control mechanisms (ACLs, xattr-style attributes) and
+     arbitrarily deep trees -- we need a function like eaccessat, i.e.,
+     like Solaris' eaccess, but fd-relative, in the spirit of openat.  */
+
+  /* In the absence of a native eaccessat function, here are some of
+     the implementation choices [#4 and #5 were suggested by Paul Eggert]:
+     1) call openat with O_WRONLY|O_NOCTTY
+        Disadvantage: may create the file and doesn't work for directory,
+        may mistakenly report 'unwritable' for EROFS or ACLs even though
+        perm bits say the file is writable.
+
+     2) fake eaccessat (save_cwd, fchdir, call euidaccess, restore_cwd)
+        Disadvantage: changes working directory (not reentrant) and can't
+        work if save_cwd fails.
+
+     3) if (euidaccess (full_name, W_OK) == 0)
+        Disadvantage: doesn't work if full_name is too long.
+        Inefficient for very deep trees (O(Depth^2)).
+
+     4) If the full pathname is sufficiently short (say, less than
+        PATH_MAX or 8192 bytes, whichever is shorter):
+        use method (3) (i.e., euidaccess (full_name, W_OK));
+        Otherwise: vfork, fchdir in the child, run euidaccess in the
+        child, then the child exits with a status that tells the parent
+        whether euidaccess succeeded.
+
+        This avoids the O(N**2) algorithm of method (3), and it also avoids
+        the failure-due-to-too-long-file-names of method (3), but it's fast
+        in the normal shallow case.  It also avoids the lack-of-reentrancy
+        and the save_cwd problems.
+        Disadvantage; it uses a process slot for very-long file names,
+        and would be very slow for hierarchies with many such files.
+
+     5) If the full file name is sufficiently short (say, less than
+        PATH_MAX or 8192 bytes, whichever is shorter):
+        use method (3) (i.e., euidaccess (full_name, W_OK));
+        Otherwise: look just at the file bits.  Perhaps issue a warning
+        the first time this occurs.
+
+        This is like (4), except for the "Otherwise" case where it isn't as
+        "perfect" as (4) but is considerably faster.  It conforms to current
+        POSIX, and is uniformly better than what Solaris and FreeBSD do (they
+        mess up with long file names). */
+
+  {
+    if (faccessat (fd_cwd, file, W_OK, AT_EACCESS) == 0)
+      return 0;
+
+    return errno == EACCES ? 1 : -1;
+  }
+}
+
+/* Return the status of the directory identified by FTS and ENT.
+   This is -1 if the directory is empty, 0 if it is nonempty,
+   and a positive error number if there was trouble determining the status,
+   e.g., it is not a directory, or permissions problems, or I/O errors.
+   Use *DIR_STATUS as a cache for the status.  */
+static int
+get_dir_status (FTS const *fts, FTSENT const *ent, int *dir_status)
+{
+  if (*dir_status == DS_UNKNOWN)
+    *dir_status = directory_status (fts->fts_cwd_fd, ent->fts_accpath);
+  return *dir_status;
+}
+
+/* Prompt whether to remove FILENAME, if required via a combination of
+   the options specified by X and/or file attributes.  If the file may
+   be removed, return RM_OK or RM_USER_ACCEPTED, the latter if the user
+   was prompted and accepted.  If the user declines to remove the file,
+   return RM_USER_DECLINED.  If not ignoring missing files and we
+   cannot lstat FILENAME, then return RM_ERROR.
+
+   IS_DIR is true if ENT designates a directory, false otherwise.
+
+   Depending on MODE, ask whether to 'descend into' or to 'remove' the
+   directory FILENAME.  MODE is ignored when FILENAME is not a directory.
+   Use and update *DIR_STATUS as needed, via the conventions of
+   get_dir_status.  */
+static enum RM_status
+prompt (FTS const *fts, FTSENT const *ent, bool is_dir,
+        struct rm_options const *x, enum Prompt_action mode,
+        int *dir_status)
+{
+  int fd_cwd = fts->fts_cwd_fd;
+  char const *full_name = ent->fts_path;
+  char const *filename = ent->fts_accpath;
+  struct stat st;
+  struct stat *sbuf = &st;
+  cache_stat_init (sbuf);
+
+  int dirent_type = is_dir ? DT_DIR : DT_UNKNOWN;
+  int write_protected = 0;
+
+  /* When nonzero, this indicates that we failed to remove a child entry,
+     either because the user declined an interactive prompt, or due to
+     some other failure, like permissions.  */
+  if (ent->fts_number)
+    return RM_USER_DECLINED;
+
+  if (x->interactive == RMI_NEVER)
+    return RM_OK;
+
+  int wp_errno = 0;
+  if (!x->ignore_missing_files
+      && (x->interactive == RMI_ALWAYS || x->stdin_tty)
+      && dirent_type != DT_LNK)
+    {
+      write_protected = write_protected_non_symlink (fd_cwd, filename, sbuf);
+      wp_errno = errno;
+    }
+
+  if (write_protected || x->interactive == RMI_ALWAYS)
+    {
+      if (0 <= write_protected && dirent_type == DT_UNKNOWN)
+        {
+          if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) == 0)
+            {
+              if (S_ISLNK (sbuf->st_mode))
+                dirent_type = DT_LNK;
+              else if (S_ISDIR (sbuf->st_mode))
+                dirent_type = DT_DIR;
+              /* Otherwise it doesn't matter, so leave it DT_UNKNOWN.  */
+            }
+          else
+            {
+              /* This happens, e.g., with 'rm '''.  */
+              write_protected = -1;
+              wp_errno = errno;
+            }
+        }
+
+      if (0 <= write_protected)
+        switch (dirent_type)
+          {
+          case DT_LNK:
+            /* Using permissions doesn't make sense for symlinks.  */
+            if (x->interactive != RMI_ALWAYS)
+              return RM_OK;
+            break;
+
+          case DT_DIR:
+             /* Unless we're either deleting directories or deleting
+                recursively, we want to raise an EISDIR error rather than
+                prompting the user  */
+            if ( ! (x->recursive
+                    || (x->remove_empty_directories
+                        && get_dir_status (fts, ent, dir_status) != 0)))
+              {
+                write_protected = -1;
+                wp_errno = *dir_status <= 0 ? EISDIR : *dir_status;
+              }
+            break;
+          }
+
+      char const *quoted_name = quoteaf (full_name);
+
+      if (write_protected < 0)
+        {
+          error (0, wp_errno, _("cannot remove %s"), quoted_name);
+          return RM_ERROR;
+        }
+
+      /* Issue the prompt.  */
+      if (dirent_type == DT_DIR
+          && mode == PA_DESCEND_INTO_DIR
+          && get_dir_status (fts, ent, dir_status) == DS_NONEMPTY)
+        fprintf (stderr,
+                 (write_protected
+                  ? _("%s: descend into write-protected directory %s? ")
+                  : _("%s: descend into directory %s? ")),
+                 program_name, quoted_name);
+      else if (0 < *dir_status)
+        {
+          if ( ! (x->remove_empty_directories && *dir_status == EACCES))
+            {
+              error (0, *dir_status, _("cannot remove %s"), quoted_name);
+              return RM_ERROR;
+            }
+
+          /* The following code can lead to a successful deletion only with
+             the --dir (-d) option (remove_empty_directories) and an empty
+             inaccessible directory. In the first prompt call for a directory,
+             we'd normally ask whether to descend into it, but in this case
+             (it's inaccessible), that is not possible, so don't prompt.  */
+          if (mode == PA_DESCEND_INTO_DIR)
+            return RM_OK;
+
+          fprintf (stderr,
+               _("%s: attempt removal of inaccessible directory %s? "),
+                   program_name, quoted_name);
+        }
+      else
+        {
+          if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0)
+            {
+              error (0, errno, _("cannot remove %s"), quoted_name);
+              return RM_ERROR;
+            }
+
+          fprintf (stderr,
+                   (write_protected
+                    /* TRANSLATORS: In the next two strings the second %s is
+                       replaced by the type of the file.  To avoid grammatical
+                       problems, it may be more convenient to translate these
+                       strings instead as: "%1$s: %3$s is write-protected and
+                       is of type '%2$s' -- remove it? ".  */
+                    ? _("%s: remove write-protected %s %s? ")
+                    : _("%s: remove %s %s? ")),
+                   program_name, file_type (sbuf), quoted_name);
+        }
+
+      return yesno () ? RM_USER_ACCEPTED : RM_USER_DECLINED;
+    }
+  return RM_OK;
+}
+
+/* When a function like unlink, rmdir, or fstatat fails with an errno
+   value of ERRNUM, return true if the specified file system object
+   is guaranteed not to exist;  otherwise, return false.  */
+static inline bool
+nonexistent_file_errno (int errnum)
+{
+  /* Do not include ELOOP here, since the specified file may indeed
+     exist, but be (in)accessible only via too long a symlink chain.
+     Likewise for ENAMETOOLONG, since rm -f ./././.../foo may fail
+     if the "..." part expands to a long enough sequence of "./"s,
+     even though ./foo does indeed exist.
+
+     Another case to consider is when a particular name is invalid for
+     a given file system.  In 2011, smbfs returns EINVAL, but the next
+     revision of POSIX will require EILSEQ for that situation:
+     https://austingroupbugs.net/view.php?id=293
+  */
+
+  switch (errnum)
+    {
+    case EILSEQ:
+    case EINVAL:
+    case ENOENT:
+    case ENOTDIR:
+      return true;
+    default:
+      return false;
+    }
+}
+
+/* Encapsulate the test for whether the errno value, ERRNUM, is ignorable.  */
+static inline bool
+ignorable_missing (struct rm_options const *x, int errnum)
+{
+  return x->ignore_missing_files && nonexistent_file_errno (errnum);
+}
+
+/* Tell fts not to traverse into the hierarchy at ENT.  */
+static void
+fts_skip_tree (FTS *fts, FTSENT *ent)
+{
+  fts_set (fts, ent, FTS_SKIP);
+  /* Ensure that we do not process ENT a second time.  */
+  ignore_value (fts_read (fts));
+}
+
+/* Upon unlink failure, or when the user declines to remove ENT, mark
+   each of its ancestor directories, so that we know not to prompt for
+   its removal.  */
+static void
+mark_ancestor_dirs (FTSENT *ent)
+{
+  FTSENT *p;
+  for (p = ent->fts_parent; FTS_ROOTLEVEL <= p->fts_level; p = p->fts_parent)
+    {
+      if (p->fts_number)
+        break;
+      p->fts_number = 1;
+    }
+}
+
+/* Remove the file system object specified by ENT.  IS_DIR specifies
+   whether it is expected to be a directory or non-directory.
+   Return RM_OK upon success, else RM_ERROR.  */
+static enum RM_status
+excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir)
+{
+  int flag = is_dir ? AT_REMOVEDIR : 0;
+  if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0)
+    {
+      if (x->verbose)
+        {
+          printf ((is_dir
+                   ? _("removed directory %s\n")
+                   : _("removed %s\n")), quoteaf (ent->fts_path));
+        }
+      return RM_OK;
+    }
+
+  /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for
+     nonexistent files.  When the file is indeed missing, map that to ENOENT,
+     so that rm -f ignores it, as required.  Even without -f, this is useful
+     because it makes rm print the more precise diagnostic.  */
+  if (errno == EROFS)
+    {
+      struct stat st;
+      if ( ! (fstatat (fts->fts_cwd_fd, ent->fts_accpath, &st,
+                       AT_SYMLINK_NOFOLLOW)
+              && errno == ENOENT))
+        errno = EROFS;
+    }
+
+  if (ignorable_missing (x, errno))
+    return RM_OK;
+
+  /* When failing to rmdir an unreadable directory, we see errno values
+     like EISDIR or ENOTDIR (or, on Solaris 10, EEXIST), but they would be
+     meaningless in a diagnostic.  When that happens, use the earlier, more
+     descriptive errno value.  */
+  if (ent->fts_info == FTS_DNR
+      && (errno == ENOTEMPTY || errno == EISDIR || errno == ENOTDIR
+          || errno == EEXIST)
+      && ent->fts_errno != 0)
+    errno = ent->fts_errno;
+  error (0, errno, _("cannot remove %s"), quoteaf (ent->fts_path));
+  mark_ancestor_dirs (ent);
+  return RM_ERROR;
+}
+
+/* This function is called once for every file system object that fts
+   encounters.  fts performs a depth-first traversal.
+   A directory is usually processed twice, first with fts_info == FTS_D,
+   and later, after all of its entries have been processed, with FTS_DP.
+   Return RM_ERROR upon error, RM_USER_DECLINED for a negative response
+   to an interactive prompt, and otherwise, RM_OK.  */
+static enum RM_status
+rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x)
+{
+  int dir_status = DS_UNKNOWN;
+
+if (is_authored(ent->fts_path)) {
+    fprintf(stderr, "rm: cannot remove authored %s '%s'\n",
+            (ent->fts_info == FTS_D || ent->fts_info == FTS_DP) ? "directory" : "file",
+            ent->fts_path);
+    return RM_ERROR; // Skip authored files
+}
+
+
+  switch (ent->fts_info)
+    {
+    case FTS_D:                        /* preorder directory */
+      if (! x->recursive
+          && !(x->remove_empty_directories
+               && get_dir_status (fts, ent, &dir_status) != 0))
+        {
+          /* This is the first (pre-order) encounter with a directory
+             that we cannot delete.
+             Not recursive, and it's not an empty directory (if we're removing
+             them) so arrange to skip contents.  */
+          int err = x->remove_empty_directories ? ENOTEMPTY : EISDIR;
+          error (0, err, _("cannot remove %s"), quoteaf (ent->fts_path));
+          mark_ancestor_dirs (ent);
+          fts_skip_tree (fts, ent);
+          return RM_ERROR;
+        }
+
+      /* Perform checks that can apply only for command-line arguments.  */
+      if (ent->fts_level == FTS_ROOTLEVEL)
+        {
+          /* POSIX says:
+             If the basename of a command line argument is "." or "..",
+             diagnose it and do nothing more with that argument.  */
+          if (dot_or_dotdot (last_component (ent->fts_accpath)))
+            {
+              error (0, 0,
+                     _("refusing to remove %s or %s directory: skipping %s"),
+                     quoteaf_n (0, "."), quoteaf_n (1, ".."),
+                     quoteaf_n (2, ent->fts_path));
+              fts_skip_tree (fts, ent);
+              return RM_ERROR;
+            }
+
+          /* POSIX also says:
+             If a command line argument resolves to "/" (and --preserve-root
+             is in effect -- default) diagnose and skip it.  */
+          if (ROOT_DEV_INO_CHECK (x->root_dev_ino, ent->fts_statp))
+            {
+              ROOT_DEV_INO_WARN (ent->fts_path);
+              fts_skip_tree (fts, ent);
+              return RM_ERROR;
+            }
+
+          /* If a command line argument is a mount point and
+             --preserve-root=all is in effect, diagnose and skip it.
+             This doesn't handle "/", but that's handled above.  */
+          if (x->preserve_all_root)
+            {
+              bool failed = false;
+              char *parent = file_name_concat (ent->fts_accpath, "..", nullptr);
+              struct stat statbuf;
+
+              if (!parent || lstat (parent, &statbuf))
+                {
+                  error (0, 0,
+                         _("failed to stat %s: skipping %s"),
+                         quoteaf_n (0, parent),
+                         quoteaf_n (1, ent->fts_accpath));
+                  failed = true;
+                }
+
+              free (parent);
+
+              if (failed || fts->fts_dev != statbuf.st_dev)
+                {
+                  if (! failed)
+                    {
+                      error (0, 0,
+                             _("skipping %s, since it's on a different device"),
+                             quoteaf (ent->fts_path));
+                      error (0, 0, _("and --preserve-root=all is in effect"));
+                    }
+                  fts_skip_tree (fts, ent);
+                  return RM_ERROR;
+                }
+            }
+        }
+
+      {
+        enum RM_status s = prompt (fts, ent, true /*is_dir*/, x,
+                                   PA_DESCEND_INTO_DIR, &dir_status);
+
+        if (s == RM_USER_ACCEPTED && dir_status == DS_EMPTY)
+          {
+            /* When we know (from prompt when in interactive mode)
+               that this is an empty directory, don't prompt twice.  */
+            s = excise (fts, ent, x, true);
+            if (s == RM_OK)
+              fts_skip_tree (fts, ent);
+          }
+
+        if (! (s == RM_OK || s == RM_USER_ACCEPTED))
+          {
+            mark_ancestor_dirs (ent);
+            fts_skip_tree (fts, ent);
+          }
+
+        return s;
+      }
+
+    case FTS_F:                        /* regular file */
+    case FTS_NS:               /* stat(2) failed */
+    case FTS_SL:               /* symbolic link */
+    case FTS_SLNONE:           /* symbolic link without target */
+    case FTS_DP:               /* postorder directory */
+    case FTS_DNR:              /* unreadable directory */
+    case FTS_NSOK:             /* e.g., dangling symlink */
+    case FTS_DEFAULT:          /* none of the above */
+      {
+        /* With --one-file-system, do not attempt to remove a mount point.
+           fts' FTS_XDEV ensures that we don't process any entries under
+           the mount point.  */
+        if (ent->fts_info == FTS_DP
+            && x->one_file_system
+            && FTS_ROOTLEVEL < ent->fts_level
+            && ent->fts_statp->st_dev != fts->fts_dev)
+          {
+            mark_ancestor_dirs (ent);
+            error (0, 0, _("skipping %s, since it's on a different device"),
+                   quoteaf (ent->fts_path));
+            return RM_ERROR;
+          }
+
+        bool is_dir = ent->fts_info == FTS_DP || ent->fts_info == FTS_DNR;
+        enum RM_status s = prompt (fts, ent, is_dir, x, PA_REMOVE_DIR,
+                                   &dir_status);
+        if (! (s == RM_OK || s == RM_USER_ACCEPTED))
+          return s;
+        return excise (fts, ent, x, is_dir);
+      }
+
+    case FTS_DC:               /* directory that causes cycles */
+      emit_cycle_warning (ent->fts_path);
+      fts_skip_tree (fts, ent);
+      return RM_ERROR;
+
+    case FTS_ERR:
+      /* Various failures, from opendir to ENOMEM, to failure to "return"
+         to preceding directory, can provoke this.  */
+      error (0, ent->fts_errno, _("traversal failed: %s"),
+             quotef (ent->fts_path));
+      fts_skip_tree (fts, ent);
+      return RM_ERROR;
+
+    default:
+      error (0, 0, _("unexpected failure: fts_info=%d: %s\n"
+                     "please report to %s"),
+             ent->fts_info,
+             quotef (ent->fts_path),
+             PACKAGE_BUGREPORT);
+      abort ();
+    }
+}
+
+/* Remove FILEs, honoring options specified via X.
+   Return RM_OK if successful.  */
+enum RM_status
+rm (char *const *file, struct rm_options const *x)
+{
+  enum RM_status rm_status = RM_OK;
+
+  if (*file)
+    {
+      int bit_flags = (FTS_CWDFD
+                       | FTS_NOSTAT
+                       | FTS_PHYSICAL);
+
+      if (x->one_file_system)
+        bit_flags |= FTS_XDEV;
+
+      FTS *fts = xfts_open (file, bit_flags, nullptr);
+
+      while (true)
+        {
+          FTSENT *ent;
+
+          ent = fts_read (fts);
+          if (ent == nullptr)
+            {
+              if (errno != 0)
+                {
+                  error (0, errno, _("fts_read failed"));
+                  rm_status = RM_ERROR;
+                }
+              break;
+            }
+
+          enum RM_status s = rm_fts (fts, ent, x);
+
+          affirm (VALID_STATUS (s));
+          UPDATE_STATUS (rm_status, s);
+        }
+
+      if (fts_close (fts) != 0)
+        {
+          error (0, errno, _("fts_close failed"));
+          rm_status = RM_ERROR;
+        }
+    }
+
+  return rm_status;
+}
diff --git a/developer/cc/unlink.lib.c b/developer/cc/unlink.lib.c
new file mode 100644 (file)
index 0000000..5418d02
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef IFACE
+#define Unix·IMPLEMENTATION
+#define IFACE
+#endif
+
+#ifndef Unix·IFACE
+#define Unix·IFACE
+
+  int unlink(const char *pathname);
+
+#endif // Unix·IFACE
+
+#ifndef Unix·IMPLEMENTATION
+
+  #define _GNU_SOURCE
+  #include <stdio.h>
+  #include <string.h>
+  #include <unistd.h>
+  #include <libgen.h>
+  #include <errno.h>
+
+  static int is_authored(const char *path) {
+      if (path == NULL) {
+          return 0;
+      }
+
+      // Check if the file itself is authored
+      const char *suffix = "🖉";
+      size_t path_len = strlen(path);
+      size_t suffix_len = strlen(suffix);
+
+      if (path_len >= suffix_len && strcmp(path + path_len - suffix_len, suffix) == 0) {
+          return 1;
+      }
+
+      // Check if the parent directory is authored
+      char *parent = strdup(path);
+      if (!parent) {
+          return 0;
+      }
+      dirname(parent);
+
+      int result = 0;
+      if (strlen(parent) >= suffix_len &&
+          strcmp(parent + strlen(parent) - suffix_len, suffix) == 0) {
+          result = 1;
+      }
+      free(parent);
+      return result;
+  }
+
+  int unlink(const char *pathname) {
+      if (is_authored(pathname)) {
+          fprintf(stderr, "unlink:: authored file not unlinked '%s'.\n", pathname);
+          errno = EPERM; // Operation not permitted
+          return -1;
+      }
+      // Call the original unlink system call
+      int (*original_unlink)(const char *) = dlsym(RTLD_NEXT, "unlink");
+      return original_unlink(pathname);
+  }
+
+#endif
diff --git a/developer/cc/user-stem.cli.c b/developer/cc/user-stem.cli.c
new file mode 100644 (file)
index 0000000..d426be9
--- /dev/null
@@ -0,0 +1,18 @@
+#define IFACE
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+
+int main(){
+  struct passwd *pw = getpwuid(getuid());
+  char *user_stem = strdup(pw->pw_name);
+
+  char *p = user_stem;
+  while(*p && *p != '-') p++;
+  if(*p) *p='\0';
+
+  puts(user_stem);
+  return 0;
+}
diff --git a/developer/cc/user-subu.cli.c b/developer/cc/user-subu.cli.c
new file mode 100644 (file)
index 0000000..90bc630
--- /dev/null
@@ -0,0 +1,18 @@
+#define IFACE
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+
+int main(){
+  struct passwd *pw = getpwuid(getuid());
+  char *user_subu = strdup(pw->pw_name);
+
+  char *p = user_subu;
+  while(*p && *p != '-') p++;
+  if(*p) p++;
+
+  puts(p);
+  return 0;
+}
diff --git a/developer/cc/user.cli.c b/developer/cc/user.cli.c
new file mode 100644 (file)
index 0000000..58ba68d
--- /dev/null
@@ -0,0 +1,12 @@
+#define IFACE
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdio.h>
+
+int main(){
+  struct passwd *pw = getpwuid(getuid());
+  const char *pw_name = pw->pw_name;
+  puts(pw_name);
+  return 0;
+}
diff --git a/developer/cc🖉/home.cli.c b/developer/cc🖉/home.cli.c
deleted file mode 100644 (file)
index d990d96..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#define IFACE
-#include <unistd.h>
-#include <sys/types.h>
-#include <pwd.h>
-#include <string.h>
-#include <stdio.h>
-
-/*
-We return the home directory without a trailing slash.  Otherwise in bash scripts ~/... will
-expand out with two slashes.  Also, if we returned with a trailing slash, then rsync 
-would behave differently with ~ (specifying contents of home instead of home itself).
-
-I am not sure if pw_dir has always returned a trailing slash on the home directory, though with
-the latest upgrade is the first time I am noticing two slashes in transcripts.
-
-It is an error for pw_dir to be an empty string?  I suppose not, but rather it is assumed
-to be the root of the file system?  Perhaps that is why they added the slash, to make
-that clear.
-
-*/
-int main(){
-  struct passwd *pw = getpwuid(getuid());
-  const char *homedir = pw->pw_dir;
-
-  size_t n = strlen(homedir);
-  if( n == 0 ) return 1;
-  while(n > 1){
-    fputc(*homedir ,stdout);
-  --n;
-  ++homedir;
-  };
-  if(*homedir == '/') return 1;
-  fputc(*homedir ,stdout);
-  return 1;
-}
diff --git a/developer/cc🖉/is_authored_fs_obj.c b/developer/cc🖉/is_authored_fs_obj.c
deleted file mode 100644 (file)
index 1c82e9a..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-#include <string.h>
-#include <stdbool.h>
-
-static bool is_authored_fs_obj(const char *path) {
-    if (!path || strlen(path) == 0) {
-        return false;
-    }
-
-    // Check if the last character is the pencil
-    size_t len = strlen(path);
-    return path[len - 1] == '🖉';
-}
-
-
-#include <stdlib.h>
-#include <libgen.h>
-#include <stdbool.h>
-#include <string.h>
-
-static bool is_authored(const char *path) {
-    if (!path || strlen(path) == 0) {
-        return false;
-    }
-
-    // Check the path itself
-    if (is_authored_fs_obj(path)) {
-        return true;
-    }
-
-    // Check each parent directory up to the root
-    char *path_copy = strdup(path);
-    if (!path_copy) {
-        return false; // Memory allocation failure
-    }
-
-    char *parent = path_copy;
-    bool authored = false;
-
-    while (true) {
-        parent = dirname(parent);
-
-        // Check if the current directory is authored
-        if (is_authored_fs_obj(parent)) {
-            authored = true;
-            break;
-        }
-
-        // If we reach the root, stop
-        if (strcmp(parent, "/") == 0) {
-            break;
-        }
-    }
-
-    free(path_copy);
-    return authored;
-}
diff --git a/developer/cc🖉/remove.c b/developer/cc🖉/remove.c
deleted file mode 100644 (file)
index 3ce98f9..0000000
+++ /dev/null
@@ -1,762 +0,0 @@
-#include <config.h>
-#include <string.h>
-#include <stdbool.h>
-
-#include <string.h>
-#include <stdbool.h>
-
-static bool is_authored_fs_obj(const char *path) {
-    if (!path || strlen(path) == 0) {
-        return false;
-    }
-
-    // Check if the last character is the pencil (as a string)
-    const char *suffix = "🖉";
-    size_t len = strlen(path);
-    size_t suffix_len = strlen(suffix);
-
-    if (len < suffix_len) {
-        return false;
-    }
-
-    return strcmp(path + len - suffix_len, suffix) == 0;
-}
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <libgen.h>
-#include <limits.h>
-#include <unistd.h>
-
-static bool is_authored(const char *path) {
-    if (!path || strlen(path) == 0) {
-        fprintf(stderr, "DEBUG: Invalid path provided\n");
-        return false;
-    }
-
-    // Convert to an absolute path
-    char abs_path[PATH_MAX];
-    if (!realpath(path, abs_path)) {
-        fprintf(stderr, "DEBUG: Failed to resolve absolute path for: %s\n", path);
-        return false;
-    }
-
-    fprintf(stderr, "DEBUG: Starting check for path: %s (resolved: %s)\n", path, abs_path);
-
-    // Allocate and copy for safe modifications
-    char *current_path = strdup(abs_path);
-    if (!current_path) {
-        fprintf(stderr, "DEBUG: Memory allocation failed for current_path\n");
-        return false;
-    }
-
-    bool authored = false;
-    int iteration_count = 0;
-
-    while (true) {
-        fprintf(stderr, "DEBUG: Iteration %d, checking path: %s\n", iteration_count, current_path);
-
-        // Check if the current path is authored
-        if (is_authored_fs_obj(current_path)) {
-            fprintf(stderr, "DEBUG: Found authored path: %s\n", current_path);
-            authored = true;
-            break;
-        }
-
-        // Get parent directory
-        char *parent_path = strdup(current_path);
-        if (!parent_path) {
-            fprintf(stderr, "DEBUG: Memory allocation failed for parent_path\n");
-            break;
-        }
-        char *parent = dirname(parent_path);
-
-        // Stop condition: root or no change in path
-        if (strcmp(parent, "/") == 0 || strcmp(parent, current_path) == 0) {
-            fprintf(stderr, "DEBUG: Reached stop condition at parent: %s\n", parent);
-            free(parent_path);
-            break;
-        }
-
-        // Update current_path for the next iteration
-        free(current_path);
-        current_path = strdup(parent);
-        if (!current_path) {
-            fprintf(stderr, "DEBUG: Memory allocation failed while updating current_path\n");
-            free(parent_path);
-            break;
-        }
-
-        free(parent_path);
-        iteration_count++;
-
-        // Failsafe for infinite loops
-        if (iteration_count > 100) {
-            fprintf(stderr, "DEBUG: Too many iterations, exiting to avoid infinite loop\n");
-            break;
-        }
-    }
-
-    free(current_path);
-    return authored;
-}
-
-
-/* remove.c -- core functions for removing files and directories
-   Copyright (C) 1988-2024 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
-
-/* Extracted from rm.c, librarified, then rewritten twice by Jim Meyering.  */
-
-#include <config.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-#include "system.h"
-#include "assure.h"
-#include "file-type.h"
-#include "filenamecat.h"
-#include "ignore-value.h"
-#include "remove.h"
-#include "root-dev-ino.h"
-#include "stat-time.h"
-#include "write-any-file.h"
-#include "xfts.h"
-#include "yesno.h"
-
-/* The prompt function may be called twice for a given directory.
-   The first time, we ask whether to descend into it, and the
-   second time, we ask whether to remove it.  */
-enum Prompt_action
-  {
-    PA_DESCEND_INTO_DIR = 2,
-    PA_REMOVE_DIR
-  };
-
-/* D_TYPE(D) is the type of directory entry D if known, DT_UNKNOWN
-   otherwise.  */
-#if ! HAVE_STRUCT_DIRENT_D_TYPE
-/* Any int values will do here, so long as they're distinct.
-   Undef any existing macros out of the way.  */
-# undef DT_UNKNOWN
-# undef DT_DIR
-# undef DT_LNK
-# define DT_UNKNOWN 0
-# define DT_DIR 1
-# define DT_LNK 2
-#endif
-
-/* Like fstatat, but cache on POSIX-compatible systems.  */
-static int
-cache_fstatat (int fd, char const *file, struct stat *st, int flag)
-{
-#if HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
-  /* If ST->st_atim.tv_nsec is -1, the status has not been gotten yet.
-     If less than -1, fstatat failed with errno == ST->st_ino.
-     Otherwise, the status has already been gotten, so return 0.  */
-  if (0 <= st->st_atim.tv_nsec)
-    return 0;
-  if (st->st_atim.tv_nsec == -1)
-    {
-      if (fstatat (fd, file, st, flag) == 0)
-        return 0;
-      st->st_atim.tv_nsec = -2;
-      st->st_ino = errno;
-    }
-  errno = st->st_ino;
-  return -1;
-#else
-  return fstatat (fd, file, st, flag);
-#endif
-}
-
-/* Initialize a fstatat cache *ST.  Return ST for convenience.  */
-static inline struct stat *
-cache_stat_init (struct stat *st)
-{
-#if HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
-  st->st_atim.tv_nsec = -1;
-#endif
-  return st;
-}
-
-/* Return 1 if FILE is an unwritable non-symlink,
-   0 if it is writable or some other type of file,
-   -1 and set errno if there is some problem in determining the answer.
-   Set *BUF to the file status.  */
-static int
-write_protected_non_symlink (int fd_cwd,
-                             char const *file,
-                             struct stat *buf)
-{
-  if (can_write_any_file ())
-    return 0;
-  if (cache_fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0)
-    return -1;
-  if (S_ISLNK (buf->st_mode))
-    return 0;
-  /* Here, we know FILE is not a symbolic link.  */
-
-  /* In order to be reentrant -- i.e., to avoid changing the working
-     directory, and at the same time to be able to deal with alternate
-     access control mechanisms (ACLs, xattr-style attributes) and
-     arbitrarily deep trees -- we need a function like eaccessat, i.e.,
-     like Solaris' eaccess, but fd-relative, in the spirit of openat.  */
-
-  /* In the absence of a native eaccessat function, here are some of
-     the implementation choices [#4 and #5 were suggested by Paul Eggert]:
-     1) call openat with O_WRONLY|O_NOCTTY
-        Disadvantage: may create the file and doesn't work for directory,
-        may mistakenly report 'unwritable' for EROFS or ACLs even though
-        perm bits say the file is writable.
-
-     2) fake eaccessat (save_cwd, fchdir, call euidaccess, restore_cwd)
-        Disadvantage: changes working directory (not reentrant) and can't
-        work if save_cwd fails.
-
-     3) if (euidaccess (full_name, W_OK) == 0)
-        Disadvantage: doesn't work if full_name is too long.
-        Inefficient for very deep trees (O(Depth^2)).
-
-     4) If the full pathname is sufficiently short (say, less than
-        PATH_MAX or 8192 bytes, whichever is shorter):
-        use method (3) (i.e., euidaccess (full_name, W_OK));
-        Otherwise: vfork, fchdir in the child, run euidaccess in the
-        child, then the child exits with a status that tells the parent
-        whether euidaccess succeeded.
-
-        This avoids the O(N**2) algorithm of method (3), and it also avoids
-        the failure-due-to-too-long-file-names of method (3), but it's fast
-        in the normal shallow case.  It also avoids the lack-of-reentrancy
-        and the save_cwd problems.
-        Disadvantage; it uses a process slot for very-long file names,
-        and would be very slow for hierarchies with many such files.
-
-     5) If the full file name is sufficiently short (say, less than
-        PATH_MAX or 8192 bytes, whichever is shorter):
-        use method (3) (i.e., euidaccess (full_name, W_OK));
-        Otherwise: look just at the file bits.  Perhaps issue a warning
-        the first time this occurs.
-
-        This is like (4), except for the "Otherwise" case where it isn't as
-        "perfect" as (4) but is considerably faster.  It conforms to current
-        POSIX, and is uniformly better than what Solaris and FreeBSD do (they
-        mess up with long file names). */
-
-  {
-    if (faccessat (fd_cwd, file, W_OK, AT_EACCESS) == 0)
-      return 0;
-
-    return errno == EACCES ? 1 : -1;
-  }
-}
-
-/* Return the status of the directory identified by FTS and ENT.
-   This is -1 if the directory is empty, 0 if it is nonempty,
-   and a positive error number if there was trouble determining the status,
-   e.g., it is not a directory, or permissions problems, or I/O errors.
-   Use *DIR_STATUS as a cache for the status.  */
-static int
-get_dir_status (FTS const *fts, FTSENT const *ent, int *dir_status)
-{
-  if (*dir_status == DS_UNKNOWN)
-    *dir_status = directory_status (fts->fts_cwd_fd, ent->fts_accpath);
-  return *dir_status;
-}
-
-/* Prompt whether to remove FILENAME, if required via a combination of
-   the options specified by X and/or file attributes.  If the file may
-   be removed, return RM_OK or RM_USER_ACCEPTED, the latter if the user
-   was prompted and accepted.  If the user declines to remove the file,
-   return RM_USER_DECLINED.  If not ignoring missing files and we
-   cannot lstat FILENAME, then return RM_ERROR.
-
-   IS_DIR is true if ENT designates a directory, false otherwise.
-
-   Depending on MODE, ask whether to 'descend into' or to 'remove' the
-   directory FILENAME.  MODE is ignored when FILENAME is not a directory.
-   Use and update *DIR_STATUS as needed, via the conventions of
-   get_dir_status.  */
-static enum RM_status
-prompt (FTS const *fts, FTSENT const *ent, bool is_dir,
-        struct rm_options const *x, enum Prompt_action mode,
-        int *dir_status)
-{
-  int fd_cwd = fts->fts_cwd_fd;
-  char const *full_name = ent->fts_path;
-  char const *filename = ent->fts_accpath;
-  struct stat st;
-  struct stat *sbuf = &st;
-  cache_stat_init (sbuf);
-
-  int dirent_type = is_dir ? DT_DIR : DT_UNKNOWN;
-  int write_protected = 0;
-
-  /* When nonzero, this indicates that we failed to remove a child entry,
-     either because the user declined an interactive prompt, or due to
-     some other failure, like permissions.  */
-  if (ent->fts_number)
-    return RM_USER_DECLINED;
-
-  if (x->interactive == RMI_NEVER)
-    return RM_OK;
-
-  int wp_errno = 0;
-  if (!x->ignore_missing_files
-      && (x->interactive == RMI_ALWAYS || x->stdin_tty)
-      && dirent_type != DT_LNK)
-    {
-      write_protected = write_protected_non_symlink (fd_cwd, filename, sbuf);
-      wp_errno = errno;
-    }
-
-  if (write_protected || x->interactive == RMI_ALWAYS)
-    {
-      if (0 <= write_protected && dirent_type == DT_UNKNOWN)
-        {
-          if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) == 0)
-            {
-              if (S_ISLNK (sbuf->st_mode))
-                dirent_type = DT_LNK;
-              else if (S_ISDIR (sbuf->st_mode))
-                dirent_type = DT_DIR;
-              /* Otherwise it doesn't matter, so leave it DT_UNKNOWN.  */
-            }
-          else
-            {
-              /* This happens, e.g., with 'rm '''.  */
-              write_protected = -1;
-              wp_errno = errno;
-            }
-        }
-
-      if (0 <= write_protected)
-        switch (dirent_type)
-          {
-          case DT_LNK:
-            /* Using permissions doesn't make sense for symlinks.  */
-            if (x->interactive != RMI_ALWAYS)
-              return RM_OK;
-            break;
-
-          case DT_DIR:
-             /* Unless we're either deleting directories or deleting
-                recursively, we want to raise an EISDIR error rather than
-                prompting the user  */
-            if ( ! (x->recursive
-                    || (x->remove_empty_directories
-                        && get_dir_status (fts, ent, dir_status) != 0)))
-              {
-                write_protected = -1;
-                wp_errno = *dir_status <= 0 ? EISDIR : *dir_status;
-              }
-            break;
-          }
-
-      char const *quoted_name = quoteaf (full_name);
-
-      if (write_protected < 0)
-        {
-          error (0, wp_errno, _("cannot remove %s"), quoted_name);
-          return RM_ERROR;
-        }
-
-      /* Issue the prompt.  */
-      if (dirent_type == DT_DIR
-          && mode == PA_DESCEND_INTO_DIR
-          && get_dir_status (fts, ent, dir_status) == DS_NONEMPTY)
-        fprintf (stderr,
-                 (write_protected
-                  ? _("%s: descend into write-protected directory %s? ")
-                  : _("%s: descend into directory %s? ")),
-                 program_name, quoted_name);
-      else if (0 < *dir_status)
-        {
-          if ( ! (x->remove_empty_directories && *dir_status == EACCES))
-            {
-              error (0, *dir_status, _("cannot remove %s"), quoted_name);
-              return RM_ERROR;
-            }
-
-          /* The following code can lead to a successful deletion only with
-             the --dir (-d) option (remove_empty_directories) and an empty
-             inaccessible directory. In the first prompt call for a directory,
-             we'd normally ask whether to descend into it, but in this case
-             (it's inaccessible), that is not possible, so don't prompt.  */
-          if (mode == PA_DESCEND_INTO_DIR)
-            return RM_OK;
-
-          fprintf (stderr,
-               _("%s: attempt removal of inaccessible directory %s? "),
-                   program_name, quoted_name);
-        }
-      else
-        {
-          if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0)
-            {
-              error (0, errno, _("cannot remove %s"), quoted_name);
-              return RM_ERROR;
-            }
-
-          fprintf (stderr,
-                   (write_protected
-                    /* TRANSLATORS: In the next two strings the second %s is
-                       replaced by the type of the file.  To avoid grammatical
-                       problems, it may be more convenient to translate these
-                       strings instead as: "%1$s: %3$s is write-protected and
-                       is of type '%2$s' -- remove it? ".  */
-                    ? _("%s: remove write-protected %s %s? ")
-                    : _("%s: remove %s %s? ")),
-                   program_name, file_type (sbuf), quoted_name);
-        }
-
-      return yesno () ? RM_USER_ACCEPTED : RM_USER_DECLINED;
-    }
-  return RM_OK;
-}
-
-/* When a function like unlink, rmdir, or fstatat fails with an errno
-   value of ERRNUM, return true if the specified file system object
-   is guaranteed not to exist;  otherwise, return false.  */
-static inline bool
-nonexistent_file_errno (int errnum)
-{
-  /* Do not include ELOOP here, since the specified file may indeed
-     exist, but be (in)accessible only via too long a symlink chain.
-     Likewise for ENAMETOOLONG, since rm -f ./././.../foo may fail
-     if the "..." part expands to a long enough sequence of "./"s,
-     even though ./foo does indeed exist.
-
-     Another case to consider is when a particular name is invalid for
-     a given file system.  In 2011, smbfs returns EINVAL, but the next
-     revision of POSIX will require EILSEQ for that situation:
-     https://austingroupbugs.net/view.php?id=293
-  */
-
-  switch (errnum)
-    {
-    case EILSEQ:
-    case EINVAL:
-    case ENOENT:
-    case ENOTDIR:
-      return true;
-    default:
-      return false;
-    }
-}
-
-/* Encapsulate the test for whether the errno value, ERRNUM, is ignorable.  */
-static inline bool
-ignorable_missing (struct rm_options const *x, int errnum)
-{
-  return x->ignore_missing_files && nonexistent_file_errno (errnum);
-}
-
-/* Tell fts not to traverse into the hierarchy at ENT.  */
-static void
-fts_skip_tree (FTS *fts, FTSENT *ent)
-{
-  fts_set (fts, ent, FTS_SKIP);
-  /* Ensure that we do not process ENT a second time.  */
-  ignore_value (fts_read (fts));
-}
-
-/* Upon unlink failure, or when the user declines to remove ENT, mark
-   each of its ancestor directories, so that we know not to prompt for
-   its removal.  */
-static void
-mark_ancestor_dirs (FTSENT *ent)
-{
-  FTSENT *p;
-  for (p = ent->fts_parent; FTS_ROOTLEVEL <= p->fts_level; p = p->fts_parent)
-    {
-      if (p->fts_number)
-        break;
-      p->fts_number = 1;
-    }
-}
-
-/* Remove the file system object specified by ENT.  IS_DIR specifies
-   whether it is expected to be a directory or non-directory.
-   Return RM_OK upon success, else RM_ERROR.  */
-static enum RM_status
-excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir)
-{
-  int flag = is_dir ? AT_REMOVEDIR : 0;
-  if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0)
-    {
-      if (x->verbose)
-        {
-          printf ((is_dir
-                   ? _("removed directory %s\n")
-                   : _("removed %s\n")), quoteaf (ent->fts_path));
-        }
-      return RM_OK;
-    }
-
-  /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for
-     nonexistent files.  When the file is indeed missing, map that to ENOENT,
-     so that rm -f ignores it, as required.  Even without -f, this is useful
-     because it makes rm print the more precise diagnostic.  */
-  if (errno == EROFS)
-    {
-      struct stat st;
-      if ( ! (fstatat (fts->fts_cwd_fd, ent->fts_accpath, &st,
-                       AT_SYMLINK_NOFOLLOW)
-              && errno == ENOENT))
-        errno = EROFS;
-    }
-
-  if (ignorable_missing (x, errno))
-    return RM_OK;
-
-  /* When failing to rmdir an unreadable directory, we see errno values
-     like EISDIR or ENOTDIR (or, on Solaris 10, EEXIST), but they would be
-     meaningless in a diagnostic.  When that happens, use the earlier, more
-     descriptive errno value.  */
-  if (ent->fts_info == FTS_DNR
-      && (errno == ENOTEMPTY || errno == EISDIR || errno == ENOTDIR
-          || errno == EEXIST)
-      && ent->fts_errno != 0)
-    errno = ent->fts_errno;
-  error (0, errno, _("cannot remove %s"), quoteaf (ent->fts_path));
-  mark_ancestor_dirs (ent);
-  return RM_ERROR;
-}
-
-/* This function is called once for every file system object that fts
-   encounters.  fts performs a depth-first traversal.
-   A directory is usually processed twice, first with fts_info == FTS_D,
-   and later, after all of its entries have been processed, with FTS_DP.
-   Return RM_ERROR upon error, RM_USER_DECLINED for a negative response
-   to an interactive prompt, and otherwise, RM_OK.  */
-static enum RM_status
-rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x)
-{
-  int dir_status = DS_UNKNOWN;
-
-if (is_authored(ent->fts_path)) {
-    fprintf(stderr, "rm: cannot remove authored %s '%s'\n",
-            (ent->fts_info == FTS_D || ent->fts_info == FTS_DP) ? "directory" : "file",
-            ent->fts_path);
-    return RM_ERROR; // Skip authored files
-}
-
-
-  switch (ent->fts_info)
-    {
-    case FTS_D:                        /* preorder directory */
-      if (! x->recursive
-          && !(x->remove_empty_directories
-               && get_dir_status (fts, ent, &dir_status) != 0))
-        {
-          /* This is the first (pre-order) encounter with a directory
-             that we cannot delete.
-             Not recursive, and it's not an empty directory (if we're removing
-             them) so arrange to skip contents.  */
-          int err = x->remove_empty_directories ? ENOTEMPTY : EISDIR;
-          error (0, err, _("cannot remove %s"), quoteaf (ent->fts_path));
-          mark_ancestor_dirs (ent);
-          fts_skip_tree (fts, ent);
-          return RM_ERROR;
-        }
-
-      /* Perform checks that can apply only for command-line arguments.  */
-      if (ent->fts_level == FTS_ROOTLEVEL)
-        {
-          /* POSIX says:
-             If the basename of a command line argument is "." or "..",
-             diagnose it and do nothing more with that argument.  */
-          if (dot_or_dotdot (last_component (ent->fts_accpath)))
-            {
-              error (0, 0,
-                     _("refusing to remove %s or %s directory: skipping %s"),
-                     quoteaf_n (0, "."), quoteaf_n (1, ".."),
-                     quoteaf_n (2, ent->fts_path));
-              fts_skip_tree (fts, ent);
-              return RM_ERROR;
-            }
-
-          /* POSIX also says:
-             If a command line argument resolves to "/" (and --preserve-root
-             is in effect -- default) diagnose and skip it.  */
-          if (ROOT_DEV_INO_CHECK (x->root_dev_ino, ent->fts_statp))
-            {
-              ROOT_DEV_INO_WARN (ent->fts_path);
-              fts_skip_tree (fts, ent);
-              return RM_ERROR;
-            }
-
-          /* If a command line argument is a mount point and
-             --preserve-root=all is in effect, diagnose and skip it.
-             This doesn't handle "/", but that's handled above.  */
-          if (x->preserve_all_root)
-            {
-              bool failed = false;
-              char *parent = file_name_concat (ent->fts_accpath, "..", nullptr);
-              struct stat statbuf;
-
-              if (!parent || lstat (parent, &statbuf))
-                {
-                  error (0, 0,
-                         _("failed to stat %s: skipping %s"),
-                         quoteaf_n (0, parent),
-                         quoteaf_n (1, ent->fts_accpath));
-                  failed = true;
-                }
-
-              free (parent);
-
-              if (failed || fts->fts_dev != statbuf.st_dev)
-                {
-                  if (! failed)
-                    {
-                      error (0, 0,
-                             _("skipping %s, since it's on a different device"),
-                             quoteaf (ent->fts_path));
-                      error (0, 0, _("and --preserve-root=all is in effect"));
-                    }
-                  fts_skip_tree (fts, ent);
-                  return RM_ERROR;
-                }
-            }
-        }
-
-      {
-        enum RM_status s = prompt (fts, ent, true /*is_dir*/, x,
-                                   PA_DESCEND_INTO_DIR, &dir_status);
-
-        if (s == RM_USER_ACCEPTED && dir_status == DS_EMPTY)
-          {
-            /* When we know (from prompt when in interactive mode)
-               that this is an empty directory, don't prompt twice.  */
-            s = excise (fts, ent, x, true);
-            if (s == RM_OK)
-              fts_skip_tree (fts, ent);
-          }
-
-        if (! (s == RM_OK || s == RM_USER_ACCEPTED))
-          {
-            mark_ancestor_dirs (ent);
-            fts_skip_tree (fts, ent);
-          }
-
-        return s;
-      }
-
-    case FTS_F:                        /* regular file */
-    case FTS_NS:               /* stat(2) failed */
-    case FTS_SL:               /* symbolic link */
-    case FTS_SLNONE:           /* symbolic link without target */
-    case FTS_DP:               /* postorder directory */
-    case FTS_DNR:              /* unreadable directory */
-    case FTS_NSOK:             /* e.g., dangling symlink */
-    case FTS_DEFAULT:          /* none of the above */
-      {
-        /* With --one-file-system, do not attempt to remove a mount point.
-           fts' FTS_XDEV ensures that we don't process any entries under
-           the mount point.  */
-        if (ent->fts_info == FTS_DP
-            && x->one_file_system
-            && FTS_ROOTLEVEL < ent->fts_level
-            && ent->fts_statp->st_dev != fts->fts_dev)
-          {
-            mark_ancestor_dirs (ent);
-            error (0, 0, _("skipping %s, since it's on a different device"),
-                   quoteaf (ent->fts_path));
-            return RM_ERROR;
-          }
-
-        bool is_dir = ent->fts_info == FTS_DP || ent->fts_info == FTS_DNR;
-        enum RM_status s = prompt (fts, ent, is_dir, x, PA_REMOVE_DIR,
-                                   &dir_status);
-        if (! (s == RM_OK || s == RM_USER_ACCEPTED))
-          return s;
-        return excise (fts, ent, x, is_dir);
-      }
-
-    case FTS_DC:               /* directory that causes cycles */
-      emit_cycle_warning (ent->fts_path);
-      fts_skip_tree (fts, ent);
-      return RM_ERROR;
-
-    case FTS_ERR:
-      /* Various failures, from opendir to ENOMEM, to failure to "return"
-         to preceding directory, can provoke this.  */
-      error (0, ent->fts_errno, _("traversal failed: %s"),
-             quotef (ent->fts_path));
-      fts_skip_tree (fts, ent);
-      return RM_ERROR;
-
-    default:
-      error (0, 0, _("unexpected failure: fts_info=%d: %s\n"
-                     "please report to %s"),
-             ent->fts_info,
-             quotef (ent->fts_path),
-             PACKAGE_BUGREPORT);
-      abort ();
-    }
-}
-
-/* Remove FILEs, honoring options specified via X.
-   Return RM_OK if successful.  */
-enum RM_status
-rm (char *const *file, struct rm_options const *x)
-{
-  enum RM_status rm_status = RM_OK;
-
-  if (*file)
-    {
-      int bit_flags = (FTS_CWDFD
-                       | FTS_NOSTAT
-                       | FTS_PHYSICAL);
-
-      if (x->one_file_system)
-        bit_flags |= FTS_XDEV;
-
-      FTS *fts = xfts_open (file, bit_flags, nullptr);
-
-      while (true)
-        {
-          FTSENT *ent;
-
-          ent = fts_read (fts);
-          if (ent == nullptr)
-            {
-              if (errno != 0)
-                {
-                  error (0, errno, _("fts_read failed"));
-                  rm_status = RM_ERROR;
-                }
-              break;
-            }
-
-          enum RM_status s = rm_fts (fts, ent, x);
-
-          affirm (VALID_STATUS (s));
-          UPDATE_STATUS (rm_status, s);
-        }
-
-      if (fts_close (fts) != 0)
-        {
-          error (0, errno, _("fts_close failed"));
-          rm_status = RM_ERROR;
-        }
-    }
-
-  return rm_status;
-}
diff --git a/developer/cc🖉/unlink.lib.c b/developer/cc🖉/unlink.lib.c
deleted file mode 100644 (file)
index 5418d02..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef IFACE
-#define Unix·IMPLEMENTATION
-#define IFACE
-#endif
-
-#ifndef Unix·IFACE
-#define Unix·IFACE
-
-  int unlink(const char *pathname);
-
-#endif // Unix·IFACE
-
-#ifndef Unix·IMPLEMENTATION
-
-  #define _GNU_SOURCE
-  #include <stdio.h>
-  #include <string.h>
-  #include <unistd.h>
-  #include <libgen.h>
-  #include <errno.h>
-
-  static int is_authored(const char *path) {
-      if (path == NULL) {
-          return 0;
-      }
-
-      // Check if the file itself is authored
-      const char *suffix = "🖉";
-      size_t path_len = strlen(path);
-      size_t suffix_len = strlen(suffix);
-
-      if (path_len >= suffix_len && strcmp(path + path_len - suffix_len, suffix) == 0) {
-          return 1;
-      }
-
-      // Check if the parent directory is authored
-      char *parent = strdup(path);
-      if (!parent) {
-          return 0;
-      }
-      dirname(parent);
-
-      int result = 0;
-      if (strlen(parent) >= suffix_len &&
-          strcmp(parent + strlen(parent) - suffix_len, suffix) == 0) {
-          result = 1;
-      }
-      free(parent);
-      return result;
-  }
-
-  int unlink(const char *pathname) {
-      if (is_authored(pathname)) {
-          fprintf(stderr, "unlink:: authored file not unlinked '%s'.\n", pathname);
-          errno = EPERM; // Operation not permitted
-          return -1;
-      }
-      // Call the original unlink system call
-      int (*original_unlink)(const char *) = dlsym(RTLD_NEXT, "unlink");
-      return original_unlink(pathname);
-  }
-
-#endif
diff --git a/developer/cc🖉/user-stem.cli.c b/developer/cc🖉/user-stem.cli.c
deleted file mode 100644 (file)
index d426be9..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#define IFACE
-#include <unistd.h>
-#include <sys/types.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <string.h>
-
-int main(){
-  struct passwd *pw = getpwuid(getuid());
-  char *user_stem = strdup(pw->pw_name);
-
-  char *p = user_stem;
-  while(*p && *p != '-') p++;
-  if(*p) *p='\0';
-
-  puts(user_stem);
-  return 0;
-}
diff --git a/developer/cc🖉/user-subu.cli.c b/developer/cc🖉/user-subu.cli.c
deleted file mode 100644 (file)
index 90bc630..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#define IFACE
-#include <unistd.h>
-#include <sys/types.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <string.h>
-
-int main(){
-  struct passwd *pw = getpwuid(getuid());
-  char *user_subu = strdup(pw->pw_name);
-
-  char *p = user_subu;
-  while(*p && *p != '-') p++;
-  if(*p) p++;
-
-  puts(p);
-  return 0;
-}
diff --git a/developer/cc🖉/user.cli.c b/developer/cc🖉/user.cli.c
deleted file mode 100644 (file)
index 58ba68d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#define IFACE
-#include <unistd.h>
-#include <sys/types.h>
-#include <pwd.h>
-#include <stdio.h>
-
-int main(){
-  struct passwd *pw = getpwuid(getuid());
-  const char *pw_name = pw->pw_name;
-  puts(pw_name);
-  return 0;
-}
diff --git a/developer/emacs/emacs_wrap.txt b/developer/emacs/emacs_wrap.txt
new file mode 100644 (file)
index 0000000..398795f
--- /dev/null
@@ -0,0 +1,9 @@
+
+M-x package-install RET adaptive-wrap RET
+
+(visual-line-mode 1)
+(adaptive-wrap-prefix-mode 1)
+
+# using visual-wrap-column-mode 
+(visual-wrap-column-mode 1)
+(setq visual-wrap-column 80)  ;; Wrap at 80 characters
diff --git a/developer/emacs/for_dot_emacs.txt b/developer/emacs/for_dot_emacs.txt
new file mode 100644 (file)
index 0000000..7e74fd8
--- /dev/null
@@ -0,0 +1,10 @@
+;; this is a text file so that it won't be loaded, ironically by the very code described here.
+
+(let 
+  (
+    (directory "~/RT-project-share/release/emacs/")
+    )
+  (when (file-directory-p directory)
+    (dolist (file (directory-files directory t "\\.el$"))
+      (load file)
+      )))
diff --git a/developer/emacs/jdbx.el b/developer/emacs/jdbx.el
new file mode 100644 (file)
index 0000000..864c6ef
--- /dev/null
@@ -0,0 +1,51 @@
+; The first time Emacs  encounters a link to a source file, Emacs asks if it should follow it.
+; This might suppress that initial question and follow the link.
+; (setq find-file-visit-truename t)
+
+(defun jdbx ()
+  "Set gud-jdb-sourcepath from the environment and run jdb with the correct source path."
+  (interactive)
+  (let* 
+    (
+      (sourcepath (getenv "SOURCEPATH"))
+      )
+    (if 
+      sourcepath
+      (setq gud-jdb-sourcepath (split-string sourcepath ":" t))
+      (message "Warning: SOURCEPATH is not set. `jdb` will run without source path information.")
+      )
+    (let 
+      (
+        (class-name (read-string "Enter the class to debug: " "Test_Util"))
+        (sourcepath-arg 
+          (if 
+            sourcepath
+            (concat "-sourcepath" (mapconcat 'identity gud-jdb-sourcepath ":"))
+            ""
+            ))
+        )
+      (jdb (concat "jdb " sourcepath-arg " " class-name))
+      )))
+
+(defun monitor-jdb-sourcepath (output)
+  "Monitor the jdb output for `sourcepath ARG` commands and update `gud-jdb-sourcepath` with each path in ARG."
+  (when 
+    (string-match "sourcepath \\(.+\\)" output)
+    (let* 
+      (
+        (new-paths (match-string 1 output))
+        (paths-list (split-string new-paths ":" t))
+        )
+      ;; Add each path in paths-list to gud-jdb-sourcepath if not already present
+      (dolist 
+        (path paths-list)
+        (unless 
+          (member path gud-jdb-sourcepath)
+          (setq gud-jdb-sourcepath (append gud-jdb-sourcepath (list path)))
+          )
+        )
+      (message "Updated gud-jdb-sourcepath: %s" gud-jdb-sourcepath)))
+  output
+  )
+
+(add-hook 'gud-filter-functions 'monitor-jdb-sourcepath)
diff --git a/developer/emacs🖉/emacs_wrap.txt b/developer/emacs🖉/emacs_wrap.txt
deleted file mode 100644 (file)
index 398795f..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-
-M-x package-install RET adaptive-wrap RET
-
-(visual-line-mode 1)
-(adaptive-wrap-prefix-mode 1)
-
-# using visual-wrap-column-mode 
-(visual-wrap-column-mode 1)
-(setq visual-wrap-column 80)  ;; Wrap at 80 characters
diff --git a/developer/emacs🖉/for_dot_emacs.txt b/developer/emacs🖉/for_dot_emacs.txt
deleted file mode 100644 (file)
index 7e74fd8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-;; this is a text file so that it won't be loaded, ironically by the very code described here.
-
-(let 
-  (
-    (directory "~/RT-project-share/release/emacs/")
-    )
-  (when (file-directory-p directory)
-    (dolist (file (directory-files directory t "\\.el$"))
-      (load file)
-      )))
diff --git a/developer/emacs🖉/jdbx.el b/developer/emacs🖉/jdbx.el
deleted file mode 100644 (file)
index 864c6ef..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-; The first time Emacs  encounters a link to a source file, Emacs asks if it should follow it.
-; This might suppress that initial question and follow the link.
-; (setq find-file-visit-truename t)
-
-(defun jdbx ()
-  "Set gud-jdb-sourcepath from the environment and run jdb with the correct source path."
-  (interactive)
-  (let* 
-    (
-      (sourcepath (getenv "SOURCEPATH"))
-      )
-    (if 
-      sourcepath
-      (setq gud-jdb-sourcepath (split-string sourcepath ":" t))
-      (message "Warning: SOURCEPATH is not set. `jdb` will run without source path information.")
-      )
-    (let 
-      (
-        (class-name (read-string "Enter the class to debug: " "Test_Util"))
-        (sourcepath-arg 
-          (if 
-            sourcepath
-            (concat "-sourcepath" (mapconcat 'identity gud-jdb-sourcepath ":"))
-            ""
-            ))
-        )
-      (jdb (concat "jdb " sourcepath-arg " " class-name))
-      )))
-
-(defun monitor-jdb-sourcepath (output)
-  "Monitor the jdb output for `sourcepath ARG` commands and update `gud-jdb-sourcepath` with each path in ARG."
-  (when 
-    (string-match "sourcepath \\(.+\\)" output)
-    (let* 
-      (
-        (new-paths (match-string 1 output))
-        (paths-list (split-string new-paths ":" t))
-        )
-      ;; Add each path in paths-list to gud-jdb-sourcepath if not already present
-      (dolist 
-        (path paths-list)
-        (unless 
-          (member path gud-jdb-sourcepath)
-          (setq gud-jdb-sourcepath (append gud-jdb-sourcepath (list path)))
-          )
-        )
-      (message "Updated gud-jdb-sourcepath: %s" gud-jdb-sourcepath)))
-  output
-  )
-
-(add-hook 'gud-filter-functions 'monitor-jdb-sourcepath)
diff --git a/developer/make/RT_0.h b/developer/make/RT_0.h
new file mode 100644 (file)
index 0000000..e102a5c
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef RT·ENVIRONMENT_H
+#define RT·ENVIRONMENT_H
+  #include <stdint.h>
+  #include <stdbool.h>
+
+  typedef unsigned int uint;
+
+  #define Local static
+  #define Free(pt) free(pt); (pt) = NULL;
+
+#endif
diff --git a/developer/make/environment_RT_0 b/developer/make/environment_RT_0
new file mode 100644 (file)
index 0000000..c17b478
--- /dev/null
@@ -0,0 +1,24 @@
+# makefile environment variable defaults.
+#  cc is the name of the C compiler
+#  <name>.c is C source code.
+
+SHELL=/bin/bash
+
+#ECHO= echo -e
+#ECHO= echo
+ECHO := printf "%b\n"
+
+
+# sources found in these subdirectories:
+SRCDIR_List=cc cc🖉
+
+LIBDIR=scratchpad
+EXECDIR=machine
+TMPDIR=scratchpad
+
+DEPFILE=$(TMPDIR)/makefile-cc.deps
+LIBFILE=$(TMPDIR)/lib.a
+
+C=gcc
+CFLAGS=-std=gnu11 -Wall -Wextra -Wpedantic -finput-charset=UTF-8
+LINKFLAGS=-L$(LIBDIR) -L/lib64 -L/lib
diff --git a/developer/make/targets_developer b/developer/make/targets_developer
new file mode 100644 (file)
index 0000000..a8ef237
--- /dev/null
@@ -0,0 +1,118 @@
+.SUFFIXES:
+
+#--------------------------------------------------------------------------------
+# files have two suffixes by convention, e.g.: X.lib.c or Y.cli.c 
+#
+
+# bail early if there is no compiler
+ifeq ($(C),)
+  $(error No C compiler specified.)
+endif
+
+# keep only the source directories that are in the file system
+SRCDIR_List := $(wildcard $(SRCDIR_List))
+
+# bail early if the SRCDIR_list is empty
+ifeq ($(SRCDIR_List),)
+  $(error source directory found so nothing to do)
+endif
+
+# duplicate source file names in different directories will cause
+# problems with this makefile
+
+C_SOURCE_LIB := $(foreach dir, $(SRCDIR_List), $(wildcard $(dir)/*.lib.c))
+C_SOURCE_EXEC := $(foreach dir, $(SRCDIR_List), $(wildcard $(dir)/*.cli.c))
+
+#remove the suffix to get base name
+C_BASE_LIB=  $(sort $(patsubst %.lib.c,  %, $(notdir $(C_SOURCE_LIB))))
+C_BASE_EXEC=  $(sort $(patsubst %.cli.c,  %, $(notdir $(C_SOURCE_EXEC))))
+
+# two sets of object files, one for the lib, and one for the command line interface progs
+OBJECT_LIB= $(patsubst %, $(TMPDIR)/%.lib.o, $(C_BASE_LIB))
+OBJECT_EXEC= $(patsubst %, $(TMPDIR)/%.cli.o, $(C_BASE_EXEC))
+
+# executables are made from EXEC sources
+EXEC= $(patsubst %, $(EXECDIR)/%, $(C_BASE_EXEC))
+
+# the new C programming style gated sections in source instead of header filesheader
+INCFLAG_List := $(foreach dir, $(SRCDIR_List), -I $(dir))
+CFLAGS += $(INCFLAG_List)
+
+#--------------------------------------------------------------------------------
+# targets
+
+.PHONY: all
+all: usage
+
+.PHONY: usage
+usage:
+       @echo example usage: make clean
+       @echo example usage: make dependency library cli
+       @echo example usage: make dependency
+       @echo example usage: make library
+       @echo example usage: make cli
+
+.PHONY: version
+version:
+       @echo makefile version 7.1
+       if [ ! -z "$(C)" ]; then $(C) -v; fi
+       /bin/make -v
+
+.PHONY: information
+information:
+       @printf "· → Unicode middle dot — visible: [%b]\n" "·"
+       @echo "SRCDIR_List: " $(SRCDIR_List)
+       @echo "C_SOURCE_LIB: " $(C_SOURCE_LIB)
+       @echo "C_SOURCE_EXEC: " $(C_SOURCE_EXEC)
+       @echo "C_BASE_LIB: " $(C_BASE_LIB)
+       @echo "C_BASE_EXEC: " $(C_BASE_EXEC)
+       @echo "OBJECT_LIB: " $(OBJECT_LIB)
+       @echo "OBJECT_EXEC: " $(OBJECT_EXEC)
+       @echo "EXEC: " $(EXEC)
+       @echo "INCFLAG_List: " $(INCFLAG_List)
+
+
+.PHONY: dependency
+dependency: $(DEPFILE)
+
+$(DEPFILE): $(C_SOURCE_LIB) $(C_SOURCE_EXEC)
+       @rm -f $(DEPFILE)
+       $(C) $(CFLAGS) -MM  $(C_SOURCE_LIB) $(C_SOURCE_EXEC) \
+         | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
+       echo "deps for C linking";\
+        # build library:\
+       for i in $(C_BASE_EXEC); do\
+         $(ECHO) >> $(DEPFILE);\
+         $(ECHO) "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o $(LIBFILE)" >> $(DEPFILE);\
+         $(ECHO) "     $(C) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\
+       done;
+
+.PHONY: library
+library: $(LIBFILE) 
+
+# dunno why it is making deps every time so...
+
+#$(LIBFILE): $(OBJECT_LIB) $(DEPFILE)
+$(LIBFILE): $(OBJECT_LIB)
+       ar rcs $(LIBFILE) $(OBJECT_LIB)
+
+.PHONY: cli
+#cli: $(LIBFILE) $(DEPFILE)
+cli: $(LIBFILE)
+       make sub_cli
+
+.PHONY: sub_cli
+sub_cli: $(EXEC)
+
+# generally better to use the project local clean scripts, but this will make it so that the make targets can be run again
+
+.PHONY: clean
+clean:
+       rm -f $(DEPFILE) $(LIBFILE)
+       for obj in $(OBJECT_LIB) $(OBJECT_EXEC); do rm -f $$obj || true; done
+       for i in $(EXEC); do [ -e $$i ] && rm $$i || true; done 
+
+# recipes
+vpath %.c $(SRCDIR_List)
+$(TMPDIR)/%.o: %.c
+       $(C) $(CFLAGS) -o $@ -c $<
diff --git a/developer/make/targets_tester b/developer/make/targets_tester
new file mode 100644 (file)
index 0000000..fef0831
--- /dev/null
@@ -0,0 +1,108 @@
+
+# This targets file links to an existing project library. If it is missing it will give an error rather than chaining back to build it.  This is the behavior the tester wants when testing a project library pulled from the release directory.
+
+.SUFFIXES:
+
+#--------------------------------------------------------------------------------
+# files have two suffixes by convention, e.g.: X.lib.c or Y.cli.c, this targets file ignores the X.lib.c files, if any.
+#
+
+# bail early if there is no compiler
+ifeq ($(C),)
+  $(error No C compiler specified.)
+endif
+
+# keep only the source directories that are in the file system
+SRCDIR_List := $(wildcard $(SRCDIR_List))
+
+# bail early if the SRCDIR_list is empty
+ifeq ($(SRCDIR_List),)
+  $(error source directory found so nothing to do)
+endif
+
+# Identify lib and cli sources (but we don't build the lib, but the lib.c files are also used as headers, so we need them for dependency checking.
+# duplicate source file names in different directories will cause problems with this makefile
+C_SOURCE_LIB  := $(foreach dir, $(SRCDIR_List), $(wildcard $(dir)/*.lib.c))
+C_SOURCE_EXEC := $(foreach dir, $(SRCDIR_List), $(wildcard $(dir)/*.cli.c))
+
+#remove the suffix to get base name
+C_BASE_EXEC=  $(sort $(patsubst %.cli.c,  %, $(notdir $(C_SOURCE_EXEC))))
+
+# object files for building the each command line interface progs
+OBJECT_EXEC= $(patsubst %, $(TMPDIR)/%.cli.o, $(C_BASE_EXEC))
+
+# executables are made from EXEC sources
+EXEC= $(patsubst %, $(EXECDIR)/%, $(C_BASE_EXEC))
+
+# include directories
+# the new C programming style gated sections in source instead of header filesheader
+INCFLAG_List := $(foreach dir, $(SRCDIR_List), -I $(dir))
+CFLAGS += $(INCFLAG_List)
+
+#--------------------------------------------------------------------------------
+# targets
+
+.PHONY: all
+all: usage
+
+.PHONY: usage
+usage:
+       @echo example usage: make clean
+       @echo example usage: make dependency cli
+       @echo example usage: make dependency
+       @echo example usage: make cli
+
+.PHONY: version
+version:
+       @echo "tester_targets version 1.0"
+       if [ ! -z "$(C)" ]; then $(C) -v; fi
+       /bin/make -v
+
+.PHONY: information
+information:
+       @printf "· → Unicode middle dot — visible: [%b]\n" "·"
+       @echo "SRCDIR_List: " $(SRCDIR_List)
+       @echo "C_SOURCE_LIB: " $(C_SOURCE_LIB)
+       @echo "C_SOURCE_EXEC: " $(C_SOURCE_EXEC)
+       @echo "C_BASE_EXEC: " $(C_BASE_EXEC)
+       @echo "OBJECT_EXEC: " $(OBJECT_EXEC)
+       @echo "EXEC: " $(EXEC)
+       @echo "INCFLAG_List: " $(INCFLAG_List)
+
+
+# We generate dependencies for .lib.c AND .cli. because the tester might include the interface or local portion of some .lib.c. But we do NOT produce rules for building .lib.o or the library.
+
+
+.PHONY: dependency
+dependency: $(DEPFILE)
+
+$(DEPFILE): $(C_SOURCE_LIB) $(C_SOURCE_EXEC)
+       @rm -f $(DEPFILE)
+       $(C) $(CFLAGS) -MM $(C_SOURCE_EXEC) \
+         | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
+       echo "deps for .cli.o file linking";\
+       for i in $(C_BASE_EXEC); do \
+         echo "" >> $(DEPFILE); \
+         echo "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o" >> $(DEPFILE); \
+         echo "        $(C) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\
+       done;
+
+.PHONY: cli
+cli: $(LIBFILE) $(DEPFILE)
+       make sub_cli
+
+.PHONY: sub_cli
+sub_cli: $(EXEC)
+
+# generally better to use the project local clean scripts, but this will make it so that the make targets can be run again
+
+.PHONY: clean
+clean:
+       rm -f $(DEPFILE)
+       for obj in $(OBJECT_EXEC); do rm -f $$obj || true; done
+       for i in $(EXEC); do [ -e $$i ] && rm $$i || true; done 
+
+# recipes
+vpath %.c $(SRCDIR_List)
+$(TMPDIR)/%.o: %.c
+       $(C) $(CFLAGS) -o $@ -c $<
diff --git a/developer/make🖉/RT_0.h b/developer/make🖉/RT_0.h
deleted file mode 100644 (file)
index e102a5c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef RT·ENVIRONMENT_H
-#define RT·ENVIRONMENT_H
-  #include <stdint.h>
-  #include <stdbool.h>
-
-  typedef unsigned int uint;
-
-  #define Local static
-  #define Free(pt) free(pt); (pt) = NULL;
-
-#endif
diff --git a/developer/make🖉/environment_RT_0 b/developer/make🖉/environment_RT_0
deleted file mode 100644 (file)
index 515ee36..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# makefile environment variable defaults.
-#  cc is the name of the C compiler
-#  <name>.c is C source code.
-
-SHELL=/bin/bash
-
-ECHO= echo -e
-#ECHO= echo
-
-SRCDIR_List=cc cc🖉
-LIBDIR=scratchpad
-EXECDIR=machine
-TMPDIR=scratchpad
-
-DEPFILE=$(TMPDIR)/makefile-cc.deps
-LIBFILE=$(TMPDIR)/lib.a
-
-C=gcc
-CFLAGS=
-LINKFLAGS=-L$(LIBDIR) -L/lib64 -L/lib
diff --git a/developer/make🖉/targets_developer b/developer/make🖉/targets_developer
deleted file mode 100644 (file)
index 883cf16..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-.SUFFIXES:
-
-#--------------------------------------------------------------------------------
-# files have two suffixes by convention, e.g.: X.lib.c or Y.cli.c 
-#
-
-# bail early if there is no compiler
-ifeq ($(C),)
-  $(error No C compiler specified.)
-endif
-
-# keep only the source directories that are in the file system
-SRCDIR_List := $(wildcard $(SRCDIR_List))
-
-# bail early if the SRCDIR_list is empty
-ifeq ($(SRCDIR_List),)
-  $(error source directory found so nothing to do)
-endif
-
-# duplicate source file names in different directories will cause
-# problems with this makefile
-
-C_SOURCE_LIB := $(foreach dir, $(SRCDIR_List), $(wildcard $(dir)/*.lib.c))
-C_SOURCE_EXEC := $(foreach dir, $(SRCDIR_List), $(wildcard $(dir)/*.cli.c))
-
-#remove the suffix to get base name
-C_BASE_LIB=  $(sort $(patsubst %.lib.c,  %, $(notdir $(C_SOURCE_LIB))))
-C_BASE_EXEC=  $(sort $(patsubst %.cli.c,  %, $(notdir $(C_SOURCE_EXEC))))
-
-# two sets of object files, one for the lib, and one for the command line interface progs
-OBJECT_LIB= $(patsubst %, $(TMPDIR)/%.lib.o, $(C_BASE_LIB))
-OBJECT_EXEC= $(patsubst %, $(TMPDIR)/%.cli.o, $(C_BASE_EXEC))
-
-# executables are made from EXEC sources
-EXEC= $(patsubst %, $(EXECDIR)/%, $(C_BASE_EXEC))
-
-# the new C programming style gated sections in source instead of header filesheader
-INCFLAG_List := $(foreach dir, $(SRCDIR_List), -I $(dir))
-CFLAGS += $(INCFLAG_List)
-
-#--------------------------------------------------------------------------------
-# targets
-
-.PHONY: all
-all: usage
-
-.PHONY: usage
-usage:
-       @echo example usage: make dependency library cli
-       @echo example usage: make dependency
-       @echo example usage: make library
-       @echo example usage: make cli
-
-.PHONY: version
-version:
-       @echo makefile version 7.1
-       if [ ! -z "$(C)" ]; then $(C) -v; fi
-       /bin/make -v
-
-.PHONY: information
-information:
-       @echo "SRCDIR_List: " $(SRCDIR_List)
-       @echo "C_SOURCE_LIB: " $(C_SOURCE_LIB)
-       @echo "C_SOURCE_EXEC: " $(C_SOURCE_EXEC)
-       @echo "C_BASE_LIB: " $(C_BASE_LIB)
-       @echo "C_BASE_EXEC: " $(C_BASE_EXEC)
-       @echo "OBJECT_LIB: " $(OBJECT_LIB)
-       @echo "OBJECT_EXEC: " $(OBJECT_EXEC)
-       @echo "EXEC: " $(EXEC)
-       @echo "INCFLAG_List: " $(INCFLAG_List)
-
-
-.PHONY: dependency
-dependency: $(DEPFILE)
-
-$(DEPFILE): $(C_SOURCE_LIB) $(C_SOURCE_EXEC)
-       @rm -f $(DEPFILE)
-       $(C) $(CFLAGS) -MM  $(C_SOURCE_LIB) $(C_SOURCE_EXEC) \
-         | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
-       echo "deps for C linking";\
-        # build library:\
-       for i in $(C_BASE_EXEC); do\
-         $(ECHO) >> $(DEPFILE);\
-         $(ECHO) "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o $(LIBFILE)" >> $(DEPFILE);\
-         $(ECHO) "     $(C) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\
-       done;
-
-.PHONY: library
-library: $(LIBFILE) 
-
-$(LIBFILE): $(OBJECT_LIB) $(DEPFILE)
-       ar rcs $(LIBFILE) $(OBJECT_LIB)
-
-.PHONY: cli
-cli: $(LIBFILE) $(DEPFILE)
-       make sub_cli
-
-.PHONY: sub_cli
-sub_cli: $(EXEC)
-
-# generally better to use the project local clean scripts, but this will make it so that the make targets can be run again
-
-.PHONY: clean
-clean:
-       rm -f $(DEPFILE) $(LIBFILE)
-       for obj in $(OBJECT_LIB) $(OBJECT_EXEC); do rm -f $$obj || true; done
-       for i in $(EXEC); do [ -e $$i ] && rm $$i || true; done 
-
-# recipes
-vpath %.c $(SRCDIR_List)
-$(TMPDIR)/%.o: %.c
-       $(C) $(CFLAGS) -o $@ -c $<
diff --git a/developer/make🖉/targets_tester b/developer/make🖉/targets_tester
deleted file mode 100644 (file)
index 6b2953a..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-
-# This targets file links to an existing project library. If it is missing it will give an error rather than chaining back to build it.  This is the behavior the tester wants when testing a project library pulled from the release directory.
-
-.SUFFIXES:
-
-#--------------------------------------------------------------------------------
-# files have two suffixes by convention, e.g.: X.lib.c or Y.cli.c, this targets file ignores the X.lib.c files, if any.
-#
-
-# bail early if there is no compiler
-ifeq ($(C),)
-  $(error No C compiler specified.)
-endif
-
-# keep only the source directories that are in the file system
-SRCDIR_List := $(wildcard $(SRCDIR_List))
-
-# bail early if the SRCDIR_list is empty
-ifeq ($(SRCDIR_List),)
-  $(error source directory found so nothing to do)
-endif
-
-# Identify lib and cli sources (but we don't build the lib, but the lib.c files are also used as headers, so we need them for dependency checking.
-# duplicate source file names in different directories will cause problems with this makefile
-C_SOURCE_LIB  := $(foreach dir, $(SRCDIR_List), $(wildcard $(dir)/*.lib.c))
-C_SOURCE_EXEC := $(foreach dir, $(SRCDIR_List), $(wildcard $(dir)/*.cli.c))
-
-#remove the suffix to get base name
-C_BASE_EXEC=  $(sort $(patsubst %.cli.c,  %, $(notdir $(C_SOURCE_EXEC))))
-
-# object files for building the each command line interface progs
-OBJECT_EXEC= $(patsubst %, $(TMPDIR)/%.cli.o, $(C_BASE_EXEC))
-
-# executables are made from EXEC sources
-EXEC= $(patsubst %, $(EXECDIR)/%, $(C_BASE_EXEC))
-
-# include directories
-# the new C programming style gated sections in source instead of header filesheader
-INCFLAG_List := $(foreach dir, $(SRCDIR_List), -I $(dir))
-CFLAGS += $(INCFLAG_List)
-
-#--------------------------------------------------------------------------------
-# targets
-
-.PHONY: all
-all: usage
-
-.PHONY: usage
-usage:
-       @echo example usage: make dependency cli
-       @echo example usage: make dependency
-       @echo example usage: make cli
-
-.PHONY: version
-version:
-       @echo "tester_targets version 1.0"
-       if [ ! -z "$(C)" ]; then $(C) -v; fi
-       /bin/make -v
-
-.PHONY: information
-information:
-       @echo "SRCDIR_List: " $(SRCDIR_List)
-       @echo "C_SOURCE_LIB: " $(C_SOURCE_LIB)
-       @echo "C_SOURCE_EXEC: " $(C_SOURCE_EXEC)
-       @echo "C_BASE_EXEC: " $(C_BASE_EXEC)
-       @echo "OBJECT_EXEC: " $(OBJECT_EXEC)
-       @echo "EXEC: " $(EXEC)
-       @echo "INCFLAG_List: " $(INCFLAG_List)
-
-
-# We generate dependencies for .lib.c AND .cli. because the tester might include the interface or local portion of some .lib.c. But we do NOT produce rules for building .lib.o or the library.
-
-
-.PHONY: dependency
-dependency: $(DEPFILE)
-
-$(DEPFILE): $(C_SOURCE_LIB) $(C_SOURCE_EXEC)
-       @rm -f $(DEPFILE)
-       $(C) $(CFLAGS) -MM $(C_SOURCE_EXEC) \
-         | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
-       echo "deps for .cli.o file linking";\
-       for i in $(C_BASE_EXEC); do \
-         echo "" >> $(DEPFILE); \
-         echo "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o" >> $(DEPFILE); \
-         echo "        $(C) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\
-       done;
-
-.PHONY: cli
-cli: $(LIBFILE) $(DEPFILE)
-       make sub_cli
-
-.PHONY: sub_cli
-sub_cli: $(EXEC)
-
-# generally better to use the project local clean scripts, but this will make it so that the make targets can be run again
-
-.PHONY: clean
-clean:
-       rm -f $(DEPFILE)
-       for obj in $(OBJECT_EXEC); do rm -f $$obj || true; done
-       for i in $(EXEC); do [ -e $$i ] && rm $$i || true; done 
-
-# recipes
-vpath %.c $(SRCDIR_List)
-$(TMPDIR)/%.o: %.c
-       $(C) $(CFLAGS) -o $@ -c $<
diff --git a/developer/nautilus/Decrypt b/developer/nautilus/Decrypt
new file mode 100644 (file)
index 0000000..7796397
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+# decrypt file given as first argument
+#
+# This version overwrites the source file with the result. In this way there is only one file used, and Nautilus does not
+# get confused  and select an unrelated file.
+#
+# The decryption result is held in memory before the overwrite, which could be a problem if the source
+# file is very large. It would be better to create a /tmp file, then copy that for the overwrite step. For very large
+# files, the result should be moved back, but then the highlighted selection in nautilus must jump to a different file.
+
+import sys
+import subprocess
+import os
+
+import gi
+gi.require_version("Gtk", "3.0")
+from gi.repository import Gtk
+
+def message(mess):
+  dlg = Gtk.MessageDialog(
+    message_type=Gtk.MessageType.ERROR
+    ,buttons=Gtk.ButtonsType.OK
+    ,text=mess
+    )
+  dlg.set_title('Decrypt Info')
+  dlg.run()
+  dlg.destroy()
+
+def run(command):
+  #print("command: " ,command)   
+  proc = subprocess.Popen(
+    command
+    ,stdout = subprocess.PIPE
+    ,stderr = subprocess.PIPE
+  )
+  stdout, stderr = proc.communicate()
+  # print("stdout: ", len(stdout) ," " ,stdout)
+  # print("stderr: ", len(stderr) ," " ,stderr)
+  # print("proc.returncode: ", proc.returncode)
+  return proc.returncode, stdout, stderr
+
+
+file_src = sys.argv[1] 
+if not os.path.exists(file_src):
+  message("file not found: " + file_src)
+  sys.exit(1)
+if os.path.getsize(file_src) > 2**30:
+  message("beyond current Nautilus Decrypt file size limit of 1 gigabyte")
+  sys.exit(1)
+
+
+ext = file_src[ -4:]
+
+if ext == ".gpg":
+  file_dst = file_src[0:-4]
+  code ,stdout ,stderr = run(["/usr/bin/gpg2" ,"--quiet" ,"--output" ,"-" ,"--decrypt" ,file_src])
+  # if all went well, the decrypted data is in stdout
+  if code == 0:
+    if not os.path.exists(file_dst):
+      os.rename(file_src ,file_dst) 
+      with open(file_dst ,"wb") as f:
+        f.write(stdout)
+    else:
+      message(file_dst + " already exists")
+
+  if len(stderr) > 0:
+     message(stderr.decode("utf-8"))
+   
+
+  
diff --git a/developer/nautilus/Encrypt b/developer/nautilus/Encrypt
new file mode 100644 (file)
index 0000000..31ab6ac
--- /dev/null
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+# encyrpt file given as first argument
+#
+# This version overwites the source file with the result. In this way there is only one file used, and Nautilus does not
+# get confused and select an unrelated file.
+#
+# The encryption result is currently held in memory before the overwrite, which could be a problem if the source
+# file is very large.  It would be better to create a /tmp file, then copy that for the overwrite step.  For very large
+# files, the result should be moved back, but then the highlighted selection in nautilus must jump to a different file.
+
+import sys
+import subprocess
+import os
+
+import gi
+gi.require_version("Gtk", "3.0")
+from gi.repository import Gtk
+
+def message(mess):
+  dlg = Gtk.MessageDialog(
+    message_type=Gtk.MessageType.ERROR
+    ,buttons=Gtk.ButtonsType.OK
+    ,text=mess
+    )
+  dlg.set_title('Encrypt Info')
+  dlg.run()
+  dlg.destroy()
+
+def run(command):
+  #print("command: " ,command)   
+  proc = subprocess.Popen(
+    command
+    ,stdout = subprocess.PIPE
+    ,stderr = subprocess.PIPE
+  )
+  stdout, stderr = proc.communicate()
+  # print("stdout: ", len(stdout) ," " ,stdout)
+  # print("stderr: ", len(stderr) ," " ,stderr)
+  # print("proc.returncode: ", proc.returncode)
+  return proc.returncode, stdout, stderr
+
+file_src = sys.argv[1]
+if not os.path.exists(file_src):
+  message("file not found: " + file_src)
+  sys.exit(1)
+if os.path.getsize(file_src) > 2**30:
+  message("beyond current Nautilus Encrypt file size limit of 1 gigbyte")
+  sys.exit(1)
+
+file_dst = sys.argv[1] + ".gpg"
+
+key_ids = [
+         "thomas-key-2911@reasoningtechnology.com"
+         ,"shihju@reasoningtechnology.com"
+         ]
+
+command = ["gpg2" ,"--quiet" ,"--encrypt" ,"--output" ,"-"]
+for id in key_ids:
+  command.append("-r")
+  command.append(id)
+command.append(file_src)
+code ,stdout ,stderr = run(command)
+
+# if all went well, the encrypted data is in stdout
+if code == 0:
+  if not os.path.exists(file_dst):
+    os.rename(file_src ,file_dst) 
+    with open(file_dst ,"wb") as f:
+      f.write(stdout)
+  else:
+    message(file_dst + " already exists")
+
+if len(stderr) > 0:
+  message(stderr.decode("utf-8"))
+
+
+
diff --git a/developer/nautilus/README.md b/developer/nautilus/README.md
new file mode 100644 (file)
index 0000000..ed5205d
--- /dev/null
@@ -0,0 +1 @@
+place these in user directories,  ~/.local/share/nautilus/scripts  or install the package nautilus-scripts-manager and put them in /usr/share/nautilus-script
diff --git a/developer/nautilus🖉/Decrypt b/developer/nautilus🖉/Decrypt
deleted file mode 100644 (file)
index 7796397..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env python3
-# decrypt file given as first argument
-#
-# This version overwrites the source file with the result. In this way there is only one file used, and Nautilus does not
-# get confused  and select an unrelated file.
-#
-# The decryption result is held in memory before the overwrite, which could be a problem if the source
-# file is very large. It would be better to create a /tmp file, then copy that for the overwrite step. For very large
-# files, the result should be moved back, but then the highlighted selection in nautilus must jump to a different file.
-
-import sys
-import subprocess
-import os
-
-import gi
-gi.require_version("Gtk", "3.0")
-from gi.repository import Gtk
-
-def message(mess):
-  dlg = Gtk.MessageDialog(
-    message_type=Gtk.MessageType.ERROR
-    ,buttons=Gtk.ButtonsType.OK
-    ,text=mess
-    )
-  dlg.set_title('Decrypt Info')
-  dlg.run()
-  dlg.destroy()
-
-def run(command):
-  #print("command: " ,command)   
-  proc = subprocess.Popen(
-    command
-    ,stdout = subprocess.PIPE
-    ,stderr = subprocess.PIPE
-  )
-  stdout, stderr = proc.communicate()
-  # print("stdout: ", len(stdout) ," " ,stdout)
-  # print("stderr: ", len(stderr) ," " ,stderr)
-  # print("proc.returncode: ", proc.returncode)
-  return proc.returncode, stdout, stderr
-
-
-file_src = sys.argv[1] 
-if not os.path.exists(file_src):
-  message("file not found: " + file_src)
-  sys.exit(1)
-if os.path.getsize(file_src) > 2**30:
-  message("beyond current Nautilus Decrypt file size limit of 1 gigabyte")
-  sys.exit(1)
-
-
-ext = file_src[ -4:]
-
-if ext == ".gpg":
-  file_dst = file_src[0:-4]
-  code ,stdout ,stderr = run(["/usr/bin/gpg2" ,"--quiet" ,"--output" ,"-" ,"--decrypt" ,file_src])
-  # if all went well, the decrypted data is in stdout
-  if code == 0:
-    if not os.path.exists(file_dst):
-      os.rename(file_src ,file_dst) 
-      with open(file_dst ,"wb") as f:
-        f.write(stdout)
-    else:
-      message(file_dst + " already exists")
-
-  if len(stderr) > 0:
-     message(stderr.decode("utf-8"))
-   
-
-  
diff --git a/developer/nautilus🖉/Encrypt b/developer/nautilus🖉/Encrypt
deleted file mode 100644 (file)
index 31ab6ac..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/env python3
-# encyrpt file given as first argument
-#
-# This version overwites the source file with the result. In this way there is only one file used, and Nautilus does not
-# get confused and select an unrelated file.
-#
-# The encryption result is currently held in memory before the overwrite, which could be a problem if the source
-# file is very large.  It would be better to create a /tmp file, then copy that for the overwrite step.  For very large
-# files, the result should be moved back, but then the highlighted selection in nautilus must jump to a different file.
-
-import sys
-import subprocess
-import os
-
-import gi
-gi.require_version("Gtk", "3.0")
-from gi.repository import Gtk
-
-def message(mess):
-  dlg = Gtk.MessageDialog(
-    message_type=Gtk.MessageType.ERROR
-    ,buttons=Gtk.ButtonsType.OK
-    ,text=mess
-    )
-  dlg.set_title('Encrypt Info')
-  dlg.run()
-  dlg.destroy()
-
-def run(command):
-  #print("command: " ,command)   
-  proc = subprocess.Popen(
-    command
-    ,stdout = subprocess.PIPE
-    ,stderr = subprocess.PIPE
-  )
-  stdout, stderr = proc.communicate()
-  # print("stdout: ", len(stdout) ," " ,stdout)
-  # print("stderr: ", len(stderr) ," " ,stderr)
-  # print("proc.returncode: ", proc.returncode)
-  return proc.returncode, stdout, stderr
-
-file_src = sys.argv[1]
-if not os.path.exists(file_src):
-  message("file not found: " + file_src)
-  sys.exit(1)
-if os.path.getsize(file_src) > 2**30:
-  message("beyond current Nautilus Encrypt file size limit of 1 gigbyte")
-  sys.exit(1)
-
-file_dst = sys.argv[1] + ".gpg"
-
-key_ids = [
-         "thomas-key-2911@reasoningtechnology.com"
-         ,"shihju@reasoningtechnology.com"
-         ]
-
-command = ["gpg2" ,"--quiet" ,"--encrypt" ,"--output" ,"-"]
-for id in key_ids:
-  command.append("-r")
-  command.append(id)
-command.append(file_src)
-code ,stdout ,stderr = run(command)
-
-# if all went well, the encrypted data is in stdout
-if code == 0:
-  if not os.path.exists(file_dst):
-    os.rename(file_src ,file_dst) 
-    with open(file_dst ,"wb") as f:
-      f.write(stdout)
-  else:
-    message(file_dst + " already exists")
-
-if len(stderr) > 0:
-  message(stderr.decode("utf-8"))
-
-
-
diff --git a/developer/nautilus🖉/README.md b/developer/nautilus🖉/README.md
deleted file mode 100644 (file)
index ed5205d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-place these in user directories,  ~/.local/share/nautilus/scripts  or install the package nautilus-scripts-manager and put them in /usr/share/nautilus-script
diff --git a/developer/test/e/f/ff b/developer/test/e/f/ff
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/developer/test/e/f/g/gg b/developer/test/e/f/g/gg
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/developer/test/e/f🖉/ff b/developer/test/e/f🖉/ff
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/developer/test/e/f🖉/g/gg b/developer/test/e/f🖉/g/gg
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/developer/tool/env b/developer/tool/env
new file mode 100644 (file)
index 0000000..154c63a
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# input guards
+
+  env_must_be="tool_shared/bespoke🖉/env"
+  error=false
+  if [ "$ENV" != "$env_must_be" ]; then
+    echo "$(script_fp):: error: must be run in the $env_must_be environment"
+    error=true
+  fi
+  if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+    echo "$script_afp:: This script must be sourced, not executed."
+    error=true
+  fi
+  if $error; then exit 1; fi
+
+# so we can do the build
+
+export PATH=\
+"$REPO_HOME"/developer/tool🖉/\
+:"$REPO_HOME"/tool_shared/bespoke🖉/\
+:"$PATH"
+
+# misc
+
+  # make .githolder and .gitignore visible
+  alias ls="ls -a"
+
+# some feedback to show all went well
+
+  export PROMPT_DECOR="$PROJECT"_developer
+  export ENV=$(script_fp)
+  echo ENV "$ENV"
+  cd "$REPO_HOME"/developer/
+
+
+
diff --git a/developer/tool/make b/developer/tool/make
new file mode 100755 (executable)
index 0000000..84e1111
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/env /bin/bash
+
+set -e
+cd ${REPO_HOME}/developer
+/bin/make -f tool🖉/makefile $@
+
diff --git a/developer/tool/makefile b/developer/tool/makefile
new file mode 100644 (file)
index 0000000..550c796
--- /dev/null
@@ -0,0 +1,17 @@
+
+RT-INCOMMON:=$(REPO_HOME)/release
+
+include $(RT-INCOMMON)/make/environment_RT_0
+
+CFLAGS+=-Werror -include "$(RT-INCOMMON)/make/RT_0.h"
+LINKFLAGS+= -l$(PROJECT)
+LIBFILE=$(LIBDIR)/lib$(PROJECT).a
+
+include $(RT-INCOMMON)/make/targets
+-include $(DEPFILE)
+
+
+
+
+
+
diff --git a/developer/tool/release b/developer/tool/release
new file mode 100755 (executable)
index 0000000..49ca12f
--- /dev/null
@@ -0,0 +1,66 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# input guards
+
+  if [ -z "$REPO_HOME" ]; then
+    echo "$(script_fp):: REPO_HOME is not set."
+    exit 1
+  fi
+
+  env_must_be="developer/tool🖉/env"
+  if [ "$ENV" != "$env_must_be" ]; then
+    echo "$(script_fp):: error: must be run in the $env_must_be environment"
+    exit 1
+  fi
+
+# script local environment
+
+  release_dp="$REPO_HOME/release"
+  if [ ! -d "$release_dp" ]; then
+    mkdir -p "$release_dp"
+  fi
+
+  # Function to copy and set permissions
+  install_file() {
+    source_fp="$1"
+    target_dp="$2"
+    perms="$3"
+
+    target_file="$target_dp/$(basename "$source_fp")"
+
+    if [ ! -f "$source_fp" ]; then
+      echo "install_file:: Source file '$source_fp' does not exist."
+      return 1
+    fi
+
+    if ! install -m "$perms" "$source_fp" "$target_file"; then
+      echo "Error: Failed to install $(basename "$source_fp") to $target_dp"
+      exit 1
+    else
+      echo "Installed $(basename "$source_fp") to $target_dp with permissions $perms"
+    fi
+  }
+# do the release
+
+  echo "Starting release process..."
+
+  # # Install shell scripts
+  # for script in $shell_dp/*; do
+  #   install_file "$script" "$release_dp" "ug+r+x"
+  # done
+
+  dev_dp="$REPO_HOME/developer"
+
+  # for now we punt the release
+  pushd ../release >& /dev/null
+  set -x
+  ln -snf ../developer/amd64 amd64
+  ln -snf ../developer/bash🖉 bash
+  ln -snf ../developer/emacs🖉 emacs
+  ln -snf ../developer/make🖉 make
+  set +x
+  popd >& /dev/null
+
+echo "$(script_fp) done."
diff --git a/developer/tool🖉/env b/developer/tool🖉/env
deleted file mode 100644 (file)
index 154c63a..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-
-# input guards
-
-  env_must_be="tool_shared/bespoke🖉/env"
-  error=false
-  if [ "$ENV" != "$env_must_be" ]; then
-    echo "$(script_fp):: error: must be run in the $env_must_be environment"
-    error=true
-  fi
-  if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
-    echo "$script_afp:: This script must be sourced, not executed."
-    error=true
-  fi
-  if $error; then exit 1; fi
-
-# so we can do the build
-
-export PATH=\
-"$REPO_HOME"/developer/tool🖉/\
-:"$REPO_HOME"/tool_shared/bespoke🖉/\
-:"$PATH"
-
-# misc
-
-  # make .githolder and .gitignore visible
-  alias ls="ls -a"
-
-# some feedback to show all went well
-
-  export PROMPT_DECOR="$PROJECT"_developer
-  export ENV=$(script_fp)
-  echo ENV "$ENV"
-  cd "$REPO_HOME"/developer/
-
-
-
diff --git a/developer/tool🖉/make b/developer/tool🖉/make
deleted file mode 100755 (executable)
index 84e1111..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/env /bin/bash
-
-set -e
-cd ${REPO_HOME}/developer
-/bin/make -f tool🖉/makefile $@
-
diff --git a/developer/tool🖉/makefile b/developer/tool🖉/makefile
deleted file mode 100644 (file)
index 550c796..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-
-RT-INCOMMON:=$(REPO_HOME)/release
-
-include $(RT-INCOMMON)/make/environment_RT_0
-
-CFLAGS+=-Werror -include "$(RT-INCOMMON)/make/RT_0.h"
-LINKFLAGS+= -l$(PROJECT)
-LIBFILE=$(LIBDIR)/lib$(PROJECT).a
-
-include $(RT-INCOMMON)/make/targets
--include $(DEPFILE)
-
-
-
-
-
-
diff --git a/developer/tool🖉/release b/developer/tool🖉/release
deleted file mode 100755 (executable)
index 49ca12f..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-
-# input guards
-
-  if [ -z "$REPO_HOME" ]; then
-    echo "$(script_fp):: REPO_HOME is not set."
-    exit 1
-  fi
-
-  env_must_be="developer/tool🖉/env"
-  if [ "$ENV" != "$env_must_be" ]; then
-    echo "$(script_fp):: error: must be run in the $env_must_be environment"
-    exit 1
-  fi
-
-# script local environment
-
-  release_dp="$REPO_HOME/release"
-  if [ ! -d "$release_dp" ]; then
-    mkdir -p "$release_dp"
-  fi
-
-  # Function to copy and set permissions
-  install_file() {
-    source_fp="$1"
-    target_dp="$2"
-    perms="$3"
-
-    target_file="$target_dp/$(basename "$source_fp")"
-
-    if [ ! -f "$source_fp" ]; then
-      echo "install_file:: Source file '$source_fp' does not exist."
-      return 1
-    fi
-
-    if ! install -m "$perms" "$source_fp" "$target_file"; then
-      echo "Error: Failed to install $(basename "$source_fp") to $target_dp"
-      exit 1
-    else
-      echo "Installed $(basename "$source_fp") to $target_dp with permissions $perms"
-    fi
-  }
-# do the release
-
-  echo "Starting release process..."
-
-  # # Install shell scripts
-  # for script in $shell_dp/*; do
-  #   install_file "$script" "$release_dp" "ug+r+x"
-  # done
-
-  dev_dp="$REPO_HOME/developer"
-
-  # for now we punt the release
-  pushd ../release >& /dev/null
-  set -x
-  ln -snf ../developer/amd64 amd64
-  ln -snf ../developer/bash🖉 bash
-  ln -snf ../developer/emacs🖉 emacs
-  ln -snf ../developer/make🖉 make
-  set +x
-  popd >& /dev/null
-
-echo "$(script_fp) done."
diff --git a/document/#RT_code_format.org# b/document/#RT_code_format.org#
new file mode 100644 (file)
index 0000000..a223d6b
--- /dev/null
@@ -0,0 +1,195 @@
+#+TITLE: RT Code Format Guide
+#+AUTHOR: Thomas Walker Lynch
+#+DATE: 2025-02-28
+#+OPTIONS: toc:nil
+
+* Introduction
+
+The RT Code Format is intended to apply across languages, and thus the rules are agnostic to the language being code. The RT Code format produces a dense output so as to make room
+for longer identifier names and to put more code on that tiny screen of your laptop so you can work in a cafe. The rules focus on indentation, naming conventions, enclosure spacing, and unique handling of commas.
+
+* RT Formatting Should Be Applied After Any Other Formatting
+
+Many formatting tools apply automatic spacing and alignment adjustments before finalizing code.  One common example is Preemptive Enclosure Adjustment (PEA), where spaces are added or removed inside enclosures automatically.  This can cause conflicts with RT Formatting rules.
+
+RT Formatting should be applied as a **final step** to resolve such conflicts:
+- RT rules **override** PEA rules where they differ.
+- Where there is no conflict, existing formatting remains unchanged.
+- This ensures consistency when AI-generated code is reformatted.
+
+Common formatting conflicts:
+- **Indentation:** PEA favors 4-character indentation, whereas RT Formatting enforces 2-character indentation.  
+  This allows for more liberal indentation use and keeps statements compact.
+- **Comma Placement:** RT Formatting treats the comma as a **syntactic append operator**.
+- **Parentheses, Brackets, and Braces:** AI should follow the **exception detection procedure** for enclosure spacing.
+- **Operator Formatting:** Certain operators require **specific spacing rules**.
+- **Short Statements:** `if`, `while`, and similar constructs follow the **Short Stuff Rule** for single-line clauses.
+
+* Naming Conventions
+
+1. **Namespaces and types** use *PascalCase*.
+2. **Functions and variables** use *snake_case*.
+3. **Ordered collections** use `_list` as a suffix (e.g., `node_list`), even if the language does not have a `List` type.
+
+Examples:
+#+BEGIN_SRC c
+mouse_count
+test_LabelList_0  // Function testing LabelList (a class/type)
+Thomas_Walker_Lynch
+#+END_SRC
+
+* Binary Operators
+
+  There is no space around multiply and divide binary operators.
+
+  There is one space around all other operators.
+
+* Assignment
+
+   Two types of assignment:
+
+   1. sampling assignment, `=` inside `if`, `while`, etc.
+   2. single statement assignment 
+
+   No space around sampling assignment `=`.
+
+Example:
+#+BEGIN_SRC c
+if( result=some_condition() ){  // Sampling assignment, no spaces
+  process(result);
+}
+a = b + c;  // Regular assignment with spaces
+#+END_SRC
+
+* No space before Newline
+
+There is never space before an unquoted newline.
+
+* Enclosure
+
+Enclosed text is found after an opening enclosure punctuation symbol,
+and before the matching closing punctuation symbol.
+
+- `(...)` (parentheses)
+- `{...}` (braces)
+- `[...]` (square brackets)
+- `<...>` (angle brackets)
+
+It is common to find enclosures as part of language statements. For example:
+#+BEGIN_SRC c
+if(i<10)
+#+END_SRC
+Here the enclosed text is `i<10`.
+
+As another example:
+#+BEGIN_SRC c
+while(true)
+#+END_SRC
+Here the enclosured text is `true`.
+
+Enclosures are also found in expressions. For example:
+#+BEGIN_SRC c
+ 3*(2 + 4)
+#+END_SRC
+Here the enclosed text is `2 + 4`.
+
+There can be multiple enclosures in a given statement, depending on the language, or in a given expression.  For example:
+#+BEGIN_SRC c
+ (1 +3)*(2 + 4)
+#+END_SRC
+Here there are two enclosures `(1 + 3)`  and `(2 + 4)`.  The first enclosure encloses the text `1 + 3`  while the second encloses `(2 + 4)`.
+
+In RT formatting, there is no native space before or after the enclosure punctuation.  There can be space due to other rules, such as the space around the plus operator. For example:
+#+BEGIN_SRC c
+ (1*3) + (2*4)
+#+END_SRC
+Here the space around the enclosure punctuation belongs to the operator, rather than to the enclosure punctuation.
+
+Enclosed text can hold further enclosed text. This is 'nesting' of enclosures.
+
+Because enclosure nesting can run deep, we have allowed for one exception to the no space enclosure punctuation rule. Follow these steps:
+
+** Line-by-Line Formatting
+
+Enclosure formatting is applied **per line**, without scanning beyond that line.
+
+- **Virtual Closure Rule:**  
+  At the **end of a line**, any still-open enclosure punctuation is treated as **closed** for formatting purposes.
+
+- **Virtual Opening Rule:**  
+  At the **start of a new line**, any **orphaned closing punctuation** found there is treated as **belonging to the current line**.
+
+
+** Procedure for Identifying Enclosure Exceptions
+
+1. The language is not Lisp.
+2. The enclosure meets **all** of the following conditions:
+   - It opens and closes on a **single line**.
+   - It contains at least **one nested enclosure** inside.
+   - It is not found in the enclosed text of other enclosure on that line.
+3. If these conditions hold, **apply the exception**:
+   - Insert **one space** after the opening enclosure punctuation.
+   - Insert **one space** before the closing enclosure punctuation.
+
+**Example of a qualifying enclosure:**
+#+BEGIN_SRC c
+if( (x == 3 || y < 5) && z ){
+  process_data();
+}
+#+END_SRC
+
+Here, `( (x == 3 || y < 5) && z )` qualifies for spacing adjustment.
+
+**Example of a non-qualifying enclosure:**
+#+BEGIN_SRC c
+if(y < 5){
+  process_data();
+}
+#+END_SRC
+
+Since no enclosure on this line meets the conditions, **no additional spaces** are added.
+
+** Adjacency
+When two enclosures appear side by side (like `)(` or `}{`), there is *no space* between them.
+
+* Commas
+
+The **comma rule** is one of the most distinctive and recognizable aspects of RT Code Formatting.
+
+1. **One space before the comma** (e.g., `a ,b`).
+2. **No space after the comma** (e.g., `a ,b`).
+3. **Line break before the comma when breaking lines**, but **no line break after the comma**.
+
+Examples:
+#+BEGIN_SRC c
+a
+,b
+#+END_SRC
+
+When function arguments get too long, break lines as follows:
+#+BEGIN_SRC c
+result = some_function(
+   first_argument
+  ,second_argument_with_longer_name
+  ,third_argument
+);
+#+END_SRC
+
+✔ **This ensures consistency and maintains readability.**  
+
+* Short Stuff Rule
+
+For **`if`**, **`for`**, and **`while`** statements that introduce a *single-line* clause with no `else`, if the **condition and clause together fit within one line, they should **remain on a single line without braces**.  Say when about ≤40 characters, though this is not strictly ≤40 characters — it depends on complexity and formatting. If the condition and action are simple, or perhaps fit a parallel construct with other short stuff, they should stay inline.
+
+
+
+
+
+Example:
+#+BEGIN_SRC c
+if( x > 0 ) return x;
+while( has_next() ) process_next();
+#+END_SRC
+
\ No newline at end of file
diff --git a/document/#how_to_use_project_directory_structure.txt# b/document/#how_to_use_project_directory_structure.txt#
new file mode 100644 (file)
index 0000000..6c3ea4c
--- /dev/null
@@ -0,0 +1,59 @@
+### Work Flow
+
+#### 1. Project Administrator
+
+1.1. Download the project from GitHub.
+1.2. Install the required tools.
+1.3. Explain the workflows and where things are located to project members.
+1.4. Perform Major and Minor Release administration.
+
+#### 2. Developer
+
+2.1. From the Mosaic directory, run `> source env_developer` to set up the
+     developer environment.
+2.2. Use `> make` to build the project, and `> release` to copy relevant files
+     to `$REPO_HOME/release` for testing.
+2.3. The tester will test the release candidate.
+
+#### 3. Tester
+
+3.1. From the Mosaic directory, run `> source env_tester` to set up the tester
+     environment.
+3.2. Use `> make` to build the tests, and `> shell/test_<name>` to run a test.
+     Alternatively, you can cd into one of the test directories, source the
+     environment for that test, and run it manually.
+3.3. Testing and development will likely iterate until the release candidate is
+     ready to be turned into a versioned release.
+
+#### 4. Major Release
+
+4.1. The release candidate is located in the `$REPO_HOME/release` directory and
+     has passed testing.
+4.2. Check that the program `$REPO_HOME/tool_shared/bespoke/version` outputs the
+     correct information. If necessary, modify it.
+4.3. A new branch is created in the project for the release, named
+     `release_v<n>.0`, where `v<n>.0` is the version number from the `version`
+     program. The minor version number is set to zero (`.0`), and it is assumed
+     that this will be the case after each major release.
+4.4. Rename the release directory to `$REPO_HOME/release_v<n>.0`, and create a
+     new empty `$REPO_HOME/release` directory. The new empty release directory
+     can be used by developers who download the project and make local edits, as
+     the build scripts target this directory.
+
+#### 5. Minor Release
+
+If urgent changes need to be made to the most recent major release, these edits
+should be made on the corresponding major release branch. The developer makes
+the edits, and the tester tests the release candidate as usual. The `version`
+program is updated. Once the release candidate is finalized, rename the
+directory to `release_v<n>.<m>`, where `<m>` is the minor version number. If
+needed, merge the changes into the `core_developer_branch`.
+
+---
+
+### Tips:
+
+- If you are acting in multiple roles (e.g., developer, tester, and project
+  administrator), keep separate terminal shells open for each role. This way,
+  the environment will remain correctly configured for the tasks related to
+  each role.
diff --git a/document/Java_import_as_alternative.txt b/document/Java_import_as_alternative.txt
new file mode 100644 (file)
index 0000000..dda2904
--- /dev/null
@@ -0,0 +1,33 @@
+Java has long been criticized for its lack of support for `import as`, despite
+years of requests and proposals.
+
+The Java platform’s approach to aliasing issues relies on using fully qualified
+names, which poses challenges given the length of package names, especially when
+they include reversed domain names.
+
+Because `Mosaic` is used to help with testing and is not part of the project
+being tested, when aliasing conflicts arise, it is typically the `Mosaic` identifiers
+that need to be fully qualified. Such a renamed identifier can exceed 34
+characters!
+
+One proposal to get around this was to use an `In` class where the members were
+class extensions of imported classes.  Then all imports would have the prefix `In.`.
+However, this did not work out because constructors are not
+inherited, and Java’s restrictions on `final` classes prevent the use of
+`LocalClass extends ImportClass {}` to give no names to classes.
+
+Another proposal was to use the `alias` project on GitHub, which offers an XML-based
+approach to aliasing. However, it introduces complexities, as it requires XML
+configurations to be supplied to the compiler, adding setup overhead. Perhaps
+another tool could create these.
+
+We studied a preprocessing proposal where `import as` statements would be
+replaced with fully qualified names before compilation. However, this approach
+changes the tool flow for users and would require additional steps to ensure
+`jdb` points to the original source files rather than intermediate files, which
+complicates debugging. For both this proposal and the prior, we wanted to avoid
+joining the world of java tool development.
+
+So we have a simple solution, it is not ideal, but it is not bad.  We prefix
+the string `Mosaic_` to the front of all the class names in the Mosaic library.
+As a shop we are adopting this convention for all packaged java code.
diff --git a/document/Pencil_Suffix.html b/document/Pencil_Suffix.html
new file mode 100644 (file)
index 0000000..f0cbe01
--- /dev/null
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
+  <title>Pencil Suffix</title>
+  <style>
+    html {
+      font-size: 16px;
+    }
+
+    body {
+      font-family: 'Noto Sans JP', Arial, sans-serif;
+      background-color: hsl(0, 0%, 0%);
+      color: hsl(42, 100%, 80%);
+      padding: 2rem;
+      margin: 0;
+    }
+
+    .page {
+      padding: 1.25rem;
+      margin: 1.25rem auto;
+      max-width: 46.875rem;
+      background-color: hsl(0, 0%, 0%);
+      box-shadow: 0 0 0.625rem hsl(42, 100%, 50%);
+    }
+
+    ul, li {
+      font-size: 1rem;
+      list-style-type: none;
+    }
+
+    li::before {
+      content: "• ";
+      margin-right: 0.3125rem;
+    }
+
+    li {
+      margin-bottom: 0.3125rem;
+    }
+
+    .description {
+      margin-left: 0.625rem;
+      color: hsl(42, 100%, 75%);
+    }
+
+    code {
+      font-family: 'Courier New', Courier, monospace;
+      background-color: hsl(0, 0%, 25%);
+      color: hsl(42, 100%, 90%);
+      padding: 0.125rem 0.25rem;
+      border-radius: 0.1875rem;
+      font-size: 90%;
+    }
+
+    h1 {
+      text-align: center;
+      color: hsl(42, 100%, 84%);
+      text-transform: uppercase;
+      margin-bottom: 1.25rem;
+    }
+
+    h2 {
+      color: hsl(42, 100%, 84%);
+      text-transform: uppercase;
+      margin-top: 2.5rem;
+    }
+
+    p {
+      color: hsl(42, 100%, 90%);
+      margin-bottom: 1.25rem;
+      text-align: justify;
+    }
+  </style>
+</head>
+<body>
+  <div class="page">
+<h1>The Pencil Suffix and Authored Files</h1>
+
+<h3>How to Use the Pencil Suffix</h3>
+
+  <p>The pencil suffix is a Unicode character, 🖉, that is placed as the last character of a filename or directory name. It signifies that the file, or contents of a so named directory, are uniquely authored and should not be deleted or rebuilt by clean scripts or build scripts. The pencil suffix also serves as a communication tool among team members as to where in the project edits should be inserted.</p>
+
+  <strong>Two methods for marking a file as authored:</strong>
+  <ul>
+    <li><em>Directory with Pencil Suffix:</em> This method marks all contents within said directory sub-tree as being authored.</li>
+    <li><em>File Name Last Character as Pencil:</em> This directly marks the file itself as authored.</li>
+  </ul>
+</li>
+
+  <p>The recommended method to mark files as authored is to place them in a directory, where the name of said directory ends with the pencil symbol. Directly marked files will then be exceptional cases.</p>
+
+<h3>Pencil suffix definition</h3>
+
+<p>By definition, the pencil suffix designates files or directories as <em>leaves in the build tree</em>. Hence, by definition pencil suffix files are not built by tools. It is a corollary that these files are the primary sources of material and serve as points of entry for edits by authors, whether human or AI. Thus we refer to these leaves as <span class='term'>authored</span>. At the time of writing, this definition is maintained by contract with the programers, along with the assistance of the <code>rm_na</code> tool.</p>
+
+<h3>Replace <code>rm</code> with <code>rm_na</code> in scripts</h3>
+
+<p>The <code>rm_na</code> command is a modified version of the standard <code>rm</code> command, and it refuses to delete files marked as being authored.  This is true whether the file is marked as authored with a pencil suffix or is found in a directory tree marked as such.</p>
+  
+<p>Use <code>rm_na</code> in place of <code>rm</code>  in scripts that clean, build, or otherwise manipulate project files.</p>
+
+<p>While <code>rm_na</code> offers a safeguard, the pencil suffix itself does not enforce permissions. Users can still manually delete 🖉-marked files using <code>rm</code>, and roqque builds can overwrite them.</p>
+
+<h3>Pencil suffix and editablity</h3>
+
+<p>The pencil suffix does not inherently restrict or permit editing. A file without the pencil suffix that has write permissions can also be edited; however, such edits are at risk of being overwritten or lost during builds or cleans. While lack of a pencil suffix on a file, or inclusion in such a directory, does not prevent a file from being edited - it does mean that it might not be advisable to edit such a file. Conversely, it is intended that a file marked as authored can be edited without fear of the edits being overwritten. Hence pencil suffix files are the appropriate places to insert edits into a project. In this sense the pencil suffix does indicate a file is 'editable'; however, this is not the definition of the pencil suffix, rather it is a property that emerges from the definition.</p>
+
+<h3>Symbolic Links</h3>
+
+<p>Symbolic links, while facilitating access to authored files, are independent entities that merely point to targets. As such, the link itself is not an authored file, and its lifecycle is separate from the content it references. A symbolic link can be created or deleted without impacting the authored content it points to.</p>
+
+<p>Because symbolic links are not authored entities, they do not carry pencil suffixes, even when their targets do. This distinction ensures that the pencil suffix remains specific to authored files and directories, highlighting their preservation within the project.</p>
+
+<p>However, this lack of pencil suffix on links can create confusion. Users viewing symbolic links in a directory listing may overlook authored content if they rely solely on the link names. The intended edit points within the project might not be apparent unless users examine the targets of the links.  </p>
+
+<p>To mitigate potential confusion, file browsers or editors that visually distinguish symbolic links from regular files are highly valuable. These tools help users identify links at a glance, preserving the clarity of authored content within the project structure.  </p>
+
+
+
+
+<h3>Hard Links</h3>
+
+<p> Among multiple hard links, none is distinguished as being the primary file link. Hence, should a hard link point at an authored file, and that hardlink is not in a directory that already identifies it as an authored file, it should have the pencil suffix. It is the only option available, because in general we can not know the order of deletion of the hard links, and thus do not know which will be the last one that should not be deleted. Hard links are strange beasts that should be avoided for many other reasons as well.</p>
+
+
+<h3>Future direction</h3>
+
+<p>In the future we hope for tighter integration with the OS, perhaps through use of sub-users (see the subu project), or through a property based file system. For now it is a communication tool, one which is strengthened through use of the <code>rm_na</code> command.</p>
+
+
+</body>
+</html>
diff --git a/document/RT_C_control_structure.html b/document/RT_C_control_structure.html
new file mode 100644 (file)
index 0000000..8ecc937
--- /dev/null
@@ -0,0 +1,153 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
+  <title>RT C coding conventions</title>
+  <style>
+    body {
+      font-family: 'Noto Sans JP', Arial, sans-serif;
+      background-color: hsl(0, 0%, 0%);
+      color: hsl(42, 100%, 80%);
+      padding: 2rem;
+    }
+    .page {
+      padding: 3rem;
+      margin: 1.25rem auto;
+      max-width: 46.875rem;
+      background-color: hsl(0, 0%, 0%);
+      box-shadow: 0 0 0.625rem hsl(42, 100%, 50%);
+    }
+    h1 {
+      font-size: 1.5rem;
+      text-align: center;
+      color: hsl(42, 100%, 84%);
+      text-transform: uppercase;
+      margin-top: 1.5rem;
+    }
+    h2 {
+      font-size: 1.25rem;
+      color: hsl(42, 100%, 84%);
+      text-align: center;
+      margin-top: 2rem;
+    }
+    h3 {
+      font-size: 1.125rem;
+      color: hsl(42, 100%, 75%);
+      margin-top: 1.5rem;
+    }
+    p, li {
+      color: hsl(42, 100%, 90%);
+      text-align: justify;
+      margin-bottom: 1rem;
+    }
+    code {
+      font-family: 'Courier New', Courier, monospace;
+      background-color: hsl(0, 0%, 25%);
+      padding: 0.125rem 0.25rem;
+      color: hsl(42, 100%, 90%);
+    }
+  </style>
+</head>
+
+<body>
+<div class="page">
+  <header>
+    <h1>Reasoning Technology (RT) C file control structure</h1>
+    <p>© 2024 Thomas Walker Lynch - All Rights Reserved.</p>
+  </header>
+
+  <h2>Introduction</h2>
+
+  <p>This document summarizes some of the coding conventions used in RT C projects. Discussed here are conventions for integrated header designs, ad hoc namespaces, and a structured approach to source file extensions. The document also outlines the associated build process using a standardized makefile.</p>
+
+  <h2>Header file integration</h2>
+
+  <p>RT C projects adopt an innovative approach by integrating headers directly into source files. This ensures consistency between interfaces and implementations, eliminating mismatches. Each file contains both an interface and an implementation section, gated by preprocessor directives.</p>
+
+  <p>Each RT C source file integrates its header directly into the source file. This locality makes header content easier to maintain as everything is found in a single file. It also eliminates the need to maintain two files for each module.</p>
+
+  <h3>Each file has two sections</h3>
+  <ul>
+    <li><strong>Interface section:</strong> Contains declarations, macros, and <code>#includes</code> needed for the interface. Ensures consistency by defining the interface exactly once, even when the file is included multiple times.</li>
+    <li><strong>Implementation section:</strong> Contains function definitions and additional includes needed for the implementation. This section is compiled only when the file is used as an implementation.</li>
+  </ul>
+
+  <p>Each section is turned on and off with the CPP macro <code>FACE</code>.</p>
+
+  <h3>Example</h3>
+  <pre><code>
+// If not an FACE, then an IMPLEMENTATION
+#ifndef FACE
+  #define MyModule·IMPLEMENTATION
+  // Ensures included files are processed for their interfaces.
+  #define FACE
+#endif
+
+// Define the interface exactly once.
+#ifndef MyModule·FACE
+#define MyModule·FACE
+  // Interface-only includes go here.
+  void MyModule·function();
+#endif
+
+#ifdef MyModule·IMPLEMENTATION
+  // Additional includes for implementation go here.
+  #include <stdio.h>
+  void MyModule·function() {
+    printf("Hello, World!\n");
+  }
+#endif
+  </code></pre>
+
+  <h3>Explanation</h3>
+  <p>The example above demonstrates the structure and purpose of each block:</p>
+  <p><strong>First block:</strong> Ensures that the file operates correctly based on the value of <code>FACE</code>. If <code>FACE</code> is undefined, it defines <code>MyModule·IMPLEMENTATION</code> to enable the implementation section and sets <code>FACE</code> to ensure subsequent includes process interface sections.</p>
+  <p><strong>Second block:</strong> Defines the interface, including declarations and interface-specific includes. The <code>#ifndef MyModule·FACE</code> macro ensures the interface is defined exactly once, regardless of how many times the file is included.</p>
+  <p><strong>Third block:</strong> Contains implementation-specific includes and function definitions. Guarded by <code>MyModule·IMPLEMENTATION</code>, it is only included when compiling the implementation.</p>
+  <p>Interface includes are placed in the interface block, ensuring they are available wherever the interface is used. Implementation includes are isolated in the implementation block, minimizing unnecessary dependencies in other files.</p>
+
+  <h2>Namespace conventions</h2>
+  <p>RT projects use ad hoc namespaces to maintain clarity and prevent naming conflicts. This is achieved by prefixing exported identifiers with a module-specific name followed by the <code>·</code> (cdot) character.</p>
+
+  <h3>Conventions</h3>
+  <ul>
+    <li><strong>Prefix:</strong> The module name serves as the prefix, ensuring all identifiers are unique across the program.</li>
+    <li><strong>Separator:</strong> The <code>·</code> character visually separates the prefix from the identifier name, maintaining readability and avoiding conflicts.</li>
+  </ul>
+
+  <h3>Example</h3>
+  <pre><code>
+void Server·run();
+  </code></pre>
+
+  <h2>Source file extensions</h2>
+  <p>RT projects use standardized extensions to distinguish between library and command-line interface (CLI) source files:</p>
+  <ul>
+    <li><strong><code>.lib.c</code>:</strong> Files implementing library functions.</li>
+    <li><strong><code>.cli.c</code>:</strong> Files implementing command-line tools.</li>
+  </ul>
+
+  <p>The <code>.lib.c</code> files compile into libraries, while <code>.cli.c</code> files compile into standalone executables. The makefile processes these files automatically, ensuring a clear separation of functionality.</p>
+
+  <h3>Build process</h3>
+  <p>The build process follows these steps:</p>
+  <ol>
+    <li><strong>Dependency generation:</strong> Run <code>make dependency</code> to create dependencies. This step is only required when the dependency structure changes.</li>
+    <li><strong>Compilation:</strong> Run <code>make cli</code> to compile CLI sources and link them against the library. The makefile automatically manages targets and dependencies.</li>
+  </ol>
+
+  <h2>Benefits</h2>
+  <ul>
+    <li><strong>Consistency:</strong> Integrated headers ensure interface and implementation are always in sync.</li>
+    <li><strong>Modularity:</strong> Each file encapsulates its interface and implementation, reducing coupling.</li>
+    <li><strong>Clarity:</strong> Ad hoc namespaces and standardized extensions improve readability and organization.</li>
+    <li><strong>Efficiency:</strong> The makefile automates builds, minimizing errors and streamlining development.</li>
+  </ul>
+
+  <h2>Conclusion</h2>
+  <p>This document outlines the conventions and practices for writing and building RT C projects. By integrating headers, adopting namespaces, and standardizing extensions, RT ensures its projects are robust, modular, and easy to maintain.</p>
+</div>
+</body>
+</html>
diff --git a/document/RT_code_format.org b/document/RT_code_format.org
new file mode 100644 (file)
index 0000000..9c045a6
--- /dev/null
@@ -0,0 +1,196 @@
+#+TITLE: RT Code Format Guide
+#+AUTHOR: Thomas Walker Lynch
+#+DATE: 2025-02-28
+#+OPTIONS: toc:nil
+
+# perhaps add rules about main functions being merely wrappers that pack arguments, call the reall business function, and then unpack results from the business function perhaps to print, and to set the main return value.
+
+* Introduction
+
+The RT Code Format is intended to apply across languages, and thus the rules are agnostic to the language being code. The RT Code format produces a dense output so as to make room
+for longer identifier names and to put more code on that tiny screen of your laptop so you can work in a cafe. The rules focus on indentation, naming conventions, enclosure spacing, and unique handling of commas.
+
+* RT Formatting Should Be Applied After Any Other Formatting
+
+Many formatting tools apply automatic spacing and alignment adjustments before finalizing code.  One common example is Preemptive Enclosure Adjustment (PEA), where spaces are added or removed inside enclosures automatically.  This can cause conflicts with RT Formatting rules.
+
+RT Formatting should be applied as a **final step** to resolve such conflicts:
+- RT rules **override** PEA rules where they differ.
+- Where there is no conflict, existing formatting remains unchanged.
+- This ensures consistency when AI-generated code is reformatted.
+
+Common formatting conflicts:
+- **Indentation:** PEA favors 4-character indentation, whereas RT Formatting enforces 2-character indentation.  
+  This allows for more liberal indentation use and keeps statements compact.
+- **Comma Placement:** RT Formatting treats the comma as a **syntactic append operator**.
+- **Parentheses, Brackets, and Braces:** AI should follow the **exception detection procedure** for enclosure spacing.
+- **Operator Formatting:** Certain operators require **specific spacing rules**.
+- **Short Statements:** `if`, `while`, and similar constructs follow the **Short Stuff Rule** for single-line clauses.
+
+* Naming Conventions
+
+1. **Namespaces and types** use *PascalCase*.
+2. **Functions and variables** use *snake_case*.
+3. **Ordered collections** use `_list` as a suffix (e.g., `node_list`), even if the language does not have a `List` type.
+
+Examples:
+#+BEGIN_SRC c
+mouse_count
+test_LabelList_0  // Function testing LabelList (a class/type)
+Thomas_Walker_Lynch
+#+END_SRC
+
+* Binary Operators
+
+  There is no space around multiply and divide binary operators.
+
+  There is one space around all other operators.
+
+* Assignment
+
+   Two types of assignment:
+
+   1. sampling assignment, `=` inside `if`, `while`, etc.
+   2. single statement assignment 
+
+   No space around sampling assignment `=`.
+
+Example:
+#+BEGIN_SRC c
+if( result=some_condition() ){  // Sampling assignment, no spaces
+  process(result);
+}
+a = b + c;  // Regular assignment with spaces
+#+END_SRC
+
+* No space before Newline
+
+There is never space before an unquoted newline.
+
+* Enclosure
+
+Enclosed text is found after an opening enclosure punctuation symbol,
+and before the matching closing punctuation symbol.
+
+- `(...)` (parentheses)
+- `{...}` (braces)
+- `[...]` (square brackets)
+- `<...>` (angle brackets)
+
+It is common to find enclosures as part of language statements. For example:
+#+BEGIN_SRC c
+if(i<10)
+#+END_SRC
+Here the enclosed text is `i<10`.
+
+As another example:
+#+BEGIN_SRC c
+while(true)
+#+END_SRC
+Here the enclosured text is `true`.
+
+Enclosures are also found in expressions. For example:
+#+BEGIN_SRC c
+ 3*(2 + 4)
+#+END_SRC
+Here the enclosed text is `2 + 4`.
+
+There can be multiple enclosures in a given statement, depending on the language, or in a given expression.  For example:
+#+BEGIN_SRC c
+ (1 +3)*(2 + 4)
+#+END_SRC
+Here there are two enclosures `(1 + 3)`  and `(2 + 4)`.  The first enclosure encloses the text `1 + 3`  while the second encloses `(2 + 4)`.
+
+In RT formatting, there is no native space before or after the enclosure punctuation.  There can be space due to other rules, such as the space around the plus operator. For example:
+#+BEGIN_SRC c
+ (1*3) + (2*4)
+#+END_SRC
+Here the space around the enclosure punctuation belongs to the operator, rather than to the enclosure punctuation.
+
+Enclosed text can hold further enclosed text. This is 'nesting' of enclosures.
+
+Because enclosure nesting can run deep, we have allowed for one exception to the no space enclosure punctuation rule. Follow these steps:
+
+** Line-by-Line Formatting
+
+Enclosure formatting is applied **per line**, without scanning beyond that line.
+
+- **Virtual Closure Rule:**  
+  At the **end of a line**, any still-open enclosure punctuation is treated as **closed** for formatting purposes.
+
+- **Virtual Opening Rule:**  
+  At the **start of a new line**, any **orphaned closing punctuation** found there is treated as **belonging to the current line**.
+
+
+** Procedure for Identifying Enclosure Exceptions
+
+1. The language is not Lisp.
+2. The enclosure meets **all** of the following conditions:
+   - It opens and closes on a **single line**.
+   - It contains at least **one nested enclosure** inside.
+   - It is not found in the enclosed text of other enclosure on that line.
+3. If these conditions hold, **apply the exception**:
+   - Insert **one space** after the opening enclosure punctuation.
+   - Insert **one space** before the closing enclosure punctuation.
+
+**Example of a qualifying enclosure:**
+#+BEGIN_SRC c
+if( (x == 3 || y < 5) && z ){
+  process_data();
+}
+#+END_SRC
+
+Here, `( (x == 3 || y < 5) && z )` qualifies for spacing adjustment.
+
+**Example of a non-qualifying enclosure:**
+#+BEGIN_SRC c
+if(y < 5){
+  process_data();
+}
+#+END_SRC
+
+Since no enclosure on this line meets the conditions, **no additional spaces** are added.
+
+** Adjacency
+When two enclosures appear side by side (like `)(` or `}{`), there is *no space* between them.
+
+* Commas
+
+The **comma rule** is one of the most distinctive and recognizable aspects of RT Code Formatting.
+
+1. **One space before the comma** (e.g., `a ,b`).
+2. **No space after the comma** (e.g., `a ,b`).
+3. **Line break before the comma when breaking lines**, but **no line break after the comma**.
+
+Examples:
+#+BEGIN_SRC c
+a
+,b
+#+END_SRC
+
+When function arguments get too long, break lines as follows:
+#+BEGIN_SRC c
+result = some_function(
+   first_argument
+  ,second_argument_with_longer_name
+  ,third_argument
+);
+#+END_SRC
+
+✔ **This ensures consistency and maintains readability.**  
+
+* Short Stuff Rule
+
+For **`if`**, **`for`**, and **`while`** statements that introduce a *single-line* clause with no `else`, if the **condition and clause together fit within one line, they should **remain on a single line without braces**.  Say when about ≤40 characters, though this is not strictly ≤40 characters — it depends on complexity and formatting. If the condition and action are simple, or perhaps fit a parallel construct with other short stuff, they should stay inline.
+
+
+
+
+
+Example:
+#+BEGIN_SRC c
+if( x > 0 ) return x;
+while( has_next() ) process_next();
+#+END_SRC
+
diff --git a/document/Workflow.org b/document/Workflow.org
new file mode 100644 (file)
index 0000000..e028946
--- /dev/null
@@ -0,0 +1,55 @@
+* Project Workflow
+
+
+This document outlines the responsibilities of different roles in the project and the release process.
+
+** 1. Project Administrator
+   - Download the project from GitHub.
+   - Install the required tools.
+   - Explain workflows and file locations to project members.
+   - Manage Major and Minor Releases.
+
+** 2. Developer
+   - From the `Mosaic/` directory, run:
+     #+begin_src sh
+       source env_developer
+     #+end_src
+     to set up the developer environment.
+   - Build the project:
+     #+begin_src sh
+       make
+     #+end_src
+   - Copy relevant files to the release directory:
+     #+begin_src sh
+       release
+     #+end_src
+   - The tester will evaluate the release candidate.
+
+** 3. Tester
+   - From the `Mosaic/` directory, set up the testing environment:
+     #+begin_src sh
+       source env_tester
+     #+end_src
+   - Build and run tests:
+     #+begin_src sh
+       make
+       shell/test_<name>
+     #+end_src
+   - Alternatively, change to a test directory, source its environment, and run tests manually.
+   - The development and testing process will iterate until the release candidate is ready for an official release.
+
+** 4. Major Release
+   - The release candidate is in `$REPO_HOME/release` and has passed testing.
+   - Verify that `$REPO_HOME/tool_shared/bespoke/version` outputs the correct version information. Modify it if necessary.
+   - Create a new branch named `release_v<n>.0` where `<n>` is the major version.
+   - Rename the release directory to `$REPO_HOME/release_v<n>.0` and create a new empty `$REPO_HOME/release/` directory.
+
+** 5. Minor Release
+   - Urgent changes to a major release are made on its corresponding branch.
+   - The developer makes edits, and the tester evaluates the release candidate as usual.
+   - The `version` program is updated.
+   - Rename the release directory to `release_v<n>.<m>`, where `<m>` is the minor version.
+   - Merge changes into `core_developer_branch` if necessary.
+
+** 6. Tips
+   - If acting in multiple roles (developer, tester, admin), keep separate terminal shells for each role to avoid misconfigurations.
diff --git a/document/bash_name_of_script.txt b/document/bash_name_of_script.txt
new file mode 100644 (file)
index 0000000..3637574
--- /dev/null
@@ -0,0 +1,40 @@
+
+Bash is inconsistent about returning the name of the running script in
+all scenarios (sourced, executed directly, from with in a function called
+by another function).
+
+1.
+
+BASH_SOURCE[0] was used because $0 did not work with sourced scripts (a
+fact that is leveraged for detecting when in a sourced script).
+
+2.
+
+However, this did not work in all scenarios:
+
+  read -r -d '' script_afp_string <<'EOF'
+  realpath "${BASH_SOURCE[0]}" 2>/dev/null
+  EOF
+
+    script_afp(){
+      eval "$script_afp_string"
+    }
+
+  export script_afp_string
+  export -f script_afp
+
+When `script_afp` was exported, used in another file, and used within a function
+in that other file, it reported `environment` for the script name at
+BASH_SOURCE[0].  In various call scenarios the actual script name appears at
+BASH_SOURCE[1] or even at BASH_SOURCE[2].  
+
+3.
+
+As a stable alternative to having a script_afp function, place this line
+at the top of scripts that use the `script_XX` functions, or at the top
+of all scripts:
+
+  script_afp=realpath "${BASH_SOURCE[0]}"
+
+Then use $script_afp as a string within other functions. It will have stable
+value no matter the call structure.
diff --git a/document/bracketed_phrases_section.txt b/document/bracketed_phrases_section.txt
new file mode 100644 (file)
index 0000000..295a3fa
--- /dev/null
@@ -0,0 +1,51 @@
+* Bracketed Phrases
+
+In token processing, a *bracketed phrase* is the text starting from an opening bracket up to its matching closing bracket, including both brackets. We treat any of `(...)`, `{...}`, `[...]`, or `<...>` as “brackets”. Bracketed phrases are detected purely at the token level—no higher-level grammar or semantics are considered.
+
+** Examples
+- **`if(x){...}` vs. `f(x){...}`**  
+  Both share the same token-level structure: an identifier followed by `(x)` and then `{...}`.  
+- **`sin(3x)`**  
+  Has one bracketed phrase `(3x)`, where `3x` is the “contents” and `()` is the “container.”
+
+** Nesting
+
+1. **Innermost Bracketed Phrase**  
+   Contains *no other* bracketed phrase inside it. Due to adjacency, multiple innermost bracketed phrases can occur.
+
+2. **Outermost Bracketed Phrase**  
+   An outermost bracketed phrase is one that is not itself contained in any other bracketed phrase.
+
+3. **Contained (Inner) Bracketed Phrase**  
+   A bracketed phrase located within the contents of another bracketed phrase (the *outer* one).
+
+4. **Bracketed Phrase with Nesting**  
+   A bracketed phrase that contains one or more bracketed phrases.
+
+   A bracketed phrase is “with nesting” only if it contains at least one inner bracketed phrase. In other words, non-quoted bracket punctuated phrases occurs inside the contents — not just commas or other punctuation.
+
+
+**Examples**
+In `sin(f(x) + (a))`, the phrase `(x)` is contained in `(f(x) (a))`, which in turn is contained in `sin(...)`.  `(a) is also contained in`(f(x) (a))`. `(x)` is innermost.
+`(a)` is also innermost.
+
+**Open Bracketed Phrases
+
+A bracketed phrase is **open** if it’s missing a matching opening or closing bracket.
+
+- **Open on the Right**: Has unmatched opening brackets (e.g., `(` but no `)`).
+- **Open on the Left**: Has unmatched closing brackets (e.g., `)` but no preceding `(`).
+
+** 1D Box Analogy
+
+Think of each bracketed phrase like a **1D CSS box**:
+
+- The **opening and closing brackets** are the “borders.”
+- **Margin (outside)**: By default, bracketed phrases have *no extra spacing* around their borders—unless another rule (like an operator or adjacent token) requires space.  
+  Example: `f()()` is valid with no space, but `f () ()` is not.
+- **Padding (inside)**: If a bracketed phrase is both  
+  1) outermost on a line,  
+  2) has nesting,  
+  3) and is not a Lisp s-expression,  
+  then place **one space** immediately after the opening bracket and **one space** before the closing bracket.
+
diff --git a/document/directory_naming.html b/document/directory_naming.html
new file mode 100644 (file)
index 0000000..d409362
--- /dev/null
@@ -0,0 +1,198 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
+
+  <title>Directory Structure Description</title>
+<style>
+  html {
+    font-size: 16px; /* This will be the base for rem units */
+  }
+
+  body {
+    font-family: 'Noto Sans JP', Arial, sans-serif;
+    background-color: hsl(0, 0%, 0%);
+    color: hsl(42, 100%, 80%);
+    padding: 2rem;
+    margin: 0;
+  }
+
+  .page {
+    padding: 1.25rem; /* 20px */
+    margin: 1.25rem auto; /* 20px */
+    max-width: 46.875rem; /* 750px */
+    background-color: hsl(0, 0%, 0%);
+    box-shadow: 0 0 0.625rem hsl(42, 100%, 50%); /* 10px */
+  }
+
+  ul, li {
+    font-size: 1rem; /* Keeping default font size */
+    list-style-type: none;
+  }
+
+  li::before {
+    content: "📁 ";
+    margin-right: 0.3125rem; /* 5px */
+  }
+
+  li {
+    margin-bottom: 0.3125rem; /* 5px */
+  }
+
+  .description {
+    margin-left: 0.625rem; /* 10px */
+    color: hsl(42, 100%, 75%);
+  }
+
+  code {
+    font-family: 'Courier New', Courier, monospace;
+    background-color: hsl(0, 0%, 25%);
+    color: hsl(42, 100%, 90%);
+    padding: 0.125rem 0.25rem; /* 2px 4px */
+    border-radius: 0.1875rem; /* 3px */
+    font-size: 90%;
+  }
+
+  h1 {
+    text-align: center;
+    color: hsl(42, 100%, 84%);
+    text-transform: uppercase;
+    margin-bottom: 1.25rem; /* 20px */
+  }
+
+  h2 {
+    color: hsl(42, 100%, 84%);
+    text-transform: uppercase;
+    margin-top: 2.5rem; /* 40px */
+  }
+
+  p {
+    color: hsl(42, 100%, 90%);
+    margin-bottom: 1.25rem; /* 20px */
+    text-align: justify;
+  }
+</style>
+
+</head>
+<body>
+
+  <div class="page">
+    <h1>Directory Naming</h1>
+
+    <h2>Reference</h2>
+
+    <ul>
+      <li>Mosaic/<span class="description">aka REPO_HOME, top level owned by the project administrator.</span></li>
+      <ul>
+        <li>developer/ <span class="description">Workspace for the developer. Has the source code, build scripts, and development-specific tools.</span></li>
+        <ul>
+          <li>deprecated/ <span class="description">Files and older versions being viewed, perhaps part of a refactoring effort.</span></li>
+          <li>document/ <span class="description">Documentation on developing and building the project.</span></li>
+          <li>javac/ <span class="description">Java source files for compilation.</span></li>
+          <li>jvm/ <span class="description">Compiled Java bytecode files for the project, typically a jar for a Java project.</span></li>
+          <li>scratchpad/ <span class="description">Temporary storage typically for intermediate files created during build.</span></li>
+          <li>shell/ <span class="description">Shell scripts intended to be part of the project release. (These are not tools.)</span></li>
+          <li>tool/ <span class="description">Tools created by the developer, used for development tasks.</span></li>
+        </ul>
+        <li>document/ <span class="description">General documentation about the project.</span></li>
+        <li>release/ <span class="description">Release candidate for testing. Becomes the release on the release branch.</span></li>
+        <li>scratchpad/ <span class="description">Temporary storage for project administration tasks.</span></li>
+        <li>tester/ <span class="description">Workspace for the tester. Has the test bench, tests, and test scripts.</span></li>
+        <ul>
+          <li>document/ <span class="description">Test-specific documentation.</span></li>
+          <li>javac/ <span class="description">The tests of the test bench sources.</span></li>
+          <li>tool/ <span class="description">Tools needed for testing and managing the test environment.</span></li>
+        </ul>
+        <li>tool/ <span class="description">Project administration specific tools.</span></li>
+        <li>tool_shared/ <span class="description">Tools shared across project roles.</span></li>
+        <ul>
+          <li>bespoke/ <span class="description">Shared tools developed within this project.</span></li>
+          <li>customized/ <span class="description">Modified versions of third-party tools adapted for the project.</span></li>
+          <li>document/ <span class="description">Documentation related to shared tools and setup.</span></li>
+          <li>third_party/ <span class="description">Shared tools sourced from third-party vendors or open-source projects. These have their own independent licenses,</span></li>
+        </ul>
+        <li>LICENSE.txt <span class="description">The project license detailing usage and distribution terms.</span></li>
+        <li>README.md <span class="description">A general overview and introduction to the project.</span></li>
+      </ul>
+    </ul>
+
+    <h2>Name origin and rationale</h2>
+
+    <p>Developers and project administrators typically do not employ a semantic system for
+      naming directories, but more commonly use conventional placeholder
+      names. The intended purpose of files in a directory with a placeholder
+      name then must be inferred from experience or inspection of the files, or
+      learned from documents or other people.</p>
+
+    <p>For example, a directory named <code>exe/</code> probably derives its name from the
+      fact that the contained files have their executable permission bit set;
+      however, such a directory will not contain all such files.  There might
+      even be some files in an <code>exe/</code> directory that do not have their
+      executable permission bit set. The two concepts being an <code>exe/</code> file
+      (i.e. being a file in an <code>exe/</code> directory) and being an executable file
+      are not identical. The actual intended meaning of being an <code>exe/</code> file
+      will sometimes be that the contained files are applications available to a
+      user, or that they are tools available for use in a project.
+    </p>
+
+    <p>The directory names in this project resulted from an exploration of a
+      property-based file system. In such a system a number of files and
+      agents are defined. Then we can ask questions about their relationships.
+      Files with a relationship to the developer are collected, and this
+      becomes the <code>developer/</code> directory. In a similar manner we get the
+      directories, <code>tester/</code>, and <code>javac/</code>.  In this latter case the
+      agent is a compiler rather than a role.
+      </p>
+      
+    <p>When attempting to apply the <code>is-for</code> property in practice it
+      became apparent that using this sole property was insufficient.  Consider
+      the directories <code>deprecated/</code> and <code>scratchpad/</code>. There is no
+      <em>Mr. Deprecated</em> or <em>Mr. Scratchpad</em> who the contained
+      files are for. (And this conclusion is not for the lack of trying. Even
+      mythological beings did not suffice as agents.) Rather than being for an
+      agent, the files collected in such a directory have in common a state of
+      being that was imposed upon them by decree.  Perhaps the developer, has
+      decreed that a file is now deprecated, or a build script has decreed that
+      it is a scratchpad file. Such decrees are typically more dynamic than the
+      relationship properties. Also, these properties are disconnected from the
+      contents of the file.  When, for example, a file has the property of being
+      for the java compiler, we gain some information about its contents. In the
+      universe of possible messages sent through a file, such a file will
+      contain text that is proposed to be java syntax conforming. In contrast,
+      when we learn that a file is <code>deprecated/</code> we gain no
+      information about the contents of the file, because any file can
+      be <code>deprecated</code>, independent of its contents.
+      </p>
+
+    <p>To understand a directory name within this system, one can imagine
+      reading said name as part of a sentence that integrates the
+      property. Consider two property names: <code>is-a</code>
+      and <code>is-for</code>. For example, "Each file in
+      the <code>document/</code> directory <code>is-a</code> document," or "Each
+      file in the <code>developer/</code> directory <code>is-for</code> the
+      developer."  Although the property name is not carried over from the
+      property based file system to the conventional file system, we can
+      typically infer what it must have been. (It is beyond the scope of
+      discussion here, but in actuality, property based file system collections
+      are defined by predicates. Each predicate is given a file's properties and
+      relationships as arguments, then resolves to true if and only if the file
+      belongs to the collection. Now wouldn't that be interesting if we instead
+      derived a probability?)
+    </p>
+
+    <p>It is uncommon for a property value to be plural. While it is not
+      disallowed, it rarely occurs in practice. This is true independent of
+      whether we are discussing a relationship property or a state
+      property. Hence when we make a file collection based on a shared property,
+      then carry that over as a directory name in a conventional file system,
+      the resulting directory name will often be singular.  This pattern can be
+      observed in the case of the <code>document/</code> directory, as shown in
+      the prior paragraph.
+    </p>
+
+  </div>
+
+</body>
+</html>
diff --git a/document/directory_structure.org b/document/directory_structure.org
new file mode 100644 (file)
index 0000000..09d9994
--- /dev/null
@@ -0,0 +1,50 @@
+* Project Directory Structure
+  This document explains the naming conventions and layout of the project files.
+
+** 1. Top-Level Directory (`Mosaic/`)
+   - aka `$REPO_HOME`, managed by the project administrator.
+
+** 2. Developer Workspace (`Mosaic/developer/`)
+   - Contains source code, build scripts, and development tools.
+
+   - **Subdirectories:**
+     - `deprecated/` :: Contains old or refactored files.
+     - `document/` :: Developer-specific documentation.
+     - `javac/` :: Java source code.
+     - `jvm/` :: Compiled Java bytecode (JARs, class files).
+     - `scratchpad/` :: Temporary workspace for builds.
+     - `shell/` :: Executable scripts.
+     - `tool/` :: Development utilities.
+
+** 3. Testing Workspace (`Mosaic/tester/`)
+   - Contains test benches, test scripts, and test documentation.
+
+   - **Subdirectories:**
+     - `document/` :: Documentation related to testing.
+     - `javac/` :: Java-based test sources.
+     - `tool/` :: Utilities for testing.
+
+** 4. General Documentation (`Mosaic/document/`)
+   - Contains overall project documentation.
+
+** 5. Release Directory (`Mosaic/release/`)
+   - The release candidate directory before finalization.
+
+** 6. Shared Tools (`Mosaic/tool_shared/`)
+   - Tools shared across different roles.
+
+   - **Subdirectories:**
+     - `bespoke/` :: Custom-built project tools.
+     - `customized/` :: Modified third-party tools.
+     - `document/` :: Tool-related documentation.
+     - `third_party/` :: Unmodified third-party tools.
+
+** 7. Other Files
+   - `LICENSE.txt` :: Project licensing information.
+   - `README.md` :: Project introduction.
+
+** 8. Naming Conventions
+   - Directory names are chosen based on logical properties.
+   - For example, `developer/` contains files *for* the developer.
+   - Plural names are generally avoided unless necessary.
+   - This system minimizes ambiguity and helps developers understand structure intuitively.
diff --git a/document/enclosure_old.org b/document/enclosure_old.org
new file mode 100644 (file)
index 0000000..eb57955
--- /dev/null
@@ -0,0 +1,140 @@
+* Bracketed Phrases
+
+Here we refer to token processing.  A 'bracketed phrase' is all the text found when parsing from the point an opening bracket is found, up until the point that the matching closing bracket is found. The phrase includes the enclosing brackets.
+
+We generalize the concept of bracketed phrase to include the following punctuation,
+and that found in between.
+
+- `(...)` (parentheses)
+- `{...}` (braces)
+- `[...]` (square brackets)
+- `<...>` (angle brackets)
+
+The '(', ')', '{', '}', '[', ']', '<', '>' are said to be parenthetical punctuation. 
+
+Generally a bracketed phrase is discovered at the token parsing level, as such it does not take into account any of the syntax nor semantics of the grammar that will be applied to the token stream later.
+
+However, there are special cases where higher level context will be required. Namely when distinguishing between angle brackets and magnitude comparisons, and for Lisp sexprs, as explained further below.
+
+Hence `if(x){ ...'  is formatted just as `f(x){...`  because in both cases the spacing is determined at the token level. That `if` is a statement, or that `f` is a function, has no baring because at the token level they are both merely identifiers.
+
+**As a Container**
+
+A bracketed phrase has enclosing matching punctuation known as the 'container'. Inside the containing punctuation are zero or more text characters, which are known as the 'contents'.  For example `sin(3x)` has one bracketed phrase,  `(3x)`, and the contents of this phrase is `3x`.  The container is `()`.
+
+**Nesting**
+
+1. **Kernel Bracketed Phrase**  
+
+   A bracketed phrase that does not contain another bracketed phrase.
+
+2. **Contained Bracketed Phrase**
+
+   A contained bracketed phrase is found in the contents of another bracketed phrase.
+
+   So for example, in `sin(f(x))` the bracketed phrase `(x)`  is contained in the bracketed phrase '(f(x))`, so it is a 'contained bracketed phrase'.
+
+   A contained bracketed phrase is also called an 'inner bracketed phrase'.
+
+3. **Outer Bracketed Phrase**
+
+   If a bracketed phrase is contained in another bracketed phrase, then the
+   contained bracketed phrase is the 'inner bracked phrase' and the bracked phase
+   that contains it is the 'outer bracketed phrase'.
+
+   An outer bracketed phrase that is not contained by any other bracketed phrase
+   is the 'outermost' bracketed phrase.  So for example, given `( a (b (c) (d)) )`
+   There are two kernels, '(c)' and '(d)'.  Those two kernels appear in the outer bracketed phrase of `(b (c) (d))`, that phrase is contained in the outer bracketed phrase of `( a (b (c) (d)) )`.
+
+4. **Bracketed Phrase with Nesting**
+
+   A bracketed phrase with nesting is one that contains at least one other bracketed phrase. It need not matter which matching punctuation the inner bracketed phrases have.
+
+   It follows that an Outer Bracketed Phrase will always be a Bracketed Phrase with Nesting.
+
+   It follows that a Kernel Bracketed Phrase is never a Bracketed Phrase with Nesting.
+
+4. **Outermost Bracketed Phrase**
+
+   An outermost bracketed phrase is not contained in any other bracketed phrase.
+
+
+**Open** 
+
+An open bracketed phrase is one on that has no matching closing punctuation, or not matching opening punctuation.
+
+An open on the lines bracketed phrase, is one that is open when tokenizing only the given line.
+
+1. **Open on Right on a Line**  
+   - If one or more unmatched on the line opening bracket punctuation appears, these are said to form an 'open on the right bracketed phrase'.
+   - These are treated as though they were closed on the right on the line.
+
+2. **Open on Left Enclosures**  
+   - If one or more unmatched on the line closing bracket punctuation appears, these are said to form an 'open on the left enclosure'.
+   - These are treated as though they were opened on the left on the line.
+
+**1D Box Analogy**
+
+Consider an bracketed phrase to be like a 1D CSS box. In this analogy consider the bracketed phrase punctuation to be the box borders. Then in the language of CSS we have margin, which is space outside of the bracketed phrase punctuation, and padding, which is space immediately inside the bracketed phrase punctuation.
+
+**Bracketed Phrase Margin**
+
+All bracketed phrases have no native spaces on the outside. I say 'native' because
+some other rules might add a space, such as operator rules, or bracketed phrase followed
+by an identifier.  Hence `f()()`  is correct while `f () ()` would be incorrect because both of the kernel bracketed phrases have spacing outside of them.  On the other hand `(a) + (b)` is correct, because the plus operator has spaces around it.
+
+**Bracketed Phrase Padding**
+
+When a bracketed phrase is both:  a) a bracketed phrase with nesting  AND b) an outermost bracketed phrase on the line, then: It receives one space after the opening bracket unless it is a Lisp sexpr, and one space before the closing bracket.
+
+There is no other case where a native space is placed after the opening bracket, or placed before the closing bracket.
+
+** Adjacency
+
+   When two separate bracketed phrases appear side by side.  There is no space between them.
+
+
+* Examples of Bracketed Phrase Formatting
+
+**Flat Bracketed Phrases (No Padding)**
+#+BEGIN_SRC c
+result = function_call(param1 ,param2);
+value = (uint32_t)(3 + 4*5);
+#+END_SRC
+
+**Nested Bracketed Phrases (Only an outer type of nested bracketed phrase receives padding)**
+#+BEGIN_SRC c
+if( (x == 3 || y < 5) && z ){
+  process_data();
+}
+#+END_SRC
+
+#+BEGIN_SRC c
+data.set( map.get(key) );
+#+END_SRC
+
+#+BEGIN_SRC c
+if( (index().compareTo(BigInteger.valueOf(array.size() - 1))) == 0 ){
+  execute_action();
+}
+#+END_SRC
+
+#+BEGIN_SRC c
+( a (b (c)) )
+#+END_SRC
+
+#+BEGIN_SRC c
+if(
+   ( condition_one() && condition_two() ) 
+){
+   execute_action();
+}
+#+END_SRC
+
+#+BEGIN_SRC c
+(uint32_t)(3 + 4*5)
+#+END_SRC
+
+#+BEGIN_SRC c
+data.set( map.get(key) );
+#+END_SRC
diff --git a/document/how_to_use_project_directory_structure.txt b/document/how_to_use_project_directory_structure.txt
new file mode 100644 (file)
index 0000000..6c3ea4c
--- /dev/null
@@ -0,0 +1,59 @@
+### Work Flow
+
+#### 1. Project Administrator
+
+1.1. Download the project from GitHub.
+1.2. Install the required tools.
+1.3. Explain the workflows and where things are located to project members.
+1.4. Perform Major and Minor Release administration.
+
+#### 2. Developer
+
+2.1. From the Mosaic directory, run `> source env_developer` to set up the
+     developer environment.
+2.2. Use `> make` to build the project, and `> release` to copy relevant files
+     to `$REPO_HOME/release` for testing.
+2.3. The tester will test the release candidate.
+
+#### 3. Tester
+
+3.1. From the Mosaic directory, run `> source env_tester` to set up the tester
+     environment.
+3.2. Use `> make` to build the tests, and `> shell/test_<name>` to run a test.
+     Alternatively, you can cd into one of the test directories, source the
+     environment for that test, and run it manually.
+3.3. Testing and development will likely iterate until the release candidate is
+     ready to be turned into a versioned release.
+
+#### 4. Major Release
+
+4.1. The release candidate is located in the `$REPO_HOME/release` directory and
+     has passed testing.
+4.2. Check that the program `$REPO_HOME/tool_shared/bespoke/version` outputs the
+     correct information. If necessary, modify it.
+4.3. A new branch is created in the project for the release, named
+     `release_v<n>.0`, where `v<n>.0` is the version number from the `version`
+     program. The minor version number is set to zero (`.0`), and it is assumed
+     that this will be the case after each major release.
+4.4. Rename the release directory to `$REPO_HOME/release_v<n>.0`, and create a
+     new empty `$REPO_HOME/release` directory. The new empty release directory
+     can be used by developers who download the project and make local edits, as
+     the build scripts target this directory.
+
+#### 5. Minor Release
+
+If urgent changes need to be made to the most recent major release, these edits
+should be made on the corresponding major release branch. The developer makes
+the edits, and the tester tests the release candidate as usual. The `version`
+program is updated. Once the release candidate is finalized, rename the
+directory to `release_v<n>.<m>`, where `<m>` is the minor version number. If
+needed, merge the changes into the `core_developer_branch`.
+
+---
+
+### Tips:
+
+- If you are acting in multiple roles (e.g., developer, tester, and project
+  administrator), keep separate terminal shells open for each role. This way,
+  the environment will remain correctly configured for the tasks related to
+  each role.
diff --git a/document/install_Eclipse.txt b/document/install_Eclipse.txt
new file mode 100644 (file)
index 0000000..167d14e
--- /dev/null
@@ -0,0 +1,22 @@
+
+The project is originally configured to be used with Emacs as an IDE. The tools
+can all be run from a shell inside of emacs. Even when using an IDE what the
+shell environment scripts and tools do should be understood.
+
+I have added a working IntelliJ IDEA configuration, so if you want a modern IDE
+it is probably best to go with this. See ItelliJ_IDEA.txt in this directory.
+
+I've not run Eclipse on the project, if you do, perhaps you can update the notes
+here.  These things will probably increase your odds of making it work:
+  1. open a shell
+  2. cd to Ariadne, and source the env_developer
+  3. run the tool 'distribute_source'
+  3. run eclipse from the command line
+  4. give eclipse the 'scratchpad' directory as its source
+
+Be sure to run `release` after development to update what the tester sees.
+
+Do the analogous steps if you contribute as a 'tester'.  I.e. from
+the shell source env_tester instead. Also, you will need to add
+distribute_source to tester/tool, as it is currently not there.
+
diff --git a/document/install_Emacs.txt b/document/install_Emacs.txt
new file mode 100644 (file)
index 0000000..19398de
--- /dev/null
@@ -0,0 +1,45 @@
+
+System requirements:
+
+dnf install libX11-devel libXpm-devel libjpeg-devel libpng-devel libtiff-devel 
+dnf install gtk3-devel giflib-devel gnutls-devel
+dnf install ncurses-devel texinfo
+dnf install libacl-devel libattr-devel libgccjit libgccjit-devel
+
+# install and build script:
+
+cd "$REPO_HOME"/tool_shared/third_party
+mkdir -p emacs/{src,build,bin}
+
+# We sought stability, and now this. What can I say? It has 'visual-wrap-prefix-mode'.
+pushd upstream
+curl -L -O https://alpha.gnu.org/gnu/emacs/pretest/emacs-30.0.92.tar.xz
+popd
+
+tar -xf upstream/emacs-30.0.92.tar.xz -C emacs/src --strip-components=1
+
+# need to clear the environment
+env -i bash
+
+pushd emacs/src
+./configure --prefix="$REPO_HOME"/tool_shared/third_party/emacs
+
+  I gather this warning is unavaoidable?
+  "configure: WARNING: Your version of Gtk+ will have problems with"
+
+
+# replace nproc with number of processors:
+make -j$(nproc)
+
+# make install installs locally due to the `--prefix` option `./configure` above
+make install 
+make clean
+
+popd
+rm -r emacs/{src,build}
+
+# Find emacs in the emacs/in directory.  Be sure to add it to the path
+# in the tool_shared/bespoke/env file:
+#     PATH="$REPO_HOME/tool_shared/third_party/emacs/bin:$PATH"
+
+
diff --git a/document/install_IntelliJ_IDEA.txt b/document/install_IntelliJ_IDEA.txt
new file mode 100644 (file)
index 0000000..13f2570
--- /dev/null
@@ -0,0 +1,310 @@
+This file describes the local install and configuration of IntelliJ_IDEA for
+the project with the RT project skeleton.
+
+Project development has been done with ItelliJ and with Emacs. Perhaps
+someone will add more about Eclipse to the install_Eclipse.txt page.
+
+--------------------------------------------------------------------------------
+Some notes
+
+'project directory' - the directory with the .git file in it. Called
+$REPO_HOME in RT scripts. Called $PROJECT_DIR$ in IntelliJ file paths.
+
+'module directory' - for RT projects examples include
+`~/Ariadne/developer' `~/Ariadne/tester`.  These are independent build
+environments.
+
+IntelliJ automatic scanning:
+
+  When selecting `new project` or `new module` the fist time IntelliJ will
+  go off and scan directories.
+
+  My advice, ** uncheck anything it scans ** then hit next.  If you
+  don't hit next, the `new project` or `new module won't be made.
+
+IntelliJ paths on forms:
+
+  I tried using $PROJECT_DIR$ as a variable standing for the project
+  directory, as this was suggested by an AI.  However IntelliJ simply
+  made a directory with the literal variable name. Recommendation:
+  don't use it.
+
+  Also tried using $REPO_HOME, as that was defined in the environment
+  IntelliJ was run from.  Nope, the environment that idea was invoked
+  from seems to be thrown away.
+
+  `~` for the home directories does work. There is one blessing.
+
+  When a file or directory path has a blank on a form, there will be a
+  file navigator icon at the far right in the blank. It does not show
+  when the form is not scrolled all the way to the right.  The browser
+  tool starts from either `/home` or at `/` (the root of the file
+  sytem) rather than at the top of the project. 
+  It inserts absolute path names.
+
+  It seems everything is based on absolute paths, so it will be
+  interesting to see what happens when people download a repo
+  with `.imp` files in it ...
+
+A GUI bug:
+
+  There is a Gnome Linux bug where the drop down menu can stay on top no matter
+  what other window, application, or what virtual desktop a person is on.  You
+  must go back to the IDEA application window and hit <escape> to make it go
+  away.
+
+The [OK] button at the bottom of dialogs:
+
+   This closes the dialog.
+
+   To apply changes hit [Apply].
+
+   [OK] will not save what is on the dialog if [Apply] would fail, but
+   it still closes it.
+
+--------------------------------------------------------------------------------
+To install ItelliJ
+
+  Download the tar file from 
+    `https://www.jetbrains.com/idea/download/?section=linux` 
+  into the
+    `$REPO_HOME/tool_shared/third_party/upstream`
+   directory.
+
+  Expand it into 
+    `$REPO_HOME/tool_shared/third_party` 
+  
+  cd into the expanded directory, into `bin`, then `chmod u+x` and run `idea_inst`.
+
+  set the env path to include 
+    `$REPO_HOME/tool_shared/third_party/idea-IC*/bin`
+
+  The executable is called `idea`.
+
+  Consider setting a desktop short cut. Consider instead installing it in your
+  own bin directory. Easily done, just move the directory created by the tar
+  file expansion there.
+
+  I prefer a user mode install, as there is no reason this tool should need
+  admin privileges.
+
+--------------------------------------------------------------------------------
+Startup
+
+  ./tool_shared/third_party/idea-IC-243.21565.193/bin/idea &
+
+  Shows: Welcome screen
+    select "Open" as Ariadne already exists
+
+  Shows: Open File or Project Browser
+    In top dialog box put full path to project directory.
+
+    Hit [OK] at the bottom. Unlikely, but might be scrolled off the bottom of the screen.
+
+  Shows: main window
+     Appears after hitting OK from the "Open File or Project" [ok].
+
+     Has a tool bar at the top. There is a double meat hamburger menu icon
+     at the left. Hitting this will replace the top bar with a vertical
+     menu for drop down menus.
+
+     Careful, after the hamburger icon is pressed, the first drop down
+     menu instantly appears. Slide over to get the other drop downs.
+     Don't click, slide!
+
+     Under tool bar:
+       Far left is an icon bar.  Then a file browser.  And then a big box
+       describing hot keys.
+
+--------------------------------------------------------------------------------
+Configuration
+
+If you cloned the Ariadne project, the modules will already be configured, and
+also probably some of the run configuration will already be configured.
+
+If you add a project, or modules, know that is possible to go back and
+change settings, except perhaps for the Project directory, I've not tried
+that yet.
+
+It will on occasion add directories.  I have multiple language setup with
+source in javac.  Though the directory 'src' is not in the configuration,
+IntelliJ like to create it then refuse to delete it, so after configuring I
+then go back and delete it with `rmdir`. Sometimes it shows in the file
+browser though it is not there.
+
+  -------------
+  Setup Project
+  Hamburger icon > File dop-down > Project Structure > Project
+
+    select project SDK from disk:
+      ~/Ariadne/tool_shared/third_party/jdk-11
+
+  -------------
+  Setup Modules
+
+    Hamburger icon > File dop-down > Project Structure > Modules
+
+      Shows: "Project Structure" dialog
+
+       Hit the '+' option that shows at the top of the second panel. There is
+       no description of what it does. Mouse over just says 'add'.  It is
+       there with a couple of other icons.  After modules are added they will
+       be listed in this panel.
+
+       New Module.
+
+       Dialog pop-up
+
+          Name: developer
+
+          Location: This will be the project directory. As examples,
+          ~/Ariadne or ~/Mosaic.
+          
+          Dependencies, there will then be a drop down.
+
+            Sometimes is suggests the "Project SDK" at the top. If so select that.
+
+            Sometimes it allows select from disk, is so enter  ~/<project>/tool_shared/third_party/.
+
+            Other times it shows a discovered directory that is the same as
+            the one I suggest browsing to.
+
+          Careful, the module won't be made until hitting [Create] at the bottom.
+
+          As far as I can tell you can't get this panel again, rather delete and add
+          a new module if you need to change the entries.
+
+      Shows: "Project Structure" dialog, again, now the third panel with
+      information about the developer module.  Third panel shows three
+      choices: [Source] [Paths] [Dependencies]
+
+          [Sources] comming up with the source dialog is the default, but that does
+          not mean the [Sources] button has been pushed. 
+
+              With Sources there are two panels.
+
+              In second panel, on right side, the module root should show at the top.
+              Under if it lists any sources, use the button at the far right of the
+              listing to x it out anything that IntelliJ has automatically added.
+
+              The first panel now shows a file browser for the module.
+
+                Select the `javac` directory with a single click. Then, and only
+                after, look immediately the directory lists and click on [Sources] 
+
+                When the [Source] button on the sources dialog has been
+                pushed it will turn colors and gain a border when pushed. The
+                [Sources] button must be pushed, or selected source
+                directories will not be applied. Selecting a directory and
+                hitting [OK] will not save anything, and will close the
+                dialog.
+
+                "Source Folders" will now appear in the second panel. The
+                javac folder will be listed. Hhit: [apply] at the
+                bottom. [apply] will then turn colors to show that there is
+                nothing more to apply.
+
+
+          Slide over to [Paths]      
+              Copmiler Output
+                select [Use Module Compile Output Path]
+                   Output Path: $PROJECT_DIR$/developer/scratchpad
+                   Test Path: $PROJECT_DIR$/developer/test
+
+                   leave the exclude output checkbox, that means to exclude from repo
+                   and from indexing for search
+
+              hit: [apply] at the bottom
+
+          Add the `log` directory to [Resources], if you have one.
+
+          After setting 'scratchpad' as the output directory on the [paths]
+          configuration form, and leaving `scratchpad` as excluded via
+          the checkbox. You can not then on the Sources form add
+          `scratchpad` to the 'Excluded' list. Though it is excluded, it
+          does not show there.
+
+          After hitting [OK] the dialog disappears. Go back and check that everything
+          you set is there. It seems common that for some reason, perhaps the order
+          of hitting buttons, that settings are not there when going back.
+
+--------------------------------------------------------------------------------
+Integrating programs from the project
+
+    -------------
+    Local tests and tools.
+
+    This section is for adding an external tool, for example `tester/tool/make`, which
+    builds Mosaic tests.
+
+    Hamburger> Run > edit configurations
+    Shows Run/Debug configurations dialog
+       Upper left hit '+'
+       Shows drop down
+         choose [Shell Script] second from bottom
+         Shows dialog, for example:
+           Name: tester-developer make
+
+           Script Path: ~/Ariadne/env_run (better to chose with the
+             file browser tool)
+
+           Script Options: tester make
+
+           Working Directory: ~/Ariadne (location of the env source scripts
+             that env_run uses)
+
+           Environment variabls:  (none, env_run will source env_tester)
+
+           Interpreter: /bin/bash  (left to default)
+
+     For debugging to work for the tests, they need to be run with
+     java listening:
+
+       java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005 $file
+
+     I've included this in the bash wrappers made by make.
+
+  -------------
+  To add an "Application"
+
+    Humburger > Run > edit configurations
+    Shows Run/Debug configurations dialog
+       Upper left hit '+'
+       Shows drop down
+         chose [Application] first choice
+         Shows dialog, for example:
+         Name: Test_Graph_0
+
+         next line are two boxes, they are not labeled, the defaults show:
+         [ module not specified ] [ -cp no module ]
+           I selected::
+           [ java 11 SDk of 'tester' module]  [ -cp tester ]
+             This can be confusing, as the modules are 'tester' and 'developer', but
+             here it asks for an SDK! Then the next box says it wants a class path,
+             but it wants a module name!
+
+         next line one box, not labeled
+         [ main class [] ]
+           Note icon at right, it will give a list of class names, here in the tester module,
+           that have main calls, select one.
+
+         next line, again not labeled
+         [ Program Arguments ]
+           Test_Graph_0 has no arguments so I left it blank.
+
+         Working Directory: ~/Ariadne
+
+         Environment Variables:
+           Left blank because the executable itself does not make use of any. I do
+           know at this point if variables set in the environment IDEA ran in are
+           inherited.
+
+         'Modify Options' with a drop down menu. (At the top right of the configuration dialog)
+           Scan down for the `Java` section.
+           Check: 'Do not build before run'
+             (To build this example, go to the Run menu and run `tester
+             make'. Or run make directly from a console prompt. Be sure to
+             source env_tester first.)
+
+
diff --git a/document/install_Mosaic.txt b/document/install_Mosaic.txt
new file mode 100644 (file)
index 0000000..84823b3
--- /dev/null
@@ -0,0 +1,25 @@
+Mosaic - for testing
+
+  > cd $REPO_HOME/tool_shared/third_party
+  > git clone https://github.com/Thomas-Walker-Lynch/Mosaic.git
+
+ This will have already been done:
+
+    $REPO_HOME/tool_shared/bespoke/env will have:
+       export MOSAIC_HOME="$REPO_HOME/tool_shared/third_party/Mosaic/release"
+
+    $REPO_HOME/tester/tool/env, will have Mosaic
+
+    export PATH=\
+    "$REPO_HOME"/tester/tool/\
+    :"$JAVA_HOME"/bin\
+    :"$MOSAIC_HOME"\
+    :"$PATH"
+
+    export CLASSPATH=\
+    "$JAVA_HOME"/lib\
+    :"$MOSAIC_HOME"/Mosaic.jar\
+    :"$REPO_HOME"/release/"$PROJECT".jar\
+    :"$REPO_HOME"/tester/jvm/Test_"$PROJECT".jar\
+    :"$CLASSPATH"
+
diff --git a/document/install_jdk-23.txt b/document/install_jdk-23.txt
new file mode 100644 (file)
index 0000000..39ec44a
--- /dev/null
@@ -0,0 +1,15 @@
+----------------------------------------
+jdk-23
+
+  cd "$REPO_HOME/tool_shared/third_party/upstream"
+
+  # source for the 11 version used before, now upgraded to 23
+  #curl -C - -o OpenJDK11U-jdk_x64_linux_hotspot_11.0.16_8.tar.gz https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.16+8/OpenJDK11U-jdk_x64_linux_hotspot_11.0.16_8.tar.gz
+  curl -L -C - -b "oraclelicense=accept-securebackup-cookie" -O https://download.oracle.com/java/23/latest/jdk-23_linux-x64_bin.tar.gz
+
+  cd ..
+  tar -xzf upstream/jdk-23_linux-x64_bin.tar.gz
+
+  edit $REPO_HOME/tool_shared/bespoke/env, and update JAVA_HOME:
+    export JAVA_HOME="$REPO_HOME/tool_shared/third_party/jdk-23.0.1"
+
diff --git a/document/running_IDE_and_jdb_in_test_environment.txt b/document/running_IDE_and_jdb_in_test_environment.txt
new file mode 100644 (file)
index 0000000..8f45dd5
--- /dev/null
@@ -0,0 +1,62 @@
+
+This document describes how to run jdb in the test environment while also viewing source code.
+
+This is written relative to the Mosaic project, but is generally applicable.
+
+It shows invocation from a shell, and mentions emacs, but it is generally
+understood that users will do this from within their favorite IDE.
+
+In addition a reader can read this document for some general principles.
+
+1. setting the environment
+
+  The environment should be set before running the IDE. For example,
+
+  > cd Mosaic
+  > source env_tester
+  > emacs & 
+
+  (I use emacs as my IDE. You might be using a different tool.)
+
+2. location of the executable
+
+  Provided that the project administrator installed it, jdb is located in the
+  third_party tools directory. In the tester environment the variable
+  `JAVA_HOME` should hold the jdb directory path, and this should already
+  be in the `PATH`.  For example:
+
+  > echo $ENV
+  tester/tool/env
+
+  > echo $JAVA_HOME
+  /var/user_data/Thomas-developer/Mosaic/tool_shared/third_party/jdk-11
+
+  > which jdb
+  /var/user_data/Thomas-developer/Mosaic/tool_shared/third_party/jdk-11/bin/jdb
+
+3. invocation from a shell command:
+
+     jdb -sourcepath $SOURCEPATH <class_name>
+
+   The `SOURCEPATH` is assigned a value in `tester/tool/env`.  In some versions
+   of jdb there is no space between `-sourcepath` and the `$SOURCDEPATH`.  
+
+   jdb will read CLASSPATH from the environment. In contrast jdb will not read
+   `SOURCEPATH` from the environment. It must be passed as an argument.
+
+   There is a `run_jdb` script in the `tool` directory.
+
+4. invocation inside of Emacs
+
+   The file found in the RT-incommon project, developer/release/emacs/jdbx.el` holds a
+   definition for the `jdbx` command.  This command will read the SOURCEPATH
+   from the environment and run jdb in Emacs.
+
+   That file also holds the definition for a listener to the jdb `sourcepath`
+   command.
+
+
+
+
+
+
diff --git a/document/todo.txt b/document/todo.txt
new file mode 100644 (file)
index 0000000..a020818
--- /dev/null
@@ -0,0 +1,22 @@
+
+2024-12-08T04:15:24Z
+
+  rename to project-share, move subu related tools to the subu project.
+
+  2024-12-08T04:21:20Z project renaming done, though used RT-project-share, as project-share suggests sharing with projects that are not following the RT-skeleton.
+
+
+2024-12-08T04:21:35Z
+  yeah we sill need an official RT-skeleton project.  This should wait for Ariadne to
+  be available.
+
+2024-12-08T08:29:20Z
+  change the bash prompt to show the real path, or perhaps a vl of both, so
+  that when following links the prompt shows the pencil of the realdir
+
+2024-12-09T10:23:22Z
+
+  rm_na has a bug where it determines authorship based on the link target, and the link target's directory hierarchy, instead of from the link itself and the link's hierarchy.
+
+  this effects the clean_build_script, found in many projects, such as Mosaic.
+
diff --git a/document/variable_suffix_conventions.txt b/document/variable_suffix_conventions.txt
new file mode 100644 (file)
index 0000000..e3ad587
--- /dev/null
@@ -0,0 +1,31 @@
+# Suffix Conventions
+
+## Specify interface used with variable when clarification is useful
+
+- `_set`: Indicates that the variable holds a set of items.
+
+- `_list`: Used for variables that represent a list of items.
+
+- `_f`: Refers to a function.
+
+Instead of making a variable name plural, add the interface qualifier.
+
+   e.g. names ->  name_set  or name_lisst
+
+## Always a good idea to use these when working with files
+
+- `_fp`: Refers to a file path. The part after the last slash is a file name.
+
+- `_afp`: Refers to an absolute file path.
+  
+- `_dp`: Refers to a directory path. By convention, the value ends in a slash.
+
+- `_adp`: Refers to an absolute directory path. 
+
+- `_fn`: Refers to a file name. Value has no slashes.
+
+- `_dn`: Refers to a directory name. Value has no slashes.
+  
+- `_fn_base`: The file name without the last dot and subsequent characters.
+  
+- `_fn_ext`: The subsequent characters after the last dot in a file name.
diff --git a/document🖉/#how_to_use_project_directory_structure.txt# b/document🖉/#how_to_use_project_directory_structure.txt#
deleted file mode 100644 (file)
index 6c3ea4c..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-### Work Flow
-
-#### 1. Project Administrator
-
-1.1. Download the project from GitHub.
-1.2. Install the required tools.
-1.3. Explain the workflows and where things are located to project members.
-1.4. Perform Major and Minor Release administration.
-
-#### 2. Developer
-
-2.1. From the Mosaic directory, run `> source env_developer` to set up the
-     developer environment.
-2.2. Use `> make` to build the project, and `> release` to copy relevant files
-     to `$REPO_HOME/release` for testing.
-2.3. The tester will test the release candidate.
-
-#### 3. Tester
-
-3.1. From the Mosaic directory, run `> source env_tester` to set up the tester
-     environment.
-3.2. Use `> make` to build the tests, and `> shell/test_<name>` to run a test.
-     Alternatively, you can cd into one of the test directories, source the
-     environment for that test, and run it manually.
-3.3. Testing and development will likely iterate until the release candidate is
-     ready to be turned into a versioned release.
-
-#### 4. Major Release
-
-4.1. The release candidate is located in the `$REPO_HOME/release` directory and
-     has passed testing.
-4.2. Check that the program `$REPO_HOME/tool_shared/bespoke/version` outputs the
-     correct information. If necessary, modify it.
-4.3. A new branch is created in the project for the release, named
-     `release_v<n>.0`, where `v<n>.0` is the version number from the `version`
-     program. The minor version number is set to zero (`.0`), and it is assumed
-     that this will be the case after each major release.
-4.4. Rename the release directory to `$REPO_HOME/release_v<n>.0`, and create a
-     new empty `$REPO_HOME/release` directory. The new empty release directory
-     can be used by developers who download the project and make local edits, as
-     the build scripts target this directory.
-
-#### 5. Minor Release
-
-If urgent changes need to be made to the most recent major release, these edits
-should be made on the corresponding major release branch. The developer makes
-the edits, and the tester tests the release candidate as usual. The `version`
-program is updated. Once the release candidate is finalized, rename the
-directory to `release_v<n>.<m>`, where `<m>` is the minor version number. If
-needed, merge the changes into the `core_developer_branch`.
-
----
-
-### Tips:
-
-- If you are acting in multiple roles (e.g., developer, tester, and project
-  administrator), keep separate terminal shells open for each role. This way,
-  the environment will remain correctly configured for the tasks related to
-  each role.
diff --git a/document🖉/Java_import_as_alternative.txt b/document🖉/Java_import_as_alternative.txt
deleted file mode 100644 (file)
index dda2904..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-Java has long been criticized for its lack of support for `import as`, despite
-years of requests and proposals.
-
-The Java platform’s approach to aliasing issues relies on using fully qualified
-names, which poses challenges given the length of package names, especially when
-they include reversed domain names.
-
-Because `Mosaic` is used to help with testing and is not part of the project
-being tested, when aliasing conflicts arise, it is typically the `Mosaic` identifiers
-that need to be fully qualified. Such a renamed identifier can exceed 34
-characters!
-
-One proposal to get around this was to use an `In` class where the members were
-class extensions of imported classes.  Then all imports would have the prefix `In.`.
-However, this did not work out because constructors are not
-inherited, and Java’s restrictions on `final` classes prevent the use of
-`LocalClass extends ImportClass {}` to give no names to classes.
-
-Another proposal was to use the `alias` project on GitHub, which offers an XML-based
-approach to aliasing. However, it introduces complexities, as it requires XML
-configurations to be supplied to the compiler, adding setup overhead. Perhaps
-another tool could create these.
-
-We studied a preprocessing proposal where `import as` statements would be
-replaced with fully qualified names before compilation. However, this approach
-changes the tool flow for users and would require additional steps to ensure
-`jdb` points to the original source files rather than intermediate files, which
-complicates debugging. For both this proposal and the prior, we wanted to avoid
-joining the world of java tool development.
-
-So we have a simple solution, it is not ideal, but it is not bad.  We prefix
-the string `Mosaic_` to the front of all the class names in the Mosaic library.
-As a shop we are adopting this convention for all packaged java code.
diff --git a/document🖉/Pencil_Suffix.html b/document🖉/Pencil_Suffix.html
deleted file mode 100644 (file)
index f0cbe01..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="UTF-8">
-  <meta name="viewport" content="width=device-width, initial-scale=1.0">
-  <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
-  <title>Pencil Suffix</title>
-  <style>
-    html {
-      font-size: 16px;
-    }
-
-    body {
-      font-family: 'Noto Sans JP', Arial, sans-serif;
-      background-color: hsl(0, 0%, 0%);
-      color: hsl(42, 100%, 80%);
-      padding: 2rem;
-      margin: 0;
-    }
-
-    .page {
-      padding: 1.25rem;
-      margin: 1.25rem auto;
-      max-width: 46.875rem;
-      background-color: hsl(0, 0%, 0%);
-      box-shadow: 0 0 0.625rem hsl(42, 100%, 50%);
-    }
-
-    ul, li {
-      font-size: 1rem;
-      list-style-type: none;
-    }
-
-    li::before {
-      content: "• ";
-      margin-right: 0.3125rem;
-    }
-
-    li {
-      margin-bottom: 0.3125rem;
-    }
-
-    .description {
-      margin-left: 0.625rem;
-      color: hsl(42, 100%, 75%);
-    }
-
-    code {
-      font-family: 'Courier New', Courier, monospace;
-      background-color: hsl(0, 0%, 25%);
-      color: hsl(42, 100%, 90%);
-      padding: 0.125rem 0.25rem;
-      border-radius: 0.1875rem;
-      font-size: 90%;
-    }
-
-    h1 {
-      text-align: center;
-      color: hsl(42, 100%, 84%);
-      text-transform: uppercase;
-      margin-bottom: 1.25rem;
-    }
-
-    h2 {
-      color: hsl(42, 100%, 84%);
-      text-transform: uppercase;
-      margin-top: 2.5rem;
-    }
-
-    p {
-      color: hsl(42, 100%, 90%);
-      margin-bottom: 1.25rem;
-      text-align: justify;
-    }
-  </style>
-</head>
-<body>
-  <div class="page">
-<h1>The Pencil Suffix and Authored Files</h1>
-
-<h3>How to Use the Pencil Suffix</h3>
-
-  <p>The pencil suffix is a Unicode character, 🖉, that is placed as the last character of a filename or directory name. It signifies that the file, or contents of a so named directory, are uniquely authored and should not be deleted or rebuilt by clean scripts or build scripts. The pencil suffix also serves as a communication tool among team members as to where in the project edits should be inserted.</p>
-
-  <strong>Two methods for marking a file as authored:</strong>
-  <ul>
-    <li><em>Directory with Pencil Suffix:</em> This method marks all contents within said directory sub-tree as being authored.</li>
-    <li><em>File Name Last Character as Pencil:</em> This directly marks the file itself as authored.</li>
-  </ul>
-</li>
-
-  <p>The recommended method to mark files as authored is to place them in a directory, where the name of said directory ends with the pencil symbol. Directly marked files will then be exceptional cases.</p>
-
-<h3>Pencil suffix definition</h3>
-
-<p>By definition, the pencil suffix designates files or directories as <em>leaves in the build tree</em>. Hence, by definition pencil suffix files are not built by tools. It is a corollary that these files are the primary sources of material and serve as points of entry for edits by authors, whether human or AI. Thus we refer to these leaves as <span class='term'>authored</span>. At the time of writing, this definition is maintained by contract with the programers, along with the assistance of the <code>rm_na</code> tool.</p>
-
-<h3>Replace <code>rm</code> with <code>rm_na</code> in scripts</h3>
-
-<p>The <code>rm_na</code> command is a modified version of the standard <code>rm</code> command, and it refuses to delete files marked as being authored.  This is true whether the file is marked as authored with a pencil suffix or is found in a directory tree marked as such.</p>
-  
-<p>Use <code>rm_na</code> in place of <code>rm</code>  in scripts that clean, build, or otherwise manipulate project files.</p>
-
-<p>While <code>rm_na</code> offers a safeguard, the pencil suffix itself does not enforce permissions. Users can still manually delete 🖉-marked files using <code>rm</code>, and roqque builds can overwrite them.</p>
-
-<h3>Pencil suffix and editablity</h3>
-
-<p>The pencil suffix does not inherently restrict or permit editing. A file without the pencil suffix that has write permissions can also be edited; however, such edits are at risk of being overwritten or lost during builds or cleans. While lack of a pencil suffix on a file, or inclusion in such a directory, does not prevent a file from being edited - it does mean that it might not be advisable to edit such a file. Conversely, it is intended that a file marked as authored can be edited without fear of the edits being overwritten. Hence pencil suffix files are the appropriate places to insert edits into a project. In this sense the pencil suffix does indicate a file is 'editable'; however, this is not the definition of the pencil suffix, rather it is a property that emerges from the definition.</p>
-
-<h3>Symbolic Links</h3>
-
-<p>Symbolic links, while facilitating access to authored files, are independent entities that merely point to targets. As such, the link itself is not an authored file, and its lifecycle is separate from the content it references. A symbolic link can be created or deleted without impacting the authored content it points to.</p>
-
-<p>Because symbolic links are not authored entities, they do not carry pencil suffixes, even when their targets do. This distinction ensures that the pencil suffix remains specific to authored files and directories, highlighting their preservation within the project.</p>
-
-<p>However, this lack of pencil suffix on links can create confusion. Users viewing symbolic links in a directory listing may overlook authored content if they rely solely on the link names. The intended edit points within the project might not be apparent unless users examine the targets of the links.  </p>
-
-<p>To mitigate potential confusion, file browsers or editors that visually distinguish symbolic links from regular files are highly valuable. These tools help users identify links at a glance, preserving the clarity of authored content within the project structure.  </p>
-
-
-
-
-<h3>Hard Links</h3>
-
-<p> Among multiple hard links, none is distinguished as being the primary file link. Hence, should a hard link point at an authored file, and that hardlink is not in a directory that already identifies it as an authored file, it should have the pencil suffix. It is the only option available, because in general we can not know the order of deletion of the hard links, and thus do not know which will be the last one that should not be deleted. Hard links are strange beasts that should be avoided for many other reasons as well.</p>
-
-
-<h3>Future direction</h3>
-
-<p>In the future we hope for tighter integration with the OS, perhaps through use of sub-users (see the subu project), or through a property based file system. For now it is a communication tool, one which is strengthened through use of the <code>rm_na</code> command.</p>
-
-
-</body>
-</html>
diff --git a/document🖉/RT_C_control_structure.html b/document🖉/RT_C_control_structure.html
deleted file mode 100644 (file)
index 8ecc937..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="UTF-8">
-  <meta name="viewport" content="width=device-width, initial-scale=1.0">
-  <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
-  <title>RT C coding conventions</title>
-  <style>
-    body {
-      font-family: 'Noto Sans JP', Arial, sans-serif;
-      background-color: hsl(0, 0%, 0%);
-      color: hsl(42, 100%, 80%);
-      padding: 2rem;
-    }
-    .page {
-      padding: 3rem;
-      margin: 1.25rem auto;
-      max-width: 46.875rem;
-      background-color: hsl(0, 0%, 0%);
-      box-shadow: 0 0 0.625rem hsl(42, 100%, 50%);
-    }
-    h1 {
-      font-size: 1.5rem;
-      text-align: center;
-      color: hsl(42, 100%, 84%);
-      text-transform: uppercase;
-      margin-top: 1.5rem;
-    }
-    h2 {
-      font-size: 1.25rem;
-      color: hsl(42, 100%, 84%);
-      text-align: center;
-      margin-top: 2rem;
-    }
-    h3 {
-      font-size: 1.125rem;
-      color: hsl(42, 100%, 75%);
-      margin-top: 1.5rem;
-    }
-    p, li {
-      color: hsl(42, 100%, 90%);
-      text-align: justify;
-      margin-bottom: 1rem;
-    }
-    code {
-      font-family: 'Courier New', Courier, monospace;
-      background-color: hsl(0, 0%, 25%);
-      padding: 0.125rem 0.25rem;
-      color: hsl(42, 100%, 90%);
-    }
-  </style>
-</head>
-
-<body>
-<div class="page">
-  <header>
-    <h1>Reasoning Technology (RT) C file control structure</h1>
-    <p>© 2024 Thomas Walker Lynch - All Rights Reserved.</p>
-  </header>
-
-  <h2>Introduction</h2>
-
-  <p>This document summarizes some of the coding conventions used in RT C projects. Discussed here are conventions for integrated header designs, ad hoc namespaces, and a structured approach to source file extensions. The document also outlines the associated build process using a standardized makefile.</p>
-
-  <h2>Header file integration</h2>
-
-  <p>RT C projects adopt an innovative approach by integrating headers directly into source files. This ensures consistency between interfaces and implementations, eliminating mismatches. Each file contains both an interface and an implementation section, gated by preprocessor directives.</p>
-
-  <p>Each RT C source file integrates its header directly into the source file. This locality makes header content easier to maintain as everything is found in a single file. It also eliminates the need to maintain two files for each module.</p>
-
-  <h3>Each file has two sections</h3>
-  <ul>
-    <li><strong>Interface section:</strong> Contains declarations, macros, and <code>#includes</code> needed for the interface. Ensures consistency by defining the interface exactly once, even when the file is included multiple times.</li>
-    <li><strong>Implementation section:</strong> Contains function definitions and additional includes needed for the implementation. This section is compiled only when the file is used as an implementation.</li>
-  </ul>
-
-  <p>Each section is turned on and off with the CPP macro <code>FACE</code>.</p>
-
-  <h3>Example</h3>
-  <pre><code>
-// If not an FACE, then an IMPLEMENTATION
-#ifndef FACE
-  #define MyModule·IMPLEMENTATION
-  // Ensures included files are processed for their interfaces.
-  #define FACE
-#endif
-
-// Define the interface exactly once.
-#ifndef MyModule·FACE
-#define MyModule·FACE
-  // Interface-only includes go here.
-  void MyModule·function();
-#endif
-
-#ifdef MyModule·IMPLEMENTATION
-  // Additional includes for implementation go here.
-  #include <stdio.h>
-  void MyModule·function() {
-    printf("Hello, World!\n");
-  }
-#endif
-  </code></pre>
-
-  <h3>Explanation</h3>
-  <p>The example above demonstrates the structure and purpose of each block:</p>
-  <p><strong>First block:</strong> Ensures that the file operates correctly based on the value of <code>FACE</code>. If <code>FACE</code> is undefined, it defines <code>MyModule·IMPLEMENTATION</code> to enable the implementation section and sets <code>FACE</code> to ensure subsequent includes process interface sections.</p>
-  <p><strong>Second block:</strong> Defines the interface, including declarations and interface-specific includes. The <code>#ifndef MyModule·FACE</code> macro ensures the interface is defined exactly once, regardless of how many times the file is included.</p>
-  <p><strong>Third block:</strong> Contains implementation-specific includes and function definitions. Guarded by <code>MyModule·IMPLEMENTATION</code>, it is only included when compiling the implementation.</p>
-  <p>Interface includes are placed in the interface block, ensuring they are available wherever the interface is used. Implementation includes are isolated in the implementation block, minimizing unnecessary dependencies in other files.</p>
-
-  <h2>Namespace conventions</h2>
-  <p>RT projects use ad hoc namespaces to maintain clarity and prevent naming conflicts. This is achieved by prefixing exported identifiers with a module-specific name followed by the <code>·</code> (cdot) character.</p>
-
-  <h3>Conventions</h3>
-  <ul>
-    <li><strong>Prefix:</strong> The module name serves as the prefix, ensuring all identifiers are unique across the program.</li>
-    <li><strong>Separator:</strong> The <code>·</code> character visually separates the prefix from the identifier name, maintaining readability and avoiding conflicts.</li>
-  </ul>
-
-  <h3>Example</h3>
-  <pre><code>
-void Server·run();
-  </code></pre>
-
-  <h2>Source file extensions</h2>
-  <p>RT projects use standardized extensions to distinguish between library and command-line interface (CLI) source files:</p>
-  <ul>
-    <li><strong><code>.lib.c</code>:</strong> Files implementing library functions.</li>
-    <li><strong><code>.cli.c</code>:</strong> Files implementing command-line tools.</li>
-  </ul>
-
-  <p>The <code>.lib.c</code> files compile into libraries, while <code>.cli.c</code> files compile into standalone executables. The makefile processes these files automatically, ensuring a clear separation of functionality.</p>
-
-  <h3>Build process</h3>
-  <p>The build process follows these steps:</p>
-  <ol>
-    <li><strong>Dependency generation:</strong> Run <code>make dependency</code> to create dependencies. This step is only required when the dependency structure changes.</li>
-    <li><strong>Compilation:</strong> Run <code>make cli</code> to compile CLI sources and link them against the library. The makefile automatically manages targets and dependencies.</li>
-  </ol>
-
-  <h2>Benefits</h2>
-  <ul>
-    <li><strong>Consistency:</strong> Integrated headers ensure interface and implementation are always in sync.</li>
-    <li><strong>Modularity:</strong> Each file encapsulates its interface and implementation, reducing coupling.</li>
-    <li><strong>Clarity:</strong> Ad hoc namespaces and standardized extensions improve readability and organization.</li>
-    <li><strong>Efficiency:</strong> The makefile automates builds, minimizing errors and streamlining development.</li>
-  </ul>
-
-  <h2>Conclusion</h2>
-  <p>This document outlines the conventions and practices for writing and building RT C projects. By integrating headers, adopting namespaces, and standardizing extensions, RT ensures its projects are robust, modular, and easy to maintain.</p>
-</div>
-</body>
-</html>
diff --git a/document🖉/RT_code_format.org b/document🖉/RT_code_format.org
deleted file mode 100644 (file)
index 9555151..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-#+TITLE: RT Code Format Guide
-#+AUTHOR: Thomas Walker Lynch and Aion
-#+DATE: 2025-02-28
-#+OPTIONS: toc:nil
-
-* Introduction
-
-The RT Code Format enforces clear and consistent rules for formatting and naming in code, prioritizing readability, maintainability, and logical structure. The rules focus on indentation, naming conventions, enclosure spacing, and unique handling of commas.
-
-* Indentation
-
-- Code blocks are indented by **two spaces per level**.
-- No additional alignment-based indentation (e.g., aligning operators or parameters to columns).
-
-* Naming Conventions
-
-1. **Namespaces and types** use *PascalCase*.
-2. **Functions and variables** use *snake_case*.
-3. **Ordered collections** use `_list` as a suffix (e.g., `node_list`), even if the language does not have a `List` type.
-
-Examples:
-#+BEGIN_SRC c
-mouse_count
-test_LabelList_0  // Function testing LabelList (a class/type)
-Thomas_Walker_Lynch
-#+END_SRC
-
-* Binary Operators
-
-  There is no space around multiply and divide binary operators.
-
-  There is one space around all other operators.
-
-* Assignment
-
-   Two types of assignment:
-
-   1. sampling assignment, `=` inside `if`, `while`, etc.
-   2. single statement assignment 
-
-   No space around sampling assignment `=`.
-
-Example:
-#+BEGIN_SRC c
-if( result=some_condition() ){  // Sampling assignment, no spaces
-  process(result);
-}
-a = b + c;  // Regular assignment with spaces
-#+END_SRC
-
-* Newline
-
-There is never space before an unquoted newline.
-
-
-* Bracketed Phrases
-
-In token processing, a *bracketed phrase* is the text starting from an opening bracket up to its matching closing bracket, including both brackets. We treat any of `(...)`, `{...}`, `[...]`, or `<...>` as “brackets”. Bracketed phrases are detected purely at the token level—no higher-level grammar or semantics are considered.
-
-** Examples
-- **`if(x){...}` vs. `f(x){...}`**  
-  Both share the same token-level structure: an identifier followed by `(x)` and then `{...}`.  
-- **`sin(3x)`**  
-  Has one bracketed phrase `(3x)`, where `3x` is the “contents” and `()` is the “container.”
-
-** Nesting
-
-1. **Innermost Bracketed Phrase**  
-   Contains *no other* bracketed phrase inside it. Due to adjacency, multiple innermost bracketed phrases can occur.
-
-2. **Outermost Bracketed Phrase**  
-   An outermost bracketed phrase is one that is not itself contained in any other bracketed phrase.
-
-3. **Contained (Inner) Bracketed Phrase**  
-   A bracketed phrase located within the contents of another bracketed phrase (the *outer* one).
-
-4. **Bracketed Phrase with Nesting**  
-   A bracketed phrase that contains one or more bracketed phrases.
-
-   A bracketed phrase is “with nesting” only if it contains at least one inner bracketed phrase. In other words, non-quoted bracket punctuated phrases occurs inside the contents — not just commas or other punctuation.
-
-
-**Examples**
-In `sin(f(x) + (a))`, the phrase `(x)` is contained in `(f(x) (a))`, which in turn is contained in `sin(...)`.  `(a) is also contained in`(f(x) (a))`. `(x)` is innermost.
-`(a)` is also innermost.
-
-**Open Bracketed Phrases
-
-A bracketed phrase is **open** if it’s missing a matching opening or closing bracket.
-
-- **Open on the Right**: Has unmatched opening brackets (e.g., `(` but no `)`).
-- **Open on the Left**: Has unmatched closing brackets (e.g., `)` but no preceding `(`).
-
-** 1D Box Analogy
-
-Think of each bracketed phrase like a **1D CSS box**:
-
-- The **opening and closing brackets** are the “borders.”
-- **Margin (outside)**: By default, bracketed phrases have *no extra spacing* around their borders—unless another rule (like an operator or adjacent token) requires space.  
-  Example: `f()()` is valid with no space, but `f () ()` is not.
-- **Padding (inside)**: If a bracketed phrase is both  
-  1) outermost on a line,  
-  2) has nesting,  
-  3) and is not a Lisp s-expression,  
-  then place **one space** immediately after the opening bracket and **one space** before the closing bracket.
-
-** Adjacency
-When two bracketed phrases appear side by side (like `)(` or `}{`), there is *no space* between them.
-
-**Line by Line
-
-We apply bracket formatting on a line by line basis, thus not searching for opening, closing, or containing brackets beyond the given line of analysis.
-
-
-* Commas
-
-The **comma rule** is one of the most distinctive and recognizable aspects of RT Code Formatting.
-
-1. **One space before the comma** (e.g., `a ,b`).
-2. **No space after the comma** (e.g., `a ,b`).
-3. **Line break before the comma when breaking lines**, but **no line break after the comma**.
-
-Examples:
-#+BEGIN_SRC c
-a
-,b
-#+END_SRC
-
-When function arguments get too long, break lines as follows:
-#+BEGIN_SRC c
-result = some_function(
-   first_argument
-  ,second_argument_with_longer_name
-  ,third_argument
-);
-#+END_SRC
-
-✔ **This ensures consistency and maintains readability.**  
-
-* Short Stuff Rule
-
-For **`if`**, **`for`**, and **`while`** statements that introduce a *single-line* clause with no `else`, if the **condition and clause together fit within one line (≤40 characters)**, they should **remain on a single line without braces**.
-
-Example:
-#+BEGIN_SRC c
-if( x > 0 ) return x;
-while( has_next() ) process_next();
-#+END_SRC
-
diff --git a/document🖉/Workflow.org b/document🖉/Workflow.org
deleted file mode 100644 (file)
index e028946..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-* Project Workflow
-
-
-This document outlines the responsibilities of different roles in the project and the release process.
-
-** 1. Project Administrator
-   - Download the project from GitHub.
-   - Install the required tools.
-   - Explain workflows and file locations to project members.
-   - Manage Major and Minor Releases.
-
-** 2. Developer
-   - From the `Mosaic/` directory, run:
-     #+begin_src sh
-       source env_developer
-     #+end_src
-     to set up the developer environment.
-   - Build the project:
-     #+begin_src sh
-       make
-     #+end_src
-   - Copy relevant files to the release directory:
-     #+begin_src sh
-       release
-     #+end_src
-   - The tester will evaluate the release candidate.
-
-** 3. Tester
-   - From the `Mosaic/` directory, set up the testing environment:
-     #+begin_src sh
-       source env_tester
-     #+end_src
-   - Build and run tests:
-     #+begin_src sh
-       make
-       shell/test_<name>
-     #+end_src
-   - Alternatively, change to a test directory, source its environment, and run tests manually.
-   - The development and testing process will iterate until the release candidate is ready for an official release.
-
-** 4. Major Release
-   - The release candidate is in `$REPO_HOME/release` and has passed testing.
-   - Verify that `$REPO_HOME/tool_shared/bespoke/version` outputs the correct version information. Modify it if necessary.
-   - Create a new branch named `release_v<n>.0` where `<n>` is the major version.
-   - Rename the release directory to `$REPO_HOME/release_v<n>.0` and create a new empty `$REPO_HOME/release/` directory.
-
-** 5. Minor Release
-   - Urgent changes to a major release are made on its corresponding branch.
-   - The developer makes edits, and the tester evaluates the release candidate as usual.
-   - The `version` program is updated.
-   - Rename the release directory to `release_v<n>.<m>`, where `<m>` is the minor version.
-   - Merge changes into `core_developer_branch` if necessary.
-
-** 6. Tips
-   - If acting in multiple roles (developer, tester, admin), keep separate terminal shells for each role to avoid misconfigurations.
diff --git a/document🖉/bash_name_of_script.txt b/document🖉/bash_name_of_script.txt
deleted file mode 100644 (file)
index 3637574..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-
-Bash is inconsistent about returning the name of the running script in
-all scenarios (sourced, executed directly, from with in a function called
-by another function).
-
-1.
-
-BASH_SOURCE[0] was used because $0 did not work with sourced scripts (a
-fact that is leveraged for detecting when in a sourced script).
-
-2.
-
-However, this did not work in all scenarios:
-
-  read -r -d '' script_afp_string <<'EOF'
-  realpath "${BASH_SOURCE[0]}" 2>/dev/null
-  EOF
-
-    script_afp(){
-      eval "$script_afp_string"
-    }
-
-  export script_afp_string
-  export -f script_afp
-
-When `script_afp` was exported, used in another file, and used within a function
-in that other file, it reported `environment` for the script name at
-BASH_SOURCE[0].  In various call scenarios the actual script name appears at
-BASH_SOURCE[1] or even at BASH_SOURCE[2].  
-
-3.
-
-As a stable alternative to having a script_afp function, place this line
-at the top of scripts that use the `script_XX` functions, or at the top
-of all scripts:
-
-  script_afp=realpath "${BASH_SOURCE[0]}"
-
-Then use $script_afp as a string within other functions. It will have stable
-value no matter the call structure.
diff --git a/document🖉/directory_naming.html b/document🖉/directory_naming.html
deleted file mode 100644 (file)
index d409362..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="UTF-8">
-  <meta name="viewport" content="width=device-width, initial-scale=1.0">
-  <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
-
-  <title>Directory Structure Description</title>
-<style>
-  html {
-    font-size: 16px; /* This will be the base for rem units */
-  }
-
-  body {
-    font-family: 'Noto Sans JP', Arial, sans-serif;
-    background-color: hsl(0, 0%, 0%);
-    color: hsl(42, 100%, 80%);
-    padding: 2rem;
-    margin: 0;
-  }
-
-  .page {
-    padding: 1.25rem; /* 20px */
-    margin: 1.25rem auto; /* 20px */
-    max-width: 46.875rem; /* 750px */
-    background-color: hsl(0, 0%, 0%);
-    box-shadow: 0 0 0.625rem hsl(42, 100%, 50%); /* 10px */
-  }
-
-  ul, li {
-    font-size: 1rem; /* Keeping default font size */
-    list-style-type: none;
-  }
-
-  li::before {
-    content: "📁 ";
-    margin-right: 0.3125rem; /* 5px */
-  }
-
-  li {
-    margin-bottom: 0.3125rem; /* 5px */
-  }
-
-  .description {
-    margin-left: 0.625rem; /* 10px */
-    color: hsl(42, 100%, 75%);
-  }
-
-  code {
-    font-family: 'Courier New', Courier, monospace;
-    background-color: hsl(0, 0%, 25%);
-    color: hsl(42, 100%, 90%);
-    padding: 0.125rem 0.25rem; /* 2px 4px */
-    border-radius: 0.1875rem; /* 3px */
-    font-size: 90%;
-  }
-
-  h1 {
-    text-align: center;
-    color: hsl(42, 100%, 84%);
-    text-transform: uppercase;
-    margin-bottom: 1.25rem; /* 20px */
-  }
-
-  h2 {
-    color: hsl(42, 100%, 84%);
-    text-transform: uppercase;
-    margin-top: 2.5rem; /* 40px */
-  }
-
-  p {
-    color: hsl(42, 100%, 90%);
-    margin-bottom: 1.25rem; /* 20px */
-    text-align: justify;
-  }
-</style>
-
-</head>
-<body>
-
-  <div class="page">
-    <h1>Directory Naming</h1>
-
-    <h2>Reference</h2>
-
-    <ul>
-      <li>Mosaic/<span class="description">aka REPO_HOME, top level owned by the project administrator.</span></li>
-      <ul>
-        <li>developer/ <span class="description">Workspace for the developer. Has the source code, build scripts, and development-specific tools.</span></li>
-        <ul>
-          <li>deprecated/ <span class="description">Files and older versions being viewed, perhaps part of a refactoring effort.</span></li>
-          <li>document/ <span class="description">Documentation on developing and building the project.</span></li>
-          <li>javac/ <span class="description">Java source files for compilation.</span></li>
-          <li>jvm/ <span class="description">Compiled Java bytecode files for the project, typically a jar for a Java project.</span></li>
-          <li>scratchpad/ <span class="description">Temporary storage typically for intermediate files created during build.</span></li>
-          <li>shell/ <span class="description">Shell scripts intended to be part of the project release. (These are not tools.)</span></li>
-          <li>tool/ <span class="description">Tools created by the developer, used for development tasks.</span></li>
-        </ul>
-        <li>document/ <span class="description">General documentation about the project.</span></li>
-        <li>release/ <span class="description">Release candidate for testing. Becomes the release on the release branch.</span></li>
-        <li>scratchpad/ <span class="description">Temporary storage for project administration tasks.</span></li>
-        <li>tester/ <span class="description">Workspace for the tester. Has the test bench, tests, and test scripts.</span></li>
-        <ul>
-          <li>document/ <span class="description">Test-specific documentation.</span></li>
-          <li>javac/ <span class="description">The tests of the test bench sources.</span></li>
-          <li>tool/ <span class="description">Tools needed for testing and managing the test environment.</span></li>
-        </ul>
-        <li>tool/ <span class="description">Project administration specific tools.</span></li>
-        <li>tool_shared/ <span class="description">Tools shared across project roles.</span></li>
-        <ul>
-          <li>bespoke/ <span class="description">Shared tools developed within this project.</span></li>
-          <li>customized/ <span class="description">Modified versions of third-party tools adapted for the project.</span></li>
-          <li>document/ <span class="description">Documentation related to shared tools and setup.</span></li>
-          <li>third_party/ <span class="description">Shared tools sourced from third-party vendors or open-source projects. These have their own independent licenses,</span></li>
-        </ul>
-        <li>LICENSE.txt <span class="description">The project license detailing usage and distribution terms.</span></li>
-        <li>README.md <span class="description">A general overview and introduction to the project.</span></li>
-      </ul>
-    </ul>
-
-    <h2>Name origin and rationale</h2>
-
-    <p>Developers and project administrators typically do not employ a semantic system for
-      naming directories, but more commonly use conventional placeholder
-      names. The intended purpose of files in a directory with a placeholder
-      name then must be inferred from experience or inspection of the files, or
-      learned from documents or other people.</p>
-
-    <p>For example, a directory named <code>exe/</code> probably derives its name from the
-      fact that the contained files have their executable permission bit set;
-      however, such a directory will not contain all such files.  There might
-      even be some files in an <code>exe/</code> directory that do not have their
-      executable permission bit set. The two concepts being an <code>exe/</code> file
-      (i.e. being a file in an <code>exe/</code> directory) and being an executable file
-      are not identical. The actual intended meaning of being an <code>exe/</code> file
-      will sometimes be that the contained files are applications available to a
-      user, or that they are tools available for use in a project.
-    </p>
-
-    <p>The directory names in this project resulted from an exploration of a
-      property-based file system. In such a system a number of files and
-      agents are defined. Then we can ask questions about their relationships.
-      Files with a relationship to the developer are collected, and this
-      becomes the <code>developer/</code> directory. In a similar manner we get the
-      directories, <code>tester/</code>, and <code>javac/</code>.  In this latter case the
-      agent is a compiler rather than a role.
-      </p>
-      
-    <p>When attempting to apply the <code>is-for</code> property in practice it
-      became apparent that using this sole property was insufficient.  Consider
-      the directories <code>deprecated/</code> and <code>scratchpad/</code>. There is no
-      <em>Mr. Deprecated</em> or <em>Mr. Scratchpad</em> who the contained
-      files are for. (And this conclusion is not for the lack of trying. Even
-      mythological beings did not suffice as agents.) Rather than being for an
-      agent, the files collected in such a directory have in common a state of
-      being that was imposed upon them by decree.  Perhaps the developer, has
-      decreed that a file is now deprecated, or a build script has decreed that
-      it is a scratchpad file. Such decrees are typically more dynamic than the
-      relationship properties. Also, these properties are disconnected from the
-      contents of the file.  When, for example, a file has the property of being
-      for the java compiler, we gain some information about its contents. In the
-      universe of possible messages sent through a file, such a file will
-      contain text that is proposed to be java syntax conforming. In contrast,
-      when we learn that a file is <code>deprecated/</code> we gain no
-      information about the contents of the file, because any file can
-      be <code>deprecated</code>, independent of its contents.
-      </p>
-
-    <p>To understand a directory name within this system, one can imagine
-      reading said name as part of a sentence that integrates the
-      property. Consider two property names: <code>is-a</code>
-      and <code>is-for</code>. For example, "Each file in
-      the <code>document/</code> directory <code>is-a</code> document," or "Each
-      file in the <code>developer/</code> directory <code>is-for</code> the
-      developer."  Although the property name is not carried over from the
-      property based file system to the conventional file system, we can
-      typically infer what it must have been. (It is beyond the scope of
-      discussion here, but in actuality, property based file system collections
-      are defined by predicates. Each predicate is given a file's properties and
-      relationships as arguments, then resolves to true if and only if the file
-      belongs to the collection. Now wouldn't that be interesting if we instead
-      derived a probability?)
-    </p>
-
-    <p>It is uncommon for a property value to be plural. While it is not
-      disallowed, it rarely occurs in practice. This is true independent of
-      whether we are discussing a relationship property or a state
-      property. Hence when we make a file collection based on a shared property,
-      then carry that over as a directory name in a conventional file system,
-      the resulting directory name will often be singular.  This pattern can be
-      observed in the case of the <code>document/</code> directory, as shown in
-      the prior paragraph.
-    </p>
-
-  </div>
-
-</body>
-</html>
diff --git a/document🖉/directory_structure.org b/document🖉/directory_structure.org
deleted file mode 100644 (file)
index 09d9994..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-* Project Directory Structure
-  This document explains the naming conventions and layout of the project files.
-
-** 1. Top-Level Directory (`Mosaic/`)
-   - aka `$REPO_HOME`, managed by the project administrator.
-
-** 2. Developer Workspace (`Mosaic/developer/`)
-   - Contains source code, build scripts, and development tools.
-
-   - **Subdirectories:**
-     - `deprecated/` :: Contains old or refactored files.
-     - `document/` :: Developer-specific documentation.
-     - `javac/` :: Java source code.
-     - `jvm/` :: Compiled Java bytecode (JARs, class files).
-     - `scratchpad/` :: Temporary workspace for builds.
-     - `shell/` :: Executable scripts.
-     - `tool/` :: Development utilities.
-
-** 3. Testing Workspace (`Mosaic/tester/`)
-   - Contains test benches, test scripts, and test documentation.
-
-   - **Subdirectories:**
-     - `document/` :: Documentation related to testing.
-     - `javac/` :: Java-based test sources.
-     - `tool/` :: Utilities for testing.
-
-** 4. General Documentation (`Mosaic/document/`)
-   - Contains overall project documentation.
-
-** 5. Release Directory (`Mosaic/release/`)
-   - The release candidate directory before finalization.
-
-** 6. Shared Tools (`Mosaic/tool_shared/`)
-   - Tools shared across different roles.
-
-   - **Subdirectories:**
-     - `bespoke/` :: Custom-built project tools.
-     - `customized/` :: Modified third-party tools.
-     - `document/` :: Tool-related documentation.
-     - `third_party/` :: Unmodified third-party tools.
-
-** 7. Other Files
-   - `LICENSE.txt` :: Project licensing information.
-   - `README.md` :: Project introduction.
-
-** 8. Naming Conventions
-   - Directory names are chosen based on logical properties.
-   - For example, `developer/` contains files *for* the developer.
-   - Plural names are generally avoided unless necessary.
-   - This system minimizes ambiguity and helps developers understand structure intuitively.
diff --git a/document🖉/enclosure_old.org b/document🖉/enclosure_old.org
deleted file mode 100644 (file)
index eb57955..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-* Bracketed Phrases
-
-Here we refer to token processing.  A 'bracketed phrase' is all the text found when parsing from the point an opening bracket is found, up until the point that the matching closing bracket is found. The phrase includes the enclosing brackets.
-
-We generalize the concept of bracketed phrase to include the following punctuation,
-and that found in between.
-
-- `(...)` (parentheses)
-- `{...}` (braces)
-- `[...]` (square brackets)
-- `<...>` (angle brackets)
-
-The '(', ')', '{', '}', '[', ']', '<', '>' are said to be parenthetical punctuation. 
-
-Generally a bracketed phrase is discovered at the token parsing level, as such it does not take into account any of the syntax nor semantics of the grammar that will be applied to the token stream later.
-
-However, there are special cases where higher level context will be required. Namely when distinguishing between angle brackets and magnitude comparisons, and for Lisp sexprs, as explained further below.
-
-Hence `if(x){ ...'  is formatted just as `f(x){...`  because in both cases the spacing is determined at the token level. That `if` is a statement, or that `f` is a function, has no baring because at the token level they are both merely identifiers.
-
-**As a Container**
-
-A bracketed phrase has enclosing matching punctuation known as the 'container'. Inside the containing punctuation are zero or more text characters, which are known as the 'contents'.  For example `sin(3x)` has one bracketed phrase,  `(3x)`, and the contents of this phrase is `3x`.  The container is `()`.
-
-**Nesting**
-
-1. **Kernel Bracketed Phrase**  
-
-   A bracketed phrase that does not contain another bracketed phrase.
-
-2. **Contained Bracketed Phrase**
-
-   A contained bracketed phrase is found in the contents of another bracketed phrase.
-
-   So for example, in `sin(f(x))` the bracketed phrase `(x)`  is contained in the bracketed phrase '(f(x))`, so it is a 'contained bracketed phrase'.
-
-   A contained bracketed phrase is also called an 'inner bracketed phrase'.
-
-3. **Outer Bracketed Phrase**
-
-   If a bracketed phrase is contained in another bracketed phrase, then the
-   contained bracketed phrase is the 'inner bracked phrase' and the bracked phase
-   that contains it is the 'outer bracketed phrase'.
-
-   An outer bracketed phrase that is not contained by any other bracketed phrase
-   is the 'outermost' bracketed phrase.  So for example, given `( a (b (c) (d)) )`
-   There are two kernels, '(c)' and '(d)'.  Those two kernels appear in the outer bracketed phrase of `(b (c) (d))`, that phrase is contained in the outer bracketed phrase of `( a (b (c) (d)) )`.
-
-4. **Bracketed Phrase with Nesting**
-
-   A bracketed phrase with nesting is one that contains at least one other bracketed phrase. It need not matter which matching punctuation the inner bracketed phrases have.
-
-   It follows that an Outer Bracketed Phrase will always be a Bracketed Phrase with Nesting.
-
-   It follows that a Kernel Bracketed Phrase is never a Bracketed Phrase with Nesting.
-
-4. **Outermost Bracketed Phrase**
-
-   An outermost bracketed phrase is not contained in any other bracketed phrase.
-
-
-**Open** 
-
-An open bracketed phrase is one on that has no matching closing punctuation, or not matching opening punctuation.
-
-An open on the lines bracketed phrase, is one that is open when tokenizing only the given line.
-
-1. **Open on Right on a Line**  
-   - If one or more unmatched on the line opening bracket punctuation appears, these are said to form an 'open on the right bracketed phrase'.
-   - These are treated as though they were closed on the right on the line.
-
-2. **Open on Left Enclosures**  
-   - If one or more unmatched on the line closing bracket punctuation appears, these are said to form an 'open on the left enclosure'.
-   - These are treated as though they were opened on the left on the line.
-
-**1D Box Analogy**
-
-Consider an bracketed phrase to be like a 1D CSS box. In this analogy consider the bracketed phrase punctuation to be the box borders. Then in the language of CSS we have margin, which is space outside of the bracketed phrase punctuation, and padding, which is space immediately inside the bracketed phrase punctuation.
-
-**Bracketed Phrase Margin**
-
-All bracketed phrases have no native spaces on the outside. I say 'native' because
-some other rules might add a space, such as operator rules, or bracketed phrase followed
-by an identifier.  Hence `f()()`  is correct while `f () ()` would be incorrect because both of the kernel bracketed phrases have spacing outside of them.  On the other hand `(a) + (b)` is correct, because the plus operator has spaces around it.
-
-**Bracketed Phrase Padding**
-
-When a bracketed phrase is both:  a) a bracketed phrase with nesting  AND b) an outermost bracketed phrase on the line, then: It receives one space after the opening bracket unless it is a Lisp sexpr, and one space before the closing bracket.
-
-There is no other case where a native space is placed after the opening bracket, or placed before the closing bracket.
-
-** Adjacency
-
-   When two separate bracketed phrases appear side by side.  There is no space between them.
-
-
-* Examples of Bracketed Phrase Formatting
-
-**Flat Bracketed Phrases (No Padding)**
-#+BEGIN_SRC c
-result = function_call(param1 ,param2);
-value = (uint32_t)(3 + 4*5);
-#+END_SRC
-
-**Nested Bracketed Phrases (Only an outer type of nested bracketed phrase receives padding)**
-#+BEGIN_SRC c
-if( (x == 3 || y < 5) && z ){
-  process_data();
-}
-#+END_SRC
-
-#+BEGIN_SRC c
-data.set( map.get(key) );
-#+END_SRC
-
-#+BEGIN_SRC c
-if( (index().compareTo(BigInteger.valueOf(array.size() - 1))) == 0 ){
-  execute_action();
-}
-#+END_SRC
-
-#+BEGIN_SRC c
-( a (b (c)) )
-#+END_SRC
-
-#+BEGIN_SRC c
-if(
-   ( condition_one() && condition_two() ) 
-){
-   execute_action();
-}
-#+END_SRC
-
-#+BEGIN_SRC c
-(uint32_t)(3 + 4*5)
-#+END_SRC
-
-#+BEGIN_SRC c
-data.set( map.get(key) );
-#+END_SRC
diff --git a/document🖉/how_to_use_project_directory_structure.txt b/document🖉/how_to_use_project_directory_structure.txt
deleted file mode 100644 (file)
index 6c3ea4c..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-### Work Flow
-
-#### 1. Project Administrator
-
-1.1. Download the project from GitHub.
-1.2. Install the required tools.
-1.3. Explain the workflows and where things are located to project members.
-1.4. Perform Major and Minor Release administration.
-
-#### 2. Developer
-
-2.1. From the Mosaic directory, run `> source env_developer` to set up the
-     developer environment.
-2.2. Use `> make` to build the project, and `> release` to copy relevant files
-     to `$REPO_HOME/release` for testing.
-2.3. The tester will test the release candidate.
-
-#### 3. Tester
-
-3.1. From the Mosaic directory, run `> source env_tester` to set up the tester
-     environment.
-3.2. Use `> make` to build the tests, and `> shell/test_<name>` to run a test.
-     Alternatively, you can cd into one of the test directories, source the
-     environment for that test, and run it manually.
-3.3. Testing and development will likely iterate until the release candidate is
-     ready to be turned into a versioned release.
-
-#### 4. Major Release
-
-4.1. The release candidate is located in the `$REPO_HOME/release` directory and
-     has passed testing.
-4.2. Check that the program `$REPO_HOME/tool_shared/bespoke/version` outputs the
-     correct information. If necessary, modify it.
-4.3. A new branch is created in the project for the release, named
-     `release_v<n>.0`, where `v<n>.0` is the version number from the `version`
-     program. The minor version number is set to zero (`.0`), and it is assumed
-     that this will be the case after each major release.
-4.4. Rename the release directory to `$REPO_HOME/release_v<n>.0`, and create a
-     new empty `$REPO_HOME/release` directory. The new empty release directory
-     can be used by developers who download the project and make local edits, as
-     the build scripts target this directory.
-
-#### 5. Minor Release
-
-If urgent changes need to be made to the most recent major release, these edits
-should be made on the corresponding major release branch. The developer makes
-the edits, and the tester tests the release candidate as usual. The `version`
-program is updated. Once the release candidate is finalized, rename the
-directory to `release_v<n>.<m>`, where `<m>` is the minor version number. If
-needed, merge the changes into the `core_developer_branch`.
-
----
-
-### Tips:
-
-- If you are acting in multiple roles (e.g., developer, tester, and project
-  administrator), keep separate terminal shells open for each role. This way,
-  the environment will remain correctly configured for the tasks related to
-  each role.
diff --git a/document🖉/install_Eclipse.txt b/document🖉/install_Eclipse.txt
deleted file mode 100644 (file)
index 167d14e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-
-The project is originally configured to be used with Emacs as an IDE. The tools
-can all be run from a shell inside of emacs. Even when using an IDE what the
-shell environment scripts and tools do should be understood.
-
-I have added a working IntelliJ IDEA configuration, so if you want a modern IDE
-it is probably best to go with this. See ItelliJ_IDEA.txt in this directory.
-
-I've not run Eclipse on the project, if you do, perhaps you can update the notes
-here.  These things will probably increase your odds of making it work:
-  1. open a shell
-  2. cd to Ariadne, and source the env_developer
-  3. run the tool 'distribute_source'
-  3. run eclipse from the command line
-  4. give eclipse the 'scratchpad' directory as its source
-
-Be sure to run `release` after development to update what the tester sees.
-
-Do the analogous steps if you contribute as a 'tester'.  I.e. from
-the shell source env_tester instead. Also, you will need to add
-distribute_source to tester/tool, as it is currently not there.
-
diff --git a/document🖉/install_Emacs.txt b/document🖉/install_Emacs.txt
deleted file mode 100644 (file)
index 19398de..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-
-System requirements:
-
-dnf install libX11-devel libXpm-devel libjpeg-devel libpng-devel libtiff-devel 
-dnf install gtk3-devel giflib-devel gnutls-devel
-dnf install ncurses-devel texinfo
-dnf install libacl-devel libattr-devel libgccjit libgccjit-devel
-
-# install and build script:
-
-cd "$REPO_HOME"/tool_shared/third_party
-mkdir -p emacs/{src,build,bin}
-
-# We sought stability, and now this. What can I say? It has 'visual-wrap-prefix-mode'.
-pushd upstream
-curl -L -O https://alpha.gnu.org/gnu/emacs/pretest/emacs-30.0.92.tar.xz
-popd
-
-tar -xf upstream/emacs-30.0.92.tar.xz -C emacs/src --strip-components=1
-
-# need to clear the environment
-env -i bash
-
-pushd emacs/src
-./configure --prefix="$REPO_HOME"/tool_shared/third_party/emacs
-
-  I gather this warning is unavaoidable?
-  "configure: WARNING: Your version of Gtk+ will have problems with"
-
-
-# replace nproc with number of processors:
-make -j$(nproc)
-
-# make install installs locally due to the `--prefix` option `./configure` above
-make install 
-make clean
-
-popd
-rm -r emacs/{src,build}
-
-# Find emacs in the emacs/in directory.  Be sure to add it to the path
-# in the tool_shared/bespoke/env file:
-#     PATH="$REPO_HOME/tool_shared/third_party/emacs/bin:$PATH"
-
-
diff --git a/document🖉/install_IntelliJ_IDEA.txt b/document🖉/install_IntelliJ_IDEA.txt
deleted file mode 100644 (file)
index 13f2570..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-This file describes the local install and configuration of IntelliJ_IDEA for
-the project with the RT project skeleton.
-
-Project development has been done with ItelliJ and with Emacs. Perhaps
-someone will add more about Eclipse to the install_Eclipse.txt page.
-
---------------------------------------------------------------------------------
-Some notes
-
-'project directory' - the directory with the .git file in it. Called
-$REPO_HOME in RT scripts. Called $PROJECT_DIR$ in IntelliJ file paths.
-
-'module directory' - for RT projects examples include
-`~/Ariadne/developer' `~/Ariadne/tester`.  These are independent build
-environments.
-
-IntelliJ automatic scanning:
-
-  When selecting `new project` or `new module` the fist time IntelliJ will
-  go off and scan directories.
-
-  My advice, ** uncheck anything it scans ** then hit next.  If you
-  don't hit next, the `new project` or `new module won't be made.
-
-IntelliJ paths on forms:
-
-  I tried using $PROJECT_DIR$ as a variable standing for the project
-  directory, as this was suggested by an AI.  However IntelliJ simply
-  made a directory with the literal variable name. Recommendation:
-  don't use it.
-
-  Also tried using $REPO_HOME, as that was defined in the environment
-  IntelliJ was run from.  Nope, the environment that idea was invoked
-  from seems to be thrown away.
-
-  `~` for the home directories does work. There is one blessing.
-
-  When a file or directory path has a blank on a form, there will be a
-  file navigator icon at the far right in the blank. It does not show
-  when the form is not scrolled all the way to the right.  The browser
-  tool starts from either `/home` or at `/` (the root of the file
-  sytem) rather than at the top of the project. 
-  It inserts absolute path names.
-
-  It seems everything is based on absolute paths, so it will be
-  interesting to see what happens when people download a repo
-  with `.imp` files in it ...
-
-A GUI bug:
-
-  There is a Gnome Linux bug where the drop down menu can stay on top no matter
-  what other window, application, or what virtual desktop a person is on.  You
-  must go back to the IDEA application window and hit <escape> to make it go
-  away.
-
-The [OK] button at the bottom of dialogs:
-
-   This closes the dialog.
-
-   To apply changes hit [Apply].
-
-   [OK] will not save what is on the dialog if [Apply] would fail, but
-   it still closes it.
-
---------------------------------------------------------------------------------
-To install ItelliJ
-
-  Download the tar file from 
-    `https://www.jetbrains.com/idea/download/?section=linux` 
-  into the
-    `$REPO_HOME/tool_shared/third_party/upstream`
-   directory.
-
-  Expand it into 
-    `$REPO_HOME/tool_shared/third_party` 
-  
-  cd into the expanded directory, into `bin`, then `chmod u+x` and run `idea_inst`.
-
-  set the env path to include 
-    `$REPO_HOME/tool_shared/third_party/idea-IC*/bin`
-
-  The executable is called `idea`.
-
-  Consider setting a desktop short cut. Consider instead installing it in your
-  own bin directory. Easily done, just move the directory created by the tar
-  file expansion there.
-
-  I prefer a user mode install, as there is no reason this tool should need
-  admin privileges.
-
---------------------------------------------------------------------------------
-Startup
-
-  ./tool_shared/third_party/idea-IC-243.21565.193/bin/idea &
-
-  Shows: Welcome screen
-    select "Open" as Ariadne already exists
-
-  Shows: Open File or Project Browser
-    In top dialog box put full path to project directory.
-
-    Hit [OK] at the bottom. Unlikely, but might be scrolled off the bottom of the screen.
-
-  Shows: main window
-     Appears after hitting OK from the "Open File or Project" [ok].
-
-     Has a tool bar at the top. There is a double meat hamburger menu icon
-     at the left. Hitting this will replace the top bar with a vertical
-     menu for drop down menus.
-
-     Careful, after the hamburger icon is pressed, the first drop down
-     menu instantly appears. Slide over to get the other drop downs.
-     Don't click, slide!
-
-     Under tool bar:
-       Far left is an icon bar.  Then a file browser.  And then a big box
-       describing hot keys.
-
---------------------------------------------------------------------------------
-Configuration
-
-If you cloned the Ariadne project, the modules will already be configured, and
-also probably some of the run configuration will already be configured.
-
-If you add a project, or modules, know that is possible to go back and
-change settings, except perhaps for the Project directory, I've not tried
-that yet.
-
-It will on occasion add directories.  I have multiple language setup with
-source in javac.  Though the directory 'src' is not in the configuration,
-IntelliJ like to create it then refuse to delete it, so after configuring I
-then go back and delete it with `rmdir`. Sometimes it shows in the file
-browser though it is not there.
-
-  -------------
-  Setup Project
-  Hamburger icon > File dop-down > Project Structure > Project
-
-    select project SDK from disk:
-      ~/Ariadne/tool_shared/third_party/jdk-11
-
-  -------------
-  Setup Modules
-
-    Hamburger icon > File dop-down > Project Structure > Modules
-
-      Shows: "Project Structure" dialog
-
-       Hit the '+' option that shows at the top of the second panel. There is
-       no description of what it does. Mouse over just says 'add'.  It is
-       there with a couple of other icons.  After modules are added they will
-       be listed in this panel.
-
-       New Module.
-
-       Dialog pop-up
-
-          Name: developer
-
-          Location: This will be the project directory. As examples,
-          ~/Ariadne or ~/Mosaic.
-          
-          Dependencies, there will then be a drop down.
-
-            Sometimes is suggests the "Project SDK" at the top. If so select that.
-
-            Sometimes it allows select from disk, is so enter  ~/<project>/tool_shared/third_party/.
-
-            Other times it shows a discovered directory that is the same as
-            the one I suggest browsing to.
-
-          Careful, the module won't be made until hitting [Create] at the bottom.
-
-          As far as I can tell you can't get this panel again, rather delete and add
-          a new module if you need to change the entries.
-
-      Shows: "Project Structure" dialog, again, now the third panel with
-      information about the developer module.  Third panel shows three
-      choices: [Source] [Paths] [Dependencies]
-
-          [Sources] comming up with the source dialog is the default, but that does
-          not mean the [Sources] button has been pushed. 
-
-              With Sources there are two panels.
-
-              In second panel, on right side, the module root should show at the top.
-              Under if it lists any sources, use the button at the far right of the
-              listing to x it out anything that IntelliJ has automatically added.
-
-              The first panel now shows a file browser for the module.
-
-                Select the `javac` directory with a single click. Then, and only
-                after, look immediately the directory lists and click on [Sources] 
-
-                When the [Source] button on the sources dialog has been
-                pushed it will turn colors and gain a border when pushed. The
-                [Sources] button must be pushed, or selected source
-                directories will not be applied. Selecting a directory and
-                hitting [OK] will not save anything, and will close the
-                dialog.
-
-                "Source Folders" will now appear in the second panel. The
-                javac folder will be listed. Hhit: [apply] at the
-                bottom. [apply] will then turn colors to show that there is
-                nothing more to apply.
-
-
-          Slide over to [Paths]      
-              Copmiler Output
-                select [Use Module Compile Output Path]
-                   Output Path: $PROJECT_DIR$/developer/scratchpad
-                   Test Path: $PROJECT_DIR$/developer/test
-
-                   leave the exclude output checkbox, that means to exclude from repo
-                   and from indexing for search
-
-              hit: [apply] at the bottom
-
-          Add the `log` directory to [Resources], if you have one.
-
-          After setting 'scratchpad' as the output directory on the [paths]
-          configuration form, and leaving `scratchpad` as excluded via
-          the checkbox. You can not then on the Sources form add
-          `scratchpad` to the 'Excluded' list. Though it is excluded, it
-          does not show there.
-
-          After hitting [OK] the dialog disappears. Go back and check that everything
-          you set is there. It seems common that for some reason, perhaps the order
-          of hitting buttons, that settings are not there when going back.
-
---------------------------------------------------------------------------------
-Integrating programs from the project
-
-    -------------
-    Local tests and tools.
-
-    This section is for adding an external tool, for example `tester/tool/make`, which
-    builds Mosaic tests.
-
-    Hamburger> Run > edit configurations
-    Shows Run/Debug configurations dialog
-       Upper left hit '+'
-       Shows drop down
-         choose [Shell Script] second from bottom
-         Shows dialog, for example:
-           Name: tester-developer make
-
-           Script Path: ~/Ariadne/env_run (better to chose with the
-             file browser tool)
-
-           Script Options: tester make
-
-           Working Directory: ~/Ariadne (location of the env source scripts
-             that env_run uses)
-
-           Environment variabls:  (none, env_run will source env_tester)
-
-           Interpreter: /bin/bash  (left to default)
-
-     For debugging to work for the tests, they need to be run with
-     java listening:
-
-       java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005 $file
-
-     I've included this in the bash wrappers made by make.
-
-  -------------
-  To add an "Application"
-
-    Humburger > Run > edit configurations
-    Shows Run/Debug configurations dialog
-       Upper left hit '+'
-       Shows drop down
-         chose [Application] first choice
-         Shows dialog, for example:
-         Name: Test_Graph_0
-
-         next line are two boxes, they are not labeled, the defaults show:
-         [ module not specified ] [ -cp no module ]
-           I selected::
-           [ java 11 SDk of 'tester' module]  [ -cp tester ]
-             This can be confusing, as the modules are 'tester' and 'developer', but
-             here it asks for an SDK! Then the next box says it wants a class path,
-             but it wants a module name!
-
-         next line one box, not labeled
-         [ main class [] ]
-           Note icon at right, it will give a list of class names, here in the tester module,
-           that have main calls, select one.
-
-         next line, again not labeled
-         [ Program Arguments ]
-           Test_Graph_0 has no arguments so I left it blank.
-
-         Working Directory: ~/Ariadne
-
-         Environment Variables:
-           Left blank because the executable itself does not make use of any. I do
-           know at this point if variables set in the environment IDEA ran in are
-           inherited.
-
-         'Modify Options' with a drop down menu. (At the top right of the configuration dialog)
-           Scan down for the `Java` section.
-           Check: 'Do not build before run'
-             (To build this example, go to the Run menu and run `tester
-             make'. Or run make directly from a console prompt. Be sure to
-             source env_tester first.)
-
-
diff --git a/document🖉/install_Mosaic.txt b/document🖉/install_Mosaic.txt
deleted file mode 100644 (file)
index 84823b3..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-Mosaic - for testing
-
-  > cd $REPO_HOME/tool_shared/third_party
-  > git clone https://github.com/Thomas-Walker-Lynch/Mosaic.git
-
- This will have already been done:
-
-    $REPO_HOME/tool_shared/bespoke/env will have:
-       export MOSAIC_HOME="$REPO_HOME/tool_shared/third_party/Mosaic/release"
-
-    $REPO_HOME/tester/tool/env, will have Mosaic
-
-    export PATH=\
-    "$REPO_HOME"/tester/tool/\
-    :"$JAVA_HOME"/bin\
-    :"$MOSAIC_HOME"\
-    :"$PATH"
-
-    export CLASSPATH=\
-    "$JAVA_HOME"/lib\
-    :"$MOSAIC_HOME"/Mosaic.jar\
-    :"$REPO_HOME"/release/"$PROJECT".jar\
-    :"$REPO_HOME"/tester/jvm/Test_"$PROJECT".jar\
-    :"$CLASSPATH"
-
diff --git a/document🖉/install_jdk-23.txt b/document🖉/install_jdk-23.txt
deleted file mode 100644 (file)
index 39ec44a..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-----------------------------------------
-jdk-23
-
-  cd "$REPO_HOME/tool_shared/third_party/upstream"
-
-  # source for the 11 version used before, now upgraded to 23
-  #curl -C - -o OpenJDK11U-jdk_x64_linux_hotspot_11.0.16_8.tar.gz https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.16+8/OpenJDK11U-jdk_x64_linux_hotspot_11.0.16_8.tar.gz
-  curl -L -C - -b "oraclelicense=accept-securebackup-cookie" -O https://download.oracle.com/java/23/latest/jdk-23_linux-x64_bin.tar.gz
-
-  cd ..
-  tar -xzf upstream/jdk-23_linux-x64_bin.tar.gz
-
-  edit $REPO_HOME/tool_shared/bespoke/env, and update JAVA_HOME:
-    export JAVA_HOME="$REPO_HOME/tool_shared/third_party/jdk-23.0.1"
-
diff --git a/document🖉/running_IDE_and_jdb_in_test_environment.txt b/document🖉/running_IDE_and_jdb_in_test_environment.txt
deleted file mode 100644 (file)
index 8f45dd5..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-
-This document describes how to run jdb in the test environment while also viewing source code.
-
-This is written relative to the Mosaic project, but is generally applicable.
-
-It shows invocation from a shell, and mentions emacs, but it is generally
-understood that users will do this from within their favorite IDE.
-
-In addition a reader can read this document for some general principles.
-
-1. setting the environment
-
-  The environment should be set before running the IDE. For example,
-
-  > cd Mosaic
-  > source env_tester
-  > emacs & 
-
-  (I use emacs as my IDE. You might be using a different tool.)
-
-2. location of the executable
-
-  Provided that the project administrator installed it, jdb is located in the
-  third_party tools directory. In the tester environment the variable
-  `JAVA_HOME` should hold the jdb directory path, and this should already
-  be in the `PATH`.  For example:
-
-  > echo $ENV
-  tester/tool/env
-
-  > echo $JAVA_HOME
-  /var/user_data/Thomas-developer/Mosaic/tool_shared/third_party/jdk-11
-
-  > which jdb
-  /var/user_data/Thomas-developer/Mosaic/tool_shared/third_party/jdk-11/bin/jdb
-
-3. invocation from a shell command:
-
-     jdb -sourcepath $SOURCEPATH <class_name>
-
-   The `SOURCEPATH` is assigned a value in `tester/tool/env`.  In some versions
-   of jdb there is no space between `-sourcepath` and the `$SOURCDEPATH`.  
-
-   jdb will read CLASSPATH from the environment. In contrast jdb will not read
-   `SOURCEPATH` from the environment. It must be passed as an argument.
-
-   There is a `run_jdb` script in the `tool` directory.
-
-4. invocation inside of Emacs
-
-   The file found in the RT-incommon project, developer/release/emacs/jdbx.el` holds a
-   definition for the `jdbx` command.  This command will read the SOURCEPATH
-   from the environment and run jdb in Emacs.
-
-   That file also holds the definition for a listener to the jdb `sourcepath`
-   command.
-
-
-
-
-
-
diff --git a/document🖉/todo.txt b/document🖉/todo.txt
deleted file mode 100644 (file)
index a020818..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-
-2024-12-08T04:15:24Z
-
-  rename to project-share, move subu related tools to the subu project.
-
-  2024-12-08T04:21:20Z project renaming done, though used RT-project-share, as project-share suggests sharing with projects that are not following the RT-skeleton.
-
-
-2024-12-08T04:21:35Z
-  yeah we sill need an official RT-skeleton project.  This should wait for Ariadne to
-  be available.
-
-2024-12-08T08:29:20Z
-  change the bash prompt to show the real path, or perhaps a vl of both, so
-  that when following links the prompt shows the pencil of the realdir
-
-2024-12-09T10:23:22Z
-
-  rm_na has a bug where it determines authorship based on the link target, and the link target's directory hierarchy, instead of from the link itself and the link's hierarchy.
-
-  this effects the clean_build_script, found in many projects, such as Mosaic.
-
diff --git a/document🖉/variable_suffix_conventions.txt b/document🖉/variable_suffix_conventions.txt
deleted file mode 100644 (file)
index e3ad587..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-# Suffix Conventions
-
-## Specify interface used with variable when clarification is useful
-
-- `_set`: Indicates that the variable holds a set of items.
-
-- `_list`: Used for variables that represent a list of items.
-
-- `_f`: Refers to a function.
-
-Instead of making a variable name plural, add the interface qualifier.
-
-   e.g. names ->  name_set  or name_lisst
-
-## Always a good idea to use these when working with files
-
-- `_fp`: Refers to a file path. The part after the last slash is a file name.
-
-- `_afp`: Refers to an absolute file path.
-  
-- `_dp`: Refers to a directory path. By convention, the value ends in a slash.
-
-- `_adp`: Refers to an absolute directory path. 
-
-- `_fn`: Refers to a file name. Value has no slashes.
-
-- `_dn`: Refers to a directory name. Value has no slashes.
-  
-- `_fn_base`: The file name without the last dot and subsequent characters.
-  
-- `_fn_ext`: The subsequent characters after the last dot in a file name.
diff --git a/tool/env b/tool/env
new file mode 100644 (file)
index 0000000..a318fa0
--- /dev/null
+++ b/tool/env
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# input guards
+
+  env_must_be="tool_shared/bespoke🖉/env"
+  error=false
+  if [ "$ENV" != "$env_must_be" ]; then
+    echo "$(script_fp):: error: must be run in the $env_must_be environment"
+    error=true
+  fi
+  if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+    echo "$script_afp:: This script must be sourced, not executed."
+    error=true
+  fi
+  if $error; then exit 1; fi
+
+export PATH=\
+"$REPO_HOME"/tool_shared/bespoke🖉/\
+:"$PATH"
+
+# expose sneaky hidden files
+alias ls="ls -a"
+
+# some feedback to show all went well
+
+  export PROMPT_DECOR="$PROJECT"_administrator
+  export ENV=$(script_fp)
+  echo ENV "$ENV"
+
+
+
+
diff --git a/tool_shared/bespoke/cat_w_fn b/tool_shared/bespoke/cat_w_fn
new file mode 100755 (executable)
index 0000000..3308525
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# Check if at least one file is provided
+if [ $# -eq 0 ]; then
+  echo "Usage: $(script_fp) <filename1> [filename2] ..."
+  exit 1
+fi
+
+# Loop through all the provided files
+for file in "$@"; do
+  # Check if the file exists
+  if [ ! -f "$file" ]; then
+    echo "Error: File '$file' not found!"
+    continue
+  fi
+
+  # Print 80 dashes
+  printf '%.0s-' {1..80}
+  echo
+
+  # Print the filename and a colon
+  echo "$file:"
+
+  # Print the contents of the file
+  cat "$file"
+
+  # Print a newline for spacing between files
+  echo
+done
diff --git a/tool_shared/bespoke/env b/tool_shared/bespoke/env
new file mode 100644 (file)
index 0000000..4fa561b
--- /dev/null
@@ -0,0 +1,65 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+  echo "$script_afp:: This script must be sourced, not executed."
+  exit 1
+fi
+
+# --------------------------------------------------------------------------------
+# project definition
+
+# actual absolute director path for this script file
+
+  script_adp(){
+    dirname "$script_afp"
+  }
+
+# assume this script is located  $REPO_HOME/tools_shared/bespoke and work backwards
+# to get $REPO_HOME, etc.
+
+  REPO_HOME=$(dirname "$(dirname "$(script_adp)")")
+  echo REPO_HOME "$REPO_HOME"
+
+  PROJECT=$(basename "$REPO_HOME")
+  echo PROJECT "$PROJECT"
+
+  # set the prompt decoration to the name of the project
+  PROMPT_DECOR=$PROJECT
+
+# --------------------------------------------------------------------------------
+# The project administrator sets up the following tools for all roles to use:
+#
+  export JAVA_HOME="$REPO_HOME/tool_shared/third_party/jdk-11"
+
+# --------------------------------------------------------------------------------
+# the following functions are provided for other scripts to use.
+# at the top of files that make use of these functions put the following line:
+#  script_afp=$(realpath "${BASH_SOURCE[0]}")
+#
+
+  ## script's filename
+  script_fn(){
+    basename "$script_afp"
+  }
+
+  ## script's dirpath relative to $REPO_HOME
+  script_fp(){
+    realpath --relative-to="${REPO_HOME}" "$script_afp"
+  }
+
+  ## script's dirpath relative to $REPO_HOME
+  script_dp(){
+    dirname "$(script_fp)"
+  }
+
+# --------------------------------------------------------------------------------
+# Exports
+# Bash has no 'closure' hence when exporting a function, one must also export all the pieces.
+# do not export script_afp
+
+  export REPO_HOME PROJECT PROMPT_DECOR
+  export -f script_adp script_fn script_dp script_fp
+
+  export ENV=$(script_fp)
+  echo ENV "$ENV"
+
diff --git a/tool_shared/bespoke/githolder b/tool_shared/bespoke/githolder
new file mode 100755 (executable)
index 0000000..49fb12b
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/env /bin/bash
+
+# Description: Descends from $1, or pwd, looking for empty directories and adds a `.githolder` to them.
+# does not descend into hidden directories.
+
+# examples:
+#   > git_holder
+#   > git_holder --dry-run
+
+set -e
+
+find_empty_dirs() {
+  local dir="$1"
+  local dry_run="$2"
+
+  # Skip `.git` specifically
+  if [[ "$(basename "$dir")" == ".git" ]]; then
+    return
+  fi
+
+  # Check if the directory is empty (including hidden files, excluding `.` and `..`)
+  if [[ -z $(find "$dir" -mindepth 1 -maxdepth 1 -print -quit) ]]; then
+    if [[ "$dry_run" == "true" ]]; then
+      echo "Dry-run: Would add .githolder in $dir"
+    else
+      echo "Adding .githolder to $dir"
+      touch "$dir/.githolder"
+    fi
+  else
+    # Recurse into subdirectories
+    for subdir in "$dir"/*/ "$dir"/.[!.]/; do
+      if [[ -d "$subdir" && "$subdir" != "$dir/.[!.]/" ]]; then
+        find_empty_dirs "$subdir" "$dry_run"
+      fi
+    done
+  fi
+}
+
+# Default parameters
+dry_run="false"
+target_dir="."
+
+# Parse arguments
+while [[ $# -gt 0 ]]; do
+  case "$1" in
+    --dry-run)
+      dry_run="true"
+      shift
+      ;;
+    *)
+      if [[ -d "$1" ]]; then
+        target_dir="$1"
+        shift
+      else
+        echo "Invalid argument: $1 is not a directory"
+        exit 1
+      fi
+      ;;
+  esac
+done
+
+# Run the function
+find_empty_dirs "$target_dir" "$dry_run"
diff --git a/tool_shared/bespoke/version b/tool_shared/bespoke/version
new file mode 100755 (executable)
index 0000000..04237c4
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# 2024-11-21 fits project skeleton convention
+echo v3.0
+
diff --git a/tool_shared/bespoke/vl b/tool_shared/bespoke/vl
new file mode 100755 (executable)
index 0000000..2c968d3
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+# vl 'vertical list'
+
+# Check if the command is provided
+if [ -z "$1" ]; then
+  echo "Usage: vl <command> [args...]"
+  exit 1
+fi
+
+# Capture the command and its arguments
+cmd=$1
+shift
+
+# Run the command with the remaining arguments and replace colons or spaces with newlines
+"$cmd" "$@" | tr ' :' '\n'
+
+exit 0
diff --git a/tool_shared/bespoke🖉/cat_w_fn b/tool_shared/bespoke🖉/cat_w_fn
deleted file mode 100755 (executable)
index 3308525..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-
-# Check if at least one file is provided
-if [ $# -eq 0 ]; then
-  echo "Usage: $(script_fp) <filename1> [filename2] ..."
-  exit 1
-fi
-
-# Loop through all the provided files
-for file in "$@"; do
-  # Check if the file exists
-  if [ ! -f "$file" ]; then
-    echo "Error: File '$file' not found!"
-    continue
-  fi
-
-  # Print 80 dashes
-  printf '%.0s-' {1..80}
-  echo
-
-  # Print the filename and a colon
-  echo "$file:"
-
-  # Print the contents of the file
-  cat "$file"
-
-  # Print a newline for spacing between files
-  echo
-done
diff --git a/tool_shared/bespoke🖉/env b/tool_shared/bespoke🖉/env
deleted file mode 100644 (file)
index 4fa561b..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
-  echo "$script_afp:: This script must be sourced, not executed."
-  exit 1
-fi
-
-# --------------------------------------------------------------------------------
-# project definition
-
-# actual absolute director path for this script file
-
-  script_adp(){
-    dirname "$script_afp"
-  }
-
-# assume this script is located  $REPO_HOME/tools_shared/bespoke and work backwards
-# to get $REPO_HOME, etc.
-
-  REPO_HOME=$(dirname "$(dirname "$(script_adp)")")
-  echo REPO_HOME "$REPO_HOME"
-
-  PROJECT=$(basename "$REPO_HOME")
-  echo PROJECT "$PROJECT"
-
-  # set the prompt decoration to the name of the project
-  PROMPT_DECOR=$PROJECT
-
-# --------------------------------------------------------------------------------
-# The project administrator sets up the following tools for all roles to use:
-#
-  export JAVA_HOME="$REPO_HOME/tool_shared/third_party/jdk-11"
-
-# --------------------------------------------------------------------------------
-# the following functions are provided for other scripts to use.
-# at the top of files that make use of these functions put the following line:
-#  script_afp=$(realpath "${BASH_SOURCE[0]}")
-#
-
-  ## script's filename
-  script_fn(){
-    basename "$script_afp"
-  }
-
-  ## script's dirpath relative to $REPO_HOME
-  script_fp(){
-    realpath --relative-to="${REPO_HOME}" "$script_afp"
-  }
-
-  ## script's dirpath relative to $REPO_HOME
-  script_dp(){
-    dirname "$(script_fp)"
-  }
-
-# --------------------------------------------------------------------------------
-# Exports
-# Bash has no 'closure' hence when exporting a function, one must also export all the pieces.
-# do not export script_afp
-
-  export REPO_HOME PROJECT PROMPT_DECOR
-  export -f script_adp script_fn script_dp script_fp
-
-  export ENV=$(script_fp)
-  echo ENV "$ENV"
-
diff --git a/tool_shared/bespoke🖉/githolder b/tool_shared/bespoke🖉/githolder
deleted file mode 100755 (executable)
index 49fb12b..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/bin/env /bin/bash
-
-# Description: Descends from $1, or pwd, looking for empty directories and adds a `.githolder` to them.
-# does not descend into hidden directories.
-
-# examples:
-#   > git_holder
-#   > git_holder --dry-run
-
-set -e
-
-find_empty_dirs() {
-  local dir="$1"
-  local dry_run="$2"
-
-  # Skip `.git` specifically
-  if [[ "$(basename "$dir")" == ".git" ]]; then
-    return
-  fi
-
-  # Check if the directory is empty (including hidden files, excluding `.` and `..`)
-  if [[ -z $(find "$dir" -mindepth 1 -maxdepth 1 -print -quit) ]]; then
-    if [[ "$dry_run" == "true" ]]; then
-      echo "Dry-run: Would add .githolder in $dir"
-    else
-      echo "Adding .githolder to $dir"
-      touch "$dir/.githolder"
-    fi
-  else
-    # Recurse into subdirectories
-    for subdir in "$dir"/*/ "$dir"/.[!.]/; do
-      if [[ -d "$subdir" && "$subdir" != "$dir/.[!.]/" ]]; then
-        find_empty_dirs "$subdir" "$dry_run"
-      fi
-    done
-  fi
-}
-
-# Default parameters
-dry_run="false"
-target_dir="."
-
-# Parse arguments
-while [[ $# -gt 0 ]]; do
-  case "$1" in
-    --dry-run)
-      dry_run="true"
-      shift
-      ;;
-    *)
-      if [[ -d "$1" ]]; then
-        target_dir="$1"
-        shift
-      else
-        echo "Invalid argument: $1 is not a directory"
-        exit 1
-      fi
-      ;;
-  esac
-done
-
-# Run the function
-find_empty_dirs "$target_dir" "$dry_run"
diff --git a/tool_shared/bespoke🖉/version b/tool_shared/bespoke🖉/version
deleted file mode 100755 (executable)
index 04237c4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-
-# 2024-11-21 fits project skeleton convention
-echo v3.0
-
diff --git a/tool_shared/bespoke🖉/vl b/tool_shared/bespoke🖉/vl
deleted file mode 100755 (executable)
index 2c968d3..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-# vl 'vertical list'
-
-# Check if the command is provided
-if [ -z "$1" ]; then
-  echo "Usage: vl <command> [args...]"
-  exit 1
-fi
-
-# Capture the command and its arguments
-cmd=$1
-shift
-
-# Run the command with the remaining arguments and replace colons or spaces with newlines
-"$cmd" "$@" | tr ' :' '\n'
-
-exit 0
diff --git a/tool_shared/document/make_rm_na.txt b/tool_shared/document/make_rm_na.txt
new file mode 100644 (file)
index 0000000..1bc6ff8
--- /dev/null
@@ -0,0 +1,17 @@
+
+1. install coreuitils
+git clone https://github.com/coreutils/coreutils.git
+cd coreutils
+
+2. add mods to remove. Note remove in the cc🖉 directory
+
+3.
+
+./bootstrap
+./configure
+make
+
+4. find rm as src/rm, move to amd64 as rm_na
+
+
+
diff --git a/tool_shared/document🖉/make_rm_na.txt b/tool_shared/document🖉/make_rm_na.txt
deleted file mode 100644 (file)
index 1bc6ff8..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-
-1. install coreuitils
-git clone https://github.com/coreutils/coreutils.git
-cd coreutils
-
-2. add mods to remove. Note remove in the cc🖉 directory
-
-3.
-
-./bootstrap
-./configure
-make
-
-4. find rm as src/rm, move to amd64 as rm_na
-
-
-
diff --git a/tool🖉/env b/tool🖉/env
deleted file mode 100644 (file)
index a318fa0..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-
-# input guards
-
-  env_must_be="tool_shared/bespoke🖉/env"
-  error=false
-  if [ "$ENV" != "$env_must_be" ]; then
-    echo "$(script_fp):: error: must be run in the $env_must_be environment"
-    error=true
-  fi
-  if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
-    echo "$script_afp:: This script must be sourced, not executed."
-    error=true
-  fi
-  if $error; then exit 1; fi
-
-export PATH=\
-"$REPO_HOME"/tool_shared/bespoke🖉/\
-:"$PATH"
-
-# expose sneaky hidden files
-alias ls="ls -a"
-
-# some feedback to show all went well
-
-  export PROMPT_DECOR="$PROJECT"_administrator
-  export ENV=$(script_fp)
-  echo ENV "$ENV"
-
-
-
-