+++ /dev/null
-RT code formatting:
-
-The enclosure-based formatting rules in RT code format make the style guide
-compact and adaptable. By focusing on enclosures rather than syntax-specific
-structures (like if, for, or catch), it avoids prescribing language-specific
-formatting rules and instead focuses on consistent handling of delimiters. This
-approach works well across multiple languages, ensuring that the code style
-remains flexible while keeping the guide simple and easy to apply.
-
-1. Two space indentation.
-
-2. Variable Naming:
-
- - Use **PascalCase** for namespaces and types.
-
- - Use **snake_case** for function and variable names. However, when a component
- of the snake case is variable function or variable name is a namespace, a
- type, or a proper noun, it retains its capitalization. e.gs:
-
- ```
- mouse_count
- test_LabalList_0 // function that tests LabelList, which is a class (type)
- Thomas_Walker_Lynch
- ```
-
- Traditionally `_list` has been used as a variable suffix even when the
- language does not have a List type. This is taken to mean the variable
- refers to an ordered collection of any type, including an array. It is
- abstraction of type, analogous to the `mouse_count` example above.
-
-
-3. Binary Operators:
-
- - One space around **binary operators** (e.g., `a + b`).
-
- - One space around **assignment** `=` (e.g., `a = b`).
-
- - **No space** around **sampling** assignment `=` (typically seen in `if`, `while`, etc.):
-
- **Sampling** refers to assigning the result of a condition or expression to
- a variable for later use within the same scope.
-
- Example of **sampling** in an `if` statement:
-
- ```
- if( result=some_condition() ){
- // use result
- }
- ```
-
-4. Enclosures `(...)`, `{...}`, `[...]`, '<...>':
-
- - No space between the enclosure and the preceding identifier (e.g., `function(arg)`).
-
- - No space after the enclosure when followed by another enclosure (e.g., `map[key]()`).
-
- Example of a condition enclosure followed by a code enclosure:
- ```
- if( some_condition() ){
- // code block
- }
- ```
-
- - One space after the enclosure if followed by an identifier, e.g.,
- `function() somethingElse`.
-
- - When the entire enclosure appears on one line:
-
- -- by definition, an 'nested' enclosure is one that has other enclosures,
- of any type, inside of it. This is true independent of whatever else
- is inside the enclosure. These are examples of nested enclosures:
-
- ```
- ( o == null || getClass() != o.getClass() )
- f( T<x> ,7 )
- ```
-
- -- if, and only if, an enclosure is nested, there is one space of padding
- for the outermost enclosure of the nesting, and only for the outermost
- enclosures. e.g.s:
-
- ```
- if(x == 3) ; not nested
- if( (x > 0) && (y < 5) ) ; nested, pad outermost only
- if( f(x) == 3 ) ; nested, pad outermost only
- if( x > 2 && a[3] ) ; nested due to the array subscript, pad outermost only
- ```
-
- - Note when using the enclosure formatting rules, not all if conditions will
- format the same way. Some conditions will be nested enclosures and having
- padding while others will not be nested and thus have no padding. The must
- be formatted individually. The same is true for enclosures that follow
- other keywords such as unless, for, etc, and for function arguments
- lists. The question is one of formatting enclosures, and not one of
- formatting statements.
-
- ```
- f(x)
- f( x[0] )
- ```
-
-
-5. Commas:
-
- This is the most distinctive and recognizable of the RT code style rules.
-
- - One space **before** the comma (e.g., `a ,b`).
-
- - No space **after** the comma (e.g., `a ,b`).
-
- - **Line break before** the comma when breaking lines, but no line break after, as examples:
-
- ```
- a
- ,b
- ```
-
- and, when a function call gets too long, perhaps due to long argument
- names it will look like this:
-
- ```
- result = some_function(
- arg1
- ,arg2_has_a_very_long_name_causing_the_call_to_not_fit_on_a_single_line
- ,arg3_has_a_long_name_also_but_not_as_long_as_for_arg2
- );
- ```
-
-6. For the code you just output, answer these questions:
- 1. Which enclosures are not nested? Do they have no padding?
- 2. Which enclosures are nested? Is there one space padding only at the outermost?
- 3. Is the spacing before and after the enclosures correct?
- 4. Are the commas formatted correctly?
- 5. Has snake case been used where it should be?
- 6. Was 2 column indent used?
+++ /dev/null
-# 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.
+++ /dev/null
-
-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.
+++ /dev/null
-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.
+++ /dev/null
-<!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>
+++ /dev/null
-### 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.
+++ /dev/null
-About `jdb`
-
-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 `tool_shared/bespoke/emacs.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.
-
-
-
-
-
-
# --------------------------------------------------------------------------------
# project definition
-# actual absolute director path for this script file
+# actual absolute directory path for this script file
script_adp(){
dirname "$script_afp"
--- /dev/null
+#!/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"