Skip to content

Commit e57f7fa

Browse files
Feature/option builders (#9)
* LineExtensions / ChildLimits / PathSorts
1 parent 9188107 commit e57f7fa

File tree

21 files changed

+812
-327
lines changed

21 files changed

+812
-327
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010

1111
### Added
1212
- New various path matchers
13+
- New `LineExtensions`, `ChildLimits` and `PathSorts` helper classes (and associated builders)
1314

1415
### Changed
16+
- Helpers classes `PathUtils` and `PathPredicates` removed, use `PathMatchers` instead
1517
- Filtering: now using `PathMatcher` interface instead of `Predicate<Path>`
1618
- Filtering: split into distinct directories and files filters for better control
17-
- `PathUtils` and `PathPredicates` removed, use `PathMatchers` instead
1819
- Line extension: empty string is now permitted
1920

2021
### Fixed

README.md

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,12 @@ filtering/
132132
Files and directories can be sorted using a custom comparator (default is alphabetical order).
133133
If the provided comparator considers two paths equal (i.e., returns `0`), an alphabetical comparator is applied as a tie-breaker to ensure consistent results across all systems.
134134

135-
The `PrettyPrintOptions.Sorts` class provides a set of basic, ready-to-use comparators.
135+
The `PathSorts` class provides a set of basic, ready-to-use comparators, as well as a builder for creating your own tailor-made sorts.
136136

137137
```java
138138
// Example: Sorting.java
139139
var prettyPrinter = FileTreePrettyPrinter.builder()
140-
.customizeOptions(options -> options.sort(PrettyPrintOptions.Sorts.DIRECTORY_FIRST))
140+
.customizeOptions(options -> options.sort(PathSorts.DIRECTORY_FIRST))
141141
.build();
142142
```
143143
```
@@ -219,14 +219,13 @@ Use the `ChildLimitBuilder` and `PathMatchers` classes to help you build the lim
219219

220220
```java
221221
// Example: ChildLimitDynamic.java
222-
var isNodeModuleMatcher = PathMatchers.hasName("node_modules");
223-
var childLimit = ChildLimitBuilder.builder()
224-
.defaultLimit(ChildLimitBuilder.UNLIMITED)
225-
.limit(isNodeModuleMatcher, 0)
222+
var childLimit = ChildLimits.builder()
223+
.setDefault(ChildLimits.UNLIMITED) // Unlimited children by default
224+
.add(PathMatchers.hasName("node_modules"), 0) // Do NOT print any children in "node_modules" folder
226225
.build();
227226
var prettyPrinter = FileTreePrettyPrinter.builder()
228-
.customizeOptions(options -> options.withChildLimit(childLimit))
229-
.build();
227+
.customizeOptions(options -> options.withChildLimit(childLimit))
228+
.build();
230229
```
231230
```
232231
child_limit_dynamic/
@@ -249,28 +248,23 @@ child_limit_dynamic/
249248
You can extend each displayed path with additional information by providing a custom `Function<Path, String>`.
250249
This is useful to annotate your tree with comments, display file sizes, or add domain-specific notes.
251250

252-
The function receives the current path and returns an optional string to append.
251+
The function receives the current path and returns an optional string to append (empty string is authorized).
253252
If the function returns `null`, nothing is added.
254253

254+
Use the `LineExtensions` class to help you build line extension functions.
255+
255256
```java
256257
// Example: LineExtension.java
257258
var printedPath = Path.of("src/example/resources/line_extension");
258259

259-
Function<Path, String> lineExtension = path -> {
260-
if (PathMatchers.hasRelativePathMatchingGlob("src/main/java/api", printedPath).matches(path)) {
261-
return "\t\t\t// All API code: controllers, etc.";
262-
}
263-
if (PathMatchers.hasRelativePathMatchingGlob("src/main/java/domain", printedPath).matches(path)) {
264-
return "\t\t\t// All domain code: value objects, etc.";
265-
}
266-
if (PathMatchers.hasRelativePathMatchingGlob("src/main/java/infra", printedPath).matches(path)) {
267-
return "\t\t\t// All infra code: database, email service, etc.";
268-
}
269-
if (PathMatchers.hasNameMatchingGlob("*.properties").matches(path)) {
270-
return "\t// Config file";
271-
}
272-
return null;
273-
};
260+
Function<Path, String> lineExtension = LineExtensions.builder()
261+
.add(PathMatchers.hasRelativePathMatchingGlob(printedPath, "src/main/java/api"), "\t\t\t// All API code: controllers, etc.")
262+
.add(PathMatchers.hasRelativePathMatchingGlob(printedPath, "src/main/java/domain"), "\t\t\t// All domain code: value objects, etc.")
263+
.add(PathMatchers.hasRelativePathMatchingGlob(printedPath, "src/main/java/infra"), "\t\t\t// All infra code: database, email service, etc.")
264+
.add(PathMatchers.hasRelativePathMatchingGlob(printedPath, "src/main/java/api"), "\t\t\t// All API code: controllers, etc.")
265+
.add(PathMatchers.hasNameMatchingGlob("*.properties"), "\t// Config file")
266+
.build();
267+
274268
var prettyPrinter = FileTreePrettyPrinter.builder()
275269
.customizeOptions(options -> options.withLineExtension(lineExtension))
276270
.build();

ROADMAP.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727

2828
## To do
2929
- [x] More `PathMatchers` functions!
30-
- [ ] Helper class for line extension
31-
- [ ] Helper class for sorting
30+
- [x] Helper class for line extension
31+
- [x] Helper class for sorting
3232
- [ ] Option: custom emojis
3333
- [ ] Option: hide number of skipped files and folders for child limit
3434
- [ ] Rework/fix Github wiki to be up to date

assets/project-structure.png

19.5 KB
Loading

src/example/java/io/github/computerdaddyguy/jfiletreeprettyprinter/example/ChildLimitDynamic.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
package io.github.computerdaddyguy.jfiletreeprettyprinter.example;
22

3-
import io.github.computerdaddyguy.jfiletreeprettyprinter.ChildLimitBuilder;
3+
import io.github.computerdaddyguy.jfiletreeprettyprinter.ChildLimits;
44
import io.github.computerdaddyguy.jfiletreeprettyprinter.FileTreePrettyPrinter;
55
import io.github.computerdaddyguy.jfiletreeprettyprinter.PathMatchers;
66

77
public class ChildLimitDynamic {
88

99
public static void main(String[] args) {
10-
var isNodeModuleMatcher = PathMatchers.hasName("node_modules");
11-
var childLimit = ChildLimitBuilder.builder()
12-
.defaultLimit(ChildLimitBuilder.UNLIMITED)
13-
.limit(isNodeModuleMatcher, 0)
10+
var childLimit = ChildLimits.builder()
11+
.setDefault(ChildLimits.UNLIMITED) // Unlimited children by default
12+
.add(PathMatchers.hasName("node_modules"), 0) // Do NOT print any children in "node_modules" folder
1413
.build();
1514
var prettyPrinter = FileTreePrettyPrinter.builder()
1615
.customizeOptions(options -> options.withChildLimit(childLimit))

src/example/java/io/github/computerdaddyguy/jfiletreeprettyprinter/example/LineExtension.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.github.computerdaddyguy.jfiletreeprettyprinter.example;
22

33
import io.github.computerdaddyguy.jfiletreeprettyprinter.FileTreePrettyPrinter;
4+
import io.github.computerdaddyguy.jfiletreeprettyprinter.LineExtensions;
45
import io.github.computerdaddyguy.jfiletreeprettyprinter.PathMatchers;
56
import java.nio.file.Path;
67
import java.util.function.Function;
@@ -10,21 +11,14 @@ public class LineExtension {
1011
public static void main(String[] args) {
1112
var printedPath = Path.of("src/example/resources/line_extension");
1213

13-
Function<Path, String> lineExtension = path -> {
14-
if (PathMatchers.hasRelativePathMatchingGlob(printedPath, "src/main/java/api").matches(path)) {
15-
return "\t\t\t// All API code: controllers, etc.";
16-
}
17-
if (PathMatchers.hasRelativePathMatchingGlob(printedPath, "src/main/java/domain").matches(path)) {
18-
return "\t\t\t// All domain code: value objects, etc.";
19-
}
20-
if (PathMatchers.hasRelativePathMatchingGlob(printedPath, "src/main/java/infra").matches(path)) {
21-
return "\t\t\t// All infra code: database, email service, etc.";
22-
}
23-
if (PathMatchers.hasNameMatchingGlob("*.properties").matches(path)) {
24-
return "\t// Config file";
25-
}
26-
return null;
27-
};
14+
Function<Path, String> lineExtension = LineExtensions.builder()
15+
.add(PathMatchers.hasRelativePathMatchingGlob(printedPath, "src/main/java/api"), "\t\t\t// All API code: controllers, etc.")
16+
.add(PathMatchers.hasRelativePathMatchingGlob(printedPath, "src/main/java/domain"), "\t\t\t// All domain code: value objects, etc.")
17+
.add(PathMatchers.hasRelativePathMatchingGlob(printedPath, "src/main/java/infra"), "\t\t\t// All infra code: database, email service, etc.")
18+
.add(PathMatchers.hasRelativePathMatchingGlob(printedPath, "src/main/java/api"), "\t\t\t// All API code: controllers, etc.")
19+
.add(PathMatchers.hasNameMatchingGlob("*.properties"), "\t// Config file")
20+
.build();
21+
2822
var prettyPrinter = FileTreePrettyPrinter.builder()
2923
.customizeOptions(options -> options.withLineExtension(lineExtension))
3024
.build();

src/example/java/io/github/computerdaddyguy/jfiletreeprettyprinter/example/ProjectStructure.java

Lines changed: 42 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package io.github.computerdaddyguy.jfiletreeprettyprinter.example;
22

3-
import io.github.computerdaddyguy.jfiletreeprettyprinter.ChildLimitBuilder;
3+
import io.github.computerdaddyguy.jfiletreeprettyprinter.ChildLimits;
44
import io.github.computerdaddyguy.jfiletreeprettyprinter.FileTreePrettyPrinter;
5+
import io.github.computerdaddyguy.jfiletreeprettyprinter.LineExtensions;
56
import io.github.computerdaddyguy.jfiletreeprettyprinter.PathMatchers;
6-
import io.github.computerdaddyguy.jfiletreeprettyprinter.PrettyPrintOptions.Sorts;
7+
import io.github.computerdaddyguy.jfiletreeprettyprinter.PathSorts;
78
import java.nio.file.Path;
89
import java.util.Comparator;
910
import java.util.function.Function;
@@ -47,46 +48,38 @@ public static void main(String[] args) {
4748
var fileFilter = PathMatchers.allOf(
4849

4950
// Hide files with names starting with "."
50-
PathMatchers.not(PathMatchers.hasNameStartingWith(".")),
51-
52-
// Inside "jfiletreeprettyprinter" folder, keep only "FileTreePrettyPrinter.java"
53-
// Files in other folders are not restricted by this rule.
54-
PathMatchers.ifMatchesThenElse(
55-
/* if */ PathMatchers.hasDirectParentMatching(PathMatchers.hasName("jfiletreeprettyprinter")),
56-
/* then */ PathMatchers.hasName("FileTreePrettyPrinter.java"),
57-
/* else */ path -> true
58-
)
51+
PathMatchers.not(PathMatchers.hasNameStartingWith("."))
5952
);
6053

6154
/*
6255
* Limit the number of displayed children by directory: some content is not relevant and clutters the final result!
6356
*/
64-
var childLimitFunction = ChildLimitBuilder.builder()
57+
var childLimitFunction = ChildLimits.builder()
6558
// Hide all files under renderer and scanner packages
66-
.limit(PathMatchers.hasAbsolutePathMatchingGlob("**/io/github/computerdaddyguy/jfiletreeprettyprinter/renderer"), 0)
67-
.limit(PathMatchers.hasAbsolutePathMatchingGlob("**/io/github/computerdaddyguy/jfiletreeprettyprinter/scanner"), 0)
59+
.add(PathMatchers.hasAbsolutePathMatchingGlob("**/io/github/computerdaddyguy/jfiletreeprettyprinter/renderer"), 0)
60+
.add(PathMatchers.hasAbsolutePathMatchingGlob("**/io/github/computerdaddyguy/jfiletreeprettyprinter/scanner"), 0)
61+
.add(PathMatchers.hasAbsolutePathMatchingGlob("**/io/github/computerdaddyguy/jfiletreeprettyprinter"), 3)
6862
.build();
6963

7064
/*
7165
* Add some comments on a few files and directories
7266
*/
73-
Function<Path, String> lineExtension = path -> {
74-
if (PathMatchers.hasName("project-structure.png").matches(path)) {
75-
return "\t// This image";
76-
} else if (PathMatchers.hasName("FileTreePrettyPrinter.java").matches(path)) {
77-
return "\t// Main entry point";
78-
} else if (PathMatchers.hasName("README.md").matches(path)) {
79-
return "\t\t// You're reading at this!";
80-
} else if (PathMatchers.hasRelativePathMatchingGlob(projectFolder, "src/main/java").matches(path)) {
81-
return ""; // Empty string: force line break in compact directory chain
82-
}
83-
return null;
84-
};
67+
Function<Path, String> lineExtension = LineExtensions.builder()
68+
.add(PathMatchers.hasName("project-structure.png"), "\t// This image")
69+
.add(PathMatchers.hasName("FileTreePrettyPrinter.java"), "\t// Main entry point")
70+
.add(PathMatchers.hasName("README.md"), "\t\t// You're reading at this!")
71+
.addLineBreak(PathMatchers.hasRelativePathMatchingGlob(projectFolder, "src/main/java"))
72+
.build();
8573

8674
/*
87-
* Sort all paths by directory first (then alphabetically by default)
75+
* Sort all paths by directory first (with highest precedence),
76+
* then "FileTreePrettyPrinter.java" has precedence "-100".
77+
* All other files have default precedence "0", and are then sorted alphabetically by default.
8878
*/
89-
Comparator<Path> pathComparator = Sorts.DIRECTORY_FIRST;
79+
Comparator<Path> pathComparator = PathSorts.builder()
80+
.addFirst(PathMatchers.isDirectory())
81+
.add(PathMatchers.hasName("FileTreePrettyPrinter.java"), -100) // Default precedence is "0"
82+
.build();
9083

9184
/*
9285
* Build the final FileTreePrettyPrinter
@@ -115,25 +108,27 @@ public static void main(String[] args) {
115108
Expected result
116109
================================
117110
118-
📂 JFileTreePrettyPrinter/
119-
├─ 📂 assets/
120-
│ └─ 🖼️ project-structure.png // This image
121-
├─ 📂 src/main/java/
122-
│ └─ 📂 io/github/computerdaddyguy/jfiletreeprettyprinter/
123-
│ ├─ 📂 renderer/
124-
│ │ └─ ... (5 files and 2 directories skipped)
125-
│ ├─ 📂 scanner/
126-
│ │ └─ ... (4 files skipped)
127-
│ └─ ☕ FileTreePrettyPrinter.java // Main entry point
128-
├─ 🗺️ CHANGELOG.md
129-
├─ 📖 CONTRIBUTING.md
130-
├─ 📄 LICENSE
131-
├─ 📖 README.md // You're reading at this!
132-
├─ 🗺️ ROADMAP.md
133-
├─ 🛡️ SECURITY.md
134-
├─ 🏗️ pom.xml
135-
├─ 📖 release_process.md
136-
└─ 📜 runMutationTests.sh
111+
📂 JFileTreePrettyPrinter/
112+
├─ 📂 assets/
113+
│ └─ 🖼️ project-structure.png // This image
114+
├─ 📂 src/main/java/
115+
│ └─ 📂 io/github/computerdaddyguy/jfiletreeprettyprinter/
116+
│ ├─ 📂 renderer/
117+
│ │ └─ ... (5 files and 2 directories skipped)
118+
│ ├─ 📂 scanner/
119+
│ │ └─ ... (4 files skipped)
120+
│ ├─ ☕ FileTreePrettyPrinter.java // Main entry point
121+
│ └─ ... (10 files skipped)
122+
├─ 🗺️ CHANGELOG.md
123+
├─ 📖 CONTRIBUTING.md
124+
├─ 📄 LICENSE
125+
├─ 📖 README.md // You're reading at this!
126+
├─ 🗺️ ROADMAP.md
127+
├─ 🛡️ SECURITY.md
128+
├─ 🏗️ pom.xml
129+
├─ 📖 release_process.md
130+
└─ 📜 runMutationTests.sh
131+
137132
*/
138133
}
139134

src/example/java/io/github/computerdaddyguy/jfiletreeprettyprinter/example/Sorting.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package io.github.computerdaddyguy.jfiletreeprettyprinter.example;
22

33
import io.github.computerdaddyguy.jfiletreeprettyprinter.FileTreePrettyPrinter;
4-
import io.github.computerdaddyguy.jfiletreeprettyprinter.PrettyPrintOptions;
4+
import io.github.computerdaddyguy.jfiletreeprettyprinter.PathSorts;
55

66
public class Sorting {
77

88
public static void main(String[] args) {
99
var prettyPrinter = FileTreePrettyPrinter.builder()
10-
.customizeOptions(options -> options.sort(PrettyPrintOptions.Sorts.DIRECTORY_FIRST))
10+
.customizeOptions(options -> options.sort(PathSorts.DIRECTORY_FIRST))
1111
.build();
1212
var tree = prettyPrinter.prettyPrint("src/example/resources/sorting");
1313
System.out.println(tree);

0 commit comments

Comments
 (0)