Skip to content

Commit b193b5d

Browse files
CLI: Work in progress
1 parent 3371861 commit b193b5d

File tree

12 files changed

+335
-88
lines changed

12 files changed

+335
-88
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
[![Javadoc](https://javadoc.io/badge2/io.github.computerdaddyguy/jfiletreeprettyprinter/javadoc.svg?color=blue)](https://javadoc.io/doc/io.github.computerdaddyguy/jfiletreeprettyprinter)
99
[![Apache License 2.0](https://img.shields.io/:license-Apache%20License%202.0-blue.svg)](https://github.com/computerdaddyguy/jfiletreeprettyprinter/blob/main/LICENSE)
1010

11-
**A lightweight and flexible Java library to pretty-print directory structures ideal for documentation, project overviews, or CLI tools.**
11+
**A lightweight and flexible Java library with a native CLI to pretty-print directory structures - ideal for documentation, project overviews, or CLI tools.**
1212

1313
Supports various [options](#customization-options) to customize the directories scanning and rendering:
1414
- Filtering & sorting files and folders

pom.xml

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
<packaging>jar</packaging>
1111
<name>JFileTreePrettyPrinter</name>
12-
<description>A lightweight and flexible Java library to pretty-print directory structures ideal for documentation, project overviews, or CLI tools.</description>
12+
<description>A lightweight and flexible Java library with a native CLI to pretty-print directory structures - ideal for documentation, project overviews, or CLI tools.</description>
1313
<url>https://github.com/ComputerDaddyGuy/JFileTreePrettyPrinter</url>
1414

1515
<licenses>
@@ -29,7 +29,7 @@
2929
<scm>
3030
<connection>scm:git:git://github.com/ComputerDaddyGuy/JFileTreePrettyPrinter.git</connection>
3131
<developerConnection>scm:git:ssh://github.com:ComputerDaddyGuy/JFileTreePrettyPrinter.git</developerConnection>
32-
<url>https://github.com/ComputerDaddyGuy/JFileTreePrettyPrinter/tree/main</url>
32+
<url>https://github.com/ComputerDaddyGuy/JFileTreePrettyPrinter</url>
3333
</scm>
3434

3535
<properties>
@@ -59,6 +59,7 @@
5959
<maven-javadoc-plugin.version>3.11.2</maven-javadoc-plugin.version>
6060
<maven-gpg-plugin.version>3.2.7</maven-gpg-plugin.version>
6161
<native.maven.plugin.version>0.11.1</native.maven.plugin.version>
62+
<git-commit-id-maven-plugin.version>9.0.2</git-commit-id-maven-plugin.version>
6263

6364
</properties>
6465

@@ -135,6 +136,26 @@
135136
</executions>
136137
</plugin>
137138

139+
<plugin>
140+
<groupId>io.github.git-commit-id</groupId>
141+
<artifactId>git-commit-id-maven-plugin</artifactId>
142+
<version>${git-commit-id-maven-plugin.version}</version> <!-- check for latest -->
143+
<executions>
144+
<execution>
145+
<id>get-the-git-infos</id>
146+
<goals>
147+
<goal>revision</goal>
148+
</goals>
149+
<phase>initialize</phase>
150+
</execution>
151+
</executions>
152+
<configuration>
153+
<generateGitPropertiesFile>false</generateGitPropertiesFile>
154+
<!-- <generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>-->
155+
<commitIdGenerationMode>full</commitIdGenerationMode>
156+
</configuration>
157+
</plugin>
158+
138159
<plugin>
139160
<groupId>org.apache.maven.plugins</groupId>
140161
<artifactId>maven-jar-plugin</artifactId>
@@ -143,6 +164,19 @@
143164
<excludes>
144165
<exclude>src/example/**</exclude>
145166
</excludes>
167+
<archive>
168+
<manifest>
169+
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
170+
<addDefaultSpecificationEntries>false</addDefaultSpecificationEntries>
171+
</manifest>
172+
<manifestEntries>
173+
<Build-Time>${git.build.time}</Build-Time>
174+
<Commit-Id>${git.commit.id.full}</Commit-Id>
175+
<Commit-Time>${git.commit.time}</Commit-Time>
176+
<Project-Desc>${project.description}</Project-Desc>
177+
<Scm-Url>${scm.url}</Scm-Url>
178+
</manifestEntries>
179+
</archive>
146180
</configuration>
147181
</plugin>
148182

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package io.github.computerdaddyguy.jfiletreeprettyprinter.cli;
2+
3+
import java.io.PrintStream;
4+
import java.util.logging.Level;
5+
import java.util.logging.Logger;
6+
import org.jspecify.annotations.NullMarked;
7+
8+
@NullMarked
9+
public class ConsoleOutput {
10+
11+
private static final Logger ROOT_LOGGER = Logger.getLogger("");
12+
13+
private boolean debug;
14+
15+
public ConsoleOutput(boolean debug) {
16+
this.debug = debug;
17+
disableAllLoggers();
18+
}
19+
20+
private void disableAllLoggers() {
21+
ROOT_LOGGER.setLevel(Level.OFF);
22+
Logger.getLogger("org.hibernate.validator").setLevel(Level.OFF);
23+
}
24+
25+
private void printOut(String msg, Object... args) {
26+
printf(System.out, msg, args);
27+
}
28+
29+
private void printErr(String msg, Object... args) {
30+
printf(System.err, msg, args);
31+
}
32+
33+
private void printf(PrintStream dest, String msg, Object... args) {
34+
dest.printf(msg, args);
35+
dest.println(); // Because "printf" does not print line return
36+
}
37+
38+
public void printDebug(String msg, Object... args) {
39+
// Could not (yet) make Logger level work within native image, so fallback to plain console output (for now)
40+
if (debug && msg != null) {
41+
printOut(msg, args);
42+
}
43+
}
44+
45+
public void print(String msg, Object... args) {
46+
printOut(msg, args);
47+
}
48+
49+
public void printError(String msg, Object... args) {
50+
printErr(msg, args);
51+
}
52+
53+
}

src/main/java/io/github/computerdaddyguy/jfiletreeprettyprinter/cli/FileTreePrettyPrinterCommandLine.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
import picocli.CommandLine;
44

5-
public class FileTreePrettyPrinterCommandLine {
5+
class FileTreePrettyPrinterCommandLine {
66

77
public static void main(String[] args) {
8-
int exitCode = new CommandLine(new PrettyPrintCommand()).execute(args);
8+
var cmd = new CommandLine(new PrettyPrintCommand());
9+
int exitCode = cmd.execute(args);
910
System.exit(exitCode);
1011
}
1112

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package io.github.computerdaddyguy.jfiletreeprettyprinter.cli;
2+
3+
import java.io.InputStream;
4+
import java.util.jar.Manifest;
5+
import picocli.CommandLine.IVersionProvider;
6+
7+
class ManifestVersionProvider implements IVersionProvider {
8+
9+
@Override
10+
public String[] getVersion() throws Exception {
11+
String implTitle = null;
12+
String implVersion = null;
13+
String projectDesc = null;
14+
String commitId = null;
15+
String commitTime = null;
16+
String scmUrl = null;
17+
String buildTime = null;
18+
19+
try (InputStream is = getClass().getResourceAsStream("/META-INF/MANIFEST.MF")) {
20+
if (is != null) {
21+
Manifest manifest = new Manifest(is);
22+
implTitle = manifest.getMainAttributes().getValue("Implementation-Title");
23+
implVersion = manifest.getMainAttributes().getValue("Implementation-Version");
24+
projectDesc = manifest.getMainAttributes().getValue("Project-Desc");
25+
commitId = manifest.getMainAttributes().getValue("Commit-Id");
26+
commitTime = manifest.getMainAttributes().getValue("Commit-Time");
27+
scmUrl = manifest.getMainAttributes().getValue("Scm-Url");
28+
buildTime = manifest.getMainAttributes().getValue("Build-Time");
29+
}
30+
}
31+
32+
return new String[] {
33+
valueOrUnknown(implTitle) + " " + valueOrUnknown(implVersion),
34+
valueOrUnknown(projectDesc),
35+
"Repository: " + valueOrUnknown(scmUrl),
36+
"Commit: " + valueOrUnknown(commitId) + " (" + valueOrUnknown(commitTime) + ")",
37+
"Built on: " + valueOrUnknown(buildTime)
38+
};
39+
}
40+
41+
private static final String valueOrUnknown(String value) {
42+
return value != null ? value : "unknown";
43+
}
44+
45+
}

src/main/java/io/github/computerdaddyguy/jfiletreeprettyprinter/cli/PrettyPrintCommand.java

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
import io.github.computerdaddyguy.jfiletreeprettyprinter.FileTreePrettyPrinter;
44
import io.github.computerdaddyguy.jfiletreeprettyprinter.cli.options.ExternalOptionsReader;
5+
import io.github.computerdaddyguy.jfiletreeprettyprinter.options.PrettyPrintOptions;
56
import java.io.File;
67
import java.nio.file.Path;
7-
import java.util.List;
8+
import java.util.ArrayList;
89
import java.util.concurrent.Callable;
9-
import java.util.logging.Level;
10-
import java.util.logging.LogManager;
11-
import java.util.logging.Logger;
10+
import org.jspecify.annotations.NullMarked;
11+
import org.jspecify.annotations.Nullable;
1212
import picocli.CommandLine.Command;
1313
import picocli.CommandLine.Option;
1414
import picocli.CommandLine.Parameters;
@@ -17,51 +17,83 @@
1717
@Command(
1818
name = "prettyprint",
1919
mixinStandardHelpOptions = true,
20-
version = "checksum 4.0",
21-
description = "Prints the checksum (SHA-256 by default) of a file to STDOUT."
20+
versionProvider = ManifestVersionProvider.class,
21+
description = "Pretty-prints directory structure"
2222
)
2323
// @formatter:on
24-
public class PrettyPrintCommand implements Callable<Integer> {
24+
@NullMarked
25+
class PrettyPrintCommand implements Callable<Integer> {
2526

26-
@Parameters(index = "0", description = "The path to pretty print", arity = "0")
27-
private File file;
27+
@Nullable
28+
@Parameters(index = "0", description = "The path to pretty print", arity = "0..1")
29+
private File target;
2830

31+
@Nullable
2932
@Option(names = { "-o", "--options" }, paramLabel = "OPTIONS", description = "the options file", arity = "0")
3033
private File optionsFile;
3134

35+
@Option(names = { "-d", "--debug" }, description = "debug mode")
36+
private boolean debug;
37+
3238
@Override
3339
public Integer call() throws Exception {
3440

35-
LogManager.getLogManager().reset();
36-
Logger.getLogger("org.hibernate.validator").setLevel(Level.OFF);
37-
38-
var reader = new ExternalOptionsReader();
39-
reader.readOptions();
41+
var output = new ConsoleOutput(debug);
4042

41-
Path path = detectPathToPrint();
42-
if (optionsFile != null) {
43-
path = optionsFile.toPath();
43+
var targetPath = detectTargetPath(output);
44+
if (!targetPath.toFile().exists()) {
45+
output.printError("Path not found: %s", targetPath);
46+
return 1;
4447
}
48+
49+
var options = detectOptions(targetPath, output);
50+
4551
try {
46-
var printer = FileTreePrettyPrinter.createDefault();
47-
var result = printer.prettyPrint(path);
48-
System.out.println(result);
52+
var printer = FileTreePrettyPrinter.builder().withOptions(options).build();
53+
var result = printer.prettyPrint(targetPath);
54+
output.print(result);
55+
return 0;
4956
} catch (Exception e) {
50-
System.err.print("Error while pretty printing: " + e.getMessage());
57+
output.printError("Error while pretty printing: " + e.getMessage());
5158
return 1;
5259
}
60+
}
5361

54-
return 0;
62+
private Path detectTargetPath(ConsoleOutput output) {
63+
Path path = null;
64+
if (target != null) {
65+
path = target.toPath();
66+
} else {
67+
output.printDebug("No target provided: use current directory");
68+
path = Path.of(".");
69+
}
70+
path = path.toAbsolutePath().normalize();
71+
output.printDebug("Target path: %s", path);
72+
return path;
5573
}
5674

57-
private static Path detectPathToPrint() {
58-
for (var p : List.of("tmp", "target/tmp")) {
59-
var path = Path.of(p);
60-
if (path.toFile().exists()) {
61-
return path;
75+
private PrettyPrintOptions detectOptions(Path targetPath, ConsoleOutput output) {
76+
77+
var reader = new ExternalOptionsReader(output);
78+
if (optionsFile != null) {
79+
var path = optionsFile.toPath().toAbsolutePath().normalize();
80+
var options = reader.readOptions(path);
81+
if (options == null) {
82+
System.exit(1);
83+
}
84+
return options;
85+
} else {
86+
var potentialOptions = new ArrayList<Path>();
87+
potentialOptions.add(targetPath.resolve(".prettyprint"));
88+
potentialOptions.add(Path.of(".").resolve(".prettyprint"));
89+
potentialOptions.add(Path.of(System.getProperty("user.home")).resolve(".prettyprint"));
90+
var options = reader.readOptions(potentialOptions);
91+
if (options != null) {
92+
return options;
6293
}
94+
output.printDebug("No options file provided/found!");
95+
return PrettyPrintOptions.createDefault();
6396
}
64-
return Path.of(".");
6597

6698
}
6799

src/main/java/io/github/computerdaddyguy/jfiletreeprettyprinter/cli/options/model/ChildLimit.java renamed to src/main/java/io/github/computerdaddyguy/jfiletreeprettyprinter/cli/options/ChildLimit.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package io.github.computerdaddyguy.jfiletreeprettyprinter.cli.options.model;
1+
package io.github.computerdaddyguy.jfiletreeprettyprinter.cli.options;
22

33
import com.fasterxml.jackson.annotation.JsonTypeInfo;
44
import com.fasterxml.jackson.annotation.JsonTypeName;
@@ -8,7 +8,7 @@
88
import java.util.List;
99

1010
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
11-
public sealed interface ChildLimit {
11+
sealed interface ChildLimit {
1212

1313
/**
1414
*

src/main/java/io/github/computerdaddyguy/jfiletreeprettyprinter/cli/options/model/ExternalOptions.java renamed to src/main/java/io/github/computerdaddyguy/jfiletreeprettyprinter/cli/options/ExternalOptions.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
package io.github.computerdaddyguy.jfiletreeprettyprinter.cli.options.model;
1+
package io.github.computerdaddyguy.jfiletreeprettyprinter.cli.options;
22

33
import jakarta.validation.Valid;
44

5-
public record ExternalOptions(
5+
record ExternalOptions(
66
Boolean emojis,
77
@Valid ChildLimit childLimit
88
) {

0 commit comments

Comments
 (0)