Skip to content

Commit

Permalink
config file with multiple sources, readying for multiple source set n…
Browse files Browse the repository at this point in the history
…avigatoin
  • Loading branch information
shrimpza committed Jun 15, 2022
1 parent c514cfe commit 1a371b8
Show file tree
Hide file tree
Showing 8 changed files with 290 additions and 39 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ build
out
.idea
*.iml

sources.ini
76 changes: 51 additions & 25 deletions src/main/java/net/shrimpworks/unreal/scriptbrowser/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,63 @@ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int
}
}

public static void main(String[] args) throws IOException {
final long startTime = System.currentTimeMillis();
private static List<USources> loadProperties() throws IOException {
IniFile config = new IniFile(Paths.get("sources.ini"));
return config.sections().stream()
.map(s -> new USources(
s,
config.section(s).value("out").toString(),
config.section(s)
.asList("paths").values
.stream()
.map(v -> Paths.get(v.toString()))
.collect(Collectors.toList()))
).collect(Collectors.toList());
}

public static void main(String[] args) throws IOException {
CLI cli = CLI.parse(Map.of(), args);

Path srcPath = Paths.get(cli.commands()[0]);
Path outPath = Paths.get(cli.commands()[1]);
Path outPath = Paths.get(cli.commands()[0]);

List<USources> sources = loadProperties();
for (USources source : sources) {
System.err.printf("Generating sources for %s%n", source.name);
loadSources(source);
// printTree(children(source, null), 0);
final long loadedTime = System.currentTimeMillis();

final Path htmlOut = outPath.resolve(source.outPath);

System.err.println(" - Generating navigation tree");
Generator.tree(children(source, null), htmlOut);

System.err.println(" - Generating source pages");
source.packages.values().forEach(pkg -> pkg.classes.values().parallelStream()
.filter(c -> c.kind == UClass.UClassKind.CLASS)
.forEach(e -> Generator.src(e, htmlOut)));
final long genTime = System.currentTimeMillis();
System.err.printf(" - Generated HTML in %dms%n", genTime - loadedTime);
}

System.err.println("Generating index page");
Generator.offloadStatic("static.list", outPath);
Generator.index(outPath);

System.err.println("Done");
}

USources sources = new USources();
private static void loadSources(USources sources) throws IOException {
for (Path srcPath : sources.paths) {
loadSources(sources, srcPath);
}
}

private static void loadSources(USources sources, Path srcPath) throws IOException {
final long startTime = System.currentTimeMillis();
final AtomicInteger classCounter = new AtomicInteger(0);
try (Stream<Path> paths = Files.list(srcPath)) {
System.err.printf("Loading classes from %s%n", srcPath);
System.err.printf(" - Loading classes from %s%n", srcPath);

paths.map(p -> {
if (!Files.isDirectory(p)) return null;
Expand Down Expand Up @@ -84,26 +128,8 @@ public static void main(String[] args) throws IOException {
.forEach(sources::addPackage);
}
final long loadedTime = System.currentTimeMillis();
System.err.printf("Loaded %d classes in %d packages in %dms%n", classCounter.get(), sources.packages.size(),
System.err.printf(" - Loaded %d classes in %d packages in %dms%n", classCounter.get(), sources.packages.size(),
loadedTime - startTime);

System.err.println("Generating index page");
Generator.offloadStatic("static.list", outPath);
Generator.index(outPath);

System.err.println("Generating navigation tree");
Generator.tree(children(sources, null), outPath);

System.err.println("Generating source pages");
sources.packages.values().forEach(pkg -> pkg.classes.values().parallelStream()
.filter(c -> c.kind == UClass.UClassKind.CLASS)
.forEach(e -> Generator.src(e, outPath)));
final long genTime = System.currentTimeMillis();
System.err.printf("Generated HTML in %dms%n", genTime - loadedTime);

// printTree(children(sources, null), 0);

System.err.println("Done");
}

public static List<UClassNode> children(USources sources, UClass parent) {
Expand Down
213 changes: 213 additions & 0 deletions src/main/java/net/shrimpworks/unreal/scriptbrowser/IniFile.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
package net.shrimpworks.unreal.scriptbrowser;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
* Provides a simple <code>.ini</code> file reader implementations, supporting
* some basic concepts like sections and repeat keys.
*/
public class IniFile {

private static final Pattern SECTION = Pattern.compile("\\s*\\[([^]]*)\\]\\s*");
private static final Pattern KEY_VALUE = Pattern.compile("\\s*([^=]*)=(.*)");
private final List<Section> sections;

public IniFile(Path intFile) throws IOException {
this(FileChannel.open(intFile, StandardOpenOption.READ), false);
}

/**
* Create a new IniFile from a file path.
*
* @param intFile path to int file to read
* @param syntheticRoot if true, will create a synthetic section named "root"
* to hold items which don't have a section header
* @throws IOException reading file failed
*/
public IniFile(Path intFile, boolean syntheticRoot) throws IOException {
this(FileChannel.open(intFile, StandardOpenOption.READ), syntheticRoot);
}

public IniFile(SeekableByteChannel channel) throws IOException {
this(channel, false);
}

/**
* Create a new IntFile from a byte channel.
*
* @param channel channel to read
* @param syntheticRoot if true, will create a synthetic section named "root"
* to hold items which don't have a section header
* @throws IOException reading channel failed
*/
public IniFile(SeekableByteChannel channel, boolean syntheticRoot) throws IOException {
this.sections = new ArrayList<>();

try (BufferedReader reader = new BufferedReader(Channels.newReader(channel, "UTF-8"))) {
String r;
Section section = null;
if (syntheticRoot) {
section = new Section("root", new HashMap<>());
sections.add(section);
}
while ((r = reader.readLine()) != null) {
Matcher m = SECTION.matcher(r);
if (m.matches()) {
section = new Section(m.group(1).trim(), new HashMap<>());
sections.add(section);
} else if (section != null) {
m = KEY_VALUE.matcher(r);
if (m.matches()) {
String k = m.group(1).trim();
String v = m.group(2).trim();

Value value = new StringValue(v);

Value current = section.values.get(k);

if (current instanceof ListValue) {
((ListValue)current).values.add(value);
} else if (current != null) {
section.values.put(k, new ListValue(new ArrayList<>(Arrays.asList(current, value))));
} else {
section.values.put(k, value);
}
}
}
}
}
}

/**
* Get a section.
*
* @param section the section name
* @return the section, or null if not found
*/
public Section section(String section) {
return sections.stream().filter(s -> s.name.equalsIgnoreCase(section)).findFirst().orElse(null);
}

/**
* Get a list of all sections within this .int file.
*
* @return section names
*/
public Collection<String> sections() {
return sections.stream().map(s -> s.name).collect(Collectors.toList());
}

@Override
public String toString() {
return String.format("IntFile [sections=%s]", sections);
}

/**
* An <code>.int</code> file section.
* <p>
* In the file structure, these are identified by their [Heading].
*/
public static class Section {

public final String name;
private final Map<String, Value> values;

public Section(String name, Map<String, Value> values) {
this.name = name;
this.values = values;
}

/**
* Retrieve a value by its key.
*
* @param key key
* @return value, or null if the key does not exist
*/
public Value value(String key) {
return values.get(key);
}

/**
* Get a list of all keys within this section.
*
* @return key names
*/
public Collection<String> keys() {
return values.keySet();
}

/**
* Convenience to always retrieve a value as a list.
* <p>
* This is useful if, based on reading the file a value appears to
* be a singleton, but code reading it perhaps expects a list to be
* present.
*
* @param key the key
* @return a list of values, or null if the key does not exist
*/
public ListValue asList(String key) {
Value val = value(key);
if (val instanceof ListValue) return (ListValue)val;
if (val != null) return new ListValue(Collections.singletonList(val));
return new ListValue(Collections.emptyList());
}

@Override
public String toString() {
return String.format("Section [name=%s, values=%s]", name, values);
}
}

public interface Value {
}

public static class StringValue implements Value {

public final String value;

public StringValue(String value) {
this.value = value;
}

@Override
public String toString() {
return value;
}
}

public static class ListValue implements Value {

public final List<Value> values;

public ListValue(List<Value> values) {
this.values = values;
}

public Value get(int index) {
return values.get(index);
}

@Override
public String toString() {
return values.toString();
}
}

}
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
package net.shrimpworks.unreal.scriptbrowser;

import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;

public class USources {

public final String name;
public final String outPath;
public final List<Path> paths;
public final Map<String, UPackage> packages;

public USources() {
public USources(String name, String outPath, List<Path> paths) {
this.name = name;
this.outPath = outPath;
this.paths = paths;
this.packages = new TreeMap<>();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ public static void index(Path outPath) {

public static void tree(Collection<UClassNode> nodes, Path outPath) {
try {
if (!Files.isDirectory(outPath)) Files.createDirectories(outPath);

Template tpl = TPL_CONFIG.getTemplate("tree.ftl");
try (Writer writer = Channels.newWriter(
Files.newByteChannel(
Expand All @@ -101,11 +103,8 @@ public static void tree(Collection<UClassNode> nodes, Path outPath) {
public static void src(UClass clazz, Path outPath) {
try (InputStream is = Files.newInputStream(clazz.path, StandardOpenOption.READ)) {
final Path htmlOut = outPath.resolve(clazz.pkg.name.toLowerCase());
try {
if (!Files.isDirectory(htmlOut)) Files.createDirectories(htmlOut);
} catch (IOException e) {
// oops
}

if (!Files.isDirectory(htmlOut)) Files.createDirectories(htmlOut);

Template tpl = TPL_CONFIG.getTemplate("script.ftl");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<body>
<div id="page">
<iframe id="nav" src="tree.html"></iframe>
<iframe id="nav" src="ut99/tree.html"></iframe>

<header><h1 id="header"></h1></header>

Expand Down Expand Up @@ -50,7 +50,7 @@
port1.onmessage = (m) => {
switch (m.data.event) {
case "loaded":
header.innerHTML = m.data.pkg + " / " + m.data.clazz
header.innerHTML = m.data.set + " / " + m.data.pkg + " / " + m.data.clazz
break
default:
console.log("unknown message event ", m.data.type, m.data)
Expand Down
Loading

0 comments on commit 1a371b8

Please sign in to comment.