Improve code comments
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Sun, 23 Mar 2025 22:45:38 +0000 (00:45 +0200)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Sun, 23 Mar 2025 22:45:38 +0000 (00:45 +0200)
src/main/java/eu/svjatoslav/alyverkko_cli/Command.java
src/main/java/eu/svjatoslav/alyverkko_cli/commands/JoinFilesCommand.java
src/main/java/eu/svjatoslav/alyverkko_cli/configuration/ConfigurationModel.java

index 18767b9..30748ca 100644 (file)
@@ -2,9 +2,25 @@ package eu.svjatoslav.alyverkko_cli;
 
 import java.io.IOException;
 
+/**
+ * A simple interface for all subcommands used by the Älyverkko CLI.
+ * Implementing classes define a unique name (e.g., "wizard") and an
+ * {@code execute} method for the command's logic.
+ */
 public interface Command {
 
+        /**
+         * @return the subcommand's name.
+         */
         String getName();
 
+        /**
+         * Called to carry out the specific subcommand. Typically reads
+         * command-line arguments and performs the desired action.
+         *
+         * @param args arguments passed after the subcommand name.
+         * @throws IOException          if I/O operations fail.
+         * @throws InterruptedException if the operation is interrupted.
+         */
         void execute(String[] args) throws IOException, InterruptedException;
 }
index 7d4c1e6..b72b440 100644 (file)
@@ -1,6 +1,6 @@
 package eu.svjatoslav.alyverkko_cli.commands;
 
-import eu.svjatoslav.alyverkko_cli.*;
+import eu.svjatoslav.alyverkko_cli.Command;
 import eu.svjatoslav.commons.cli_helper.parameter_parser.Parser;
 import eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.DirectoryOption;
 import eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.NullOption;
@@ -17,34 +17,80 @@ import java.nio.file.*;
 import static eu.svjatoslav.alyverkko_cli.Main.configuration;
 import static eu.svjatoslav.alyverkko_cli.configuration.Configuration.loadConfiguration;
 
+/**
+ * The JoinFilesCommand aggregates multiple files (optionally matching
+ * a specific pattern) into a single file for AI processing, typically
+ * in the mail directory.
+ *
+ * Usage Example:
+ * <pre>
+ *   alyverkko-cli joinfiles -s /path/to/source -p "*.java" -t "my_topic" --edit
+ * </pre>
+ */
 public class JoinFilesCommand implements Command {
 
+    /**
+     * A command-line parser to handle joinfiles arguments.
+     */
     final Parser parser = new Parser();
 
+    /**
+     * Directory from which files will be joined.
+     */
     public DirectoryOption sourceDirectoryOption = parser.add(new DirectoryOption("Directory to join files from"))
-            .addAliases("--src-dir", "-s").mustExist();
+            .addAliases("--src-dir", "-s")
+            .mustExist();
 
+    /**
+     * Pattern for matching files, such as "*.java".
+     */
     public StringOption patternOption = parser.add(new StringOption("Pattern to match files"))
             .addAliases("--pattern", "-p");
 
+    /**
+     * Topic name, used as the basis for the output file name.
+     */
     public StringOption topic = parser.add(new StringOption("Topic of the joined files"))
-            .addAliases("--topic", "-t").setMandatory();
+            .addAliases("--topic", "-t")
+            .setMandatory();
 
+    /**
+     * If present, open the joined file using a text editor afterward.
+     */
     public NullOption editOption = parser.add(new NullOption("Edit the joined file using text editor"))
             .addAliases("--edit", "-e");
 
+    /**
+     * The base directory for recursion when joining files.
+     */
+    public Path sourceBaseDirectory;
 
+    /**
+     * The pattern used to filter files for joining, e.g. "*.java".
+     */
+    public String fileNamePattern = null;
+
+    /**
+     * The resulting output file that aggregates all matched files.
+     */
+    File outputFile;
+
+    /**
+     * @return the name of this command, i.e., "joinfiles".
+     */
     @Override
     public String getName() {
         return "joinfiles";
     }
 
-    public Path baseDirectory;
-
-    public String pattern = null;
-
-    File outputFile;
-
+    /**
+     * Executes the command that joins files from a specified directory
+     * (matching an optional pattern) into one output file in the mail
+     * directory. Optionally, it can open the output file in an editor.
+     *
+     * @param cliArguments the command-line arguments after "joinfiles".
+     * @throws IOException if any IO operations fail.
+     */
     @Override
     public void execute(String[] cliArguments) throws IOException {
         configuration = loadConfiguration();
@@ -54,51 +100,69 @@ public class JoinFilesCommand implements Command {
         }
 
         if (!parser.parse(cliArguments)) {
-            System.out.println("Failed to parse commandline arguments");
+            System.out.println("Failed to parse command-line arguments");
             parser.showHelp();
             return;
         }
 
-        // build the path to the target file that is relative to the mail directory
+        // Build the path to the target file that is relative to the mail directory
         outputFile = configuration.getMailDirectory().toPath().resolve(topic.getValue() + ".org").toFile();
 
         if (patternOption.isPresent()) {
-            pattern = patternOption.getValue();
+            fileNamePattern = patternOption.getValue();
             joinFiles();
         }
 
-        if (editOption.isPresent()) openFileWithEditor();
-
+        if (editOption.isPresent()) {
+            openFileWithEditor();
+        }
     }
 
+    /**
+     * Opens the joined file with a text editor. Currently uses a
+     * command "emc" as an example—adapt as needed.
+     *
+     * @throws IOException if the launch of the editor fails.
+     */
     private void openFileWithEditor() throws IOException {
-        String [] cmd = {"emc", outputFile.getAbsolutePath()};
+        String[] cmd = {"emc", outputFile.getAbsolutePath()};
         Runtime.getRuntime().exec(cmd);
     }
 
+    /**
+     * Joins the matching files from the configured source directory
+     * into a single file named {@code <topic>.org} in the mail directory.
+     *
+     * @throws IOException if reading or writing files fails.
+     */
     private void joinFiles() throws IOException {
-
-        // Create or append to the target file
         boolean appendToFile = outputFile.exists();
 
         if (sourceDirectoryOption.isPresent()) {
-            baseDirectory = sourceDirectoryOption.getValue().toPath();
+            sourceBaseDirectory = sourceDirectoryOption.getValue().toPath();
         } else {
-            baseDirectory = Paths.get(".");
+            sourceBaseDirectory = Paths.get(".");
         }
 
         try (BufferedWriter writer = Files.newBufferedWriter(
                 outputFile.toPath(), StandardCharsets.UTF_8,
                 appendToFile ? StandardOpenOption.APPEND : StandardOpenOption.CREATE)) {
 
-
-            // Join files that match the pattern in the specified directory
-            joinFilesRecursively(sourceDirectoryOption.getValue().toPath(), writer);
+            // Recursively join files that match the pattern
+            joinFilesRecursively(sourceBaseDirectory, writer);
         }
 
         System.out.println("Files have been joined into: " + outputFile.getAbsolutePath());
     }
 
+    /**
+     * Recursively traverses the specified directory and writes the contents
+     * of files that match the specified {@link #fileNamePattern}.
+     *
+     * @param directoryToIndex the directory to be searched recursively.
+     * @param writer           the writer to which file contents are appended.
+     * @throws IOException if file reading fails.
+     */
     private void joinFilesRecursively(Path directoryToIndex, BufferedWriter writer) throws IOException {
         try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryToIndex)) {
             for (Path entry : stream) {
@@ -107,7 +171,7 @@ public class JoinFilesCommand implements Command {
                 } else if (Files.isRegularFile(entry)) {
                     String fileName = entry.getFileName().toString();
 
-                    boolean match = GlobMatcher.match(fileName, pattern);
+                    boolean match = GlobMatcher.match(fileName, fileNamePattern);
                     if (match) {
                         System.out.println("Joining file: " + fileName);
                         writeFile(writer, entry);
@@ -117,10 +181,18 @@ public class JoinFilesCommand implements Command {
         }
     }
 
+    /**
+     * Writes the contents of a single file to the specified writer,
+     * including a small header containing the file path.
+     *
+     * @param writer the writer to which file contents are appended.
+     * @param entry  the file to read and write.
+     * @throws IOException if file reading or writing fails.
+     */
     private void writeFile(BufferedWriter writer, Path entry) throws IOException {
         writeFileHeader(writer, entry);
 
-        String fileContent = new String(Files.readAllBytes(entry));
+        String fileContent = new String(Files.readAllBytes(entry), StandardCharsets.UTF_8);
 
         // remove empty lines from the beginning and end of the file
         fileContent = fileContent.replaceAll("(?m)^\\s*$", "");
@@ -128,8 +200,15 @@ public class JoinFilesCommand implements Command {
         writer.write(fileContent + "\n");
     }
 
+    /**
+     * Writes a small header line to indicate which file is being appended.
+     *
+     * @param writer the writer to which the header is appended.
+     * @param entry  the path of the current file.
+     * @throws IOException if writing fails.
+     */
     private void writeFileHeader(BufferedWriter writer, Path entry) throws IOException {
-        String relativePath = baseDirectory.relativize(entry).toString();
+        String relativePath = sourceBaseDirectory.relativize(entry).toString();
         writer.write("* file: " + relativePath + "\n\n");
     }
 }
index 5116d4a..604f327 100644 (file)
@@ -3,21 +3,36 @@ package eu.svjatoslav.alyverkko_cli.configuration;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import lombok.Data;
 
+/**
+ * Represents a single AI model configuration entry, including alias,
+ * path to the model file, token context size, and an optional
+ * end-of-text marker.
+ */
 @Data
 public class ConfigurationModel {
 
+    /**
+     * A short name for the model, e.g., "default" or "mistral".
+     */
     private String alias;
 
     /**
-     * Absolute path in the file system where the model is stored.
+     * The path to the model file (GGUF, etc.), relative to
+     * {@link Configuration#getModelsDirectory()} or fully qualified.
      */
     @JsonProperty("filesystem_path")
     private String filesystemPath;
 
+    /**
+     * The maximum context size the model supports, in tokens.
+     */
     @JsonProperty("context_size_tokens")
     private int contextSizeTokens;
 
+    /**
+     * Optional text marker signifying the end of text for this model.
+     * If non-null, it will be used to strip trailing tokens from the AI response.
+     */
     @JsonProperty("end_of_text_marker")
     private String endOfTextMarker;
-
 }