Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
398 changes: 398 additions & 0 deletions java/PhaseNote.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,398 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import java.util.stream.Collectors;

// Start of Phase 1 Notes
public class PhaseNote {
private static final Path NOTES_DIR = Path.of(System.getProperty("user.home"), ".notes");

public static void main(String[] args) {
if (args.length < 1) {
System.err.println("Error: No command provided.");
System.err.println("Usage: java PhaseNote [command]");
System.err.println("Try 'java PhaseNote help' for more information.");
System.exit(1);
}

String command = args[0].toLowerCase();
switch (command) {
case "help" -> {
showHelp();
System.exit(0);
}
case "list" -> {
boolean success = listNotes(NOTES_DIR);
System.exit(success ? 0 : 1);
}
case "create" -> {
boolean success = createNote(NOTES_DIR);
System.exit(success ? 0 : 1);
}
case "read" -> {
if (args.length < 2) {
System.err.println("Error: No note number provided.");
System.err.println("Usage: java PhaseNote read [note-number]");
System.exit(1);
}
try {
int noteNumber = Integer.parseInt(args[1]);
boolean success = readNote(NOTES_DIR, noteNumber);
System.exit(success ? 0 : 1);
} catch (NumberFormatException e) {
System.err.println("Error: Invalid note number '" + args[1] + "'");
System.exit(1);
}
}
case "delete" -> {
if (args.length < 2) {
System.err.println("Error: No note number provided.");
System.err.println("Usage: java PhaseNote delete [note-number]");
System.exit(1);
}
try {
int noteNumber = Integer.parseInt(args[1]);
boolean success = deleteNote(NOTES_DIR, noteNumber);
System.exit(success ? 0 : 1);
} catch (NumberFormatException e) {
System.err.println("Error: Invalid note number '" + args[1] + "'");
System.exit(1);
}
}
case "edit" -> {
if (args.length < 2) {
System.err.println("Error: No note number provided.");
System.err.println("Usage: java PhaseNote edit [note-number]");
System.exit(1);
}
try {
int noteNumber = Integer.parseInt(args[1]);
boolean success = editNote(NOTES_DIR, noteNumber);
System.exit(success ? 0 : 1);
} catch (NumberFormatException e) {
System.err.println("Error: Invalid note number '" + args[1] + "'");
System.exit(1);
}
}
default -> {
System.err.println("Error: Unknown command '" + command + "'");
System.err.println("Try 'java PhaseNote help' for more information.");
System.exit(1);
}
}
}

private static Map<String, String> parseYamlHeader(Path path) {
Map<String, String> metadata = new HashMap<>();
metadata.put("file", path.getFileName().toString());

try {
List<String> lines = Files.readAllLines(path);
if (lines.isEmpty() || !lines.get(0).trim().equals("---")) {
metadata.put("title", path.getFileName().toString());
return metadata;
}

// Find the closing ---
int closingIndex = -1;
for (int i = 1; i < lines.size(); i++) {
if (lines.get(i).trim().equals("---")) {
closingIndex = i;
break;
}
}

if (closingIndex == -1) {
metadata.put("title", path.getFileName().toString());
return metadata;
}

// Parse key-value pairs between the markers
for (int i = 1; i < closingIndex; i++) {
String line = lines.get(i).trim();
if (line.contains(":")) {
String[] parts = line.split(":", 2);
metadata.put(parts[0].trim(), parts[1].trim());
}
}
} catch (IOException e) {
metadata.put("error", e.getMessage());
}

return metadata;
}

private static boolean listNotes(Path baseDir) {
if (!Files.exists(baseDir)) {
System.err.println("Error: Notes directory does not exist: " + baseDir);
System.err.println("Create it with: mkdir -p ~/.notes/notes");
return false;
}

Path searchPath = Files.exists(baseDir.resolve("notes")) ? baseDir.resolve("notes") : baseDir;
List<Path> noteFiles;

try (Stream<Path> walk = Files.walk(searchPath, 1)) {
noteFiles = walk
.filter(Files::isRegularFile)
.filter(p -> {
String name = p.getFileName().toString();
return name.endsWith(".md") || name.endsWith(".note") || name.endsWith(".txt");
})
.sorted()
.collect(Collectors.toList());
} catch (IOException e) {
System.err.println("Error reading notes directory: " + e.getMessage());
return false;
}

if (noteFiles.isEmpty()) {
System.out.println("No notes found in " + baseDir);
return true;
}

System.out.println("Notes in " + baseDir + ":");
System.out.println("=".repeat(60));

for (int i = 0; i < noteFiles.size(); i++) {
Path file = noteFiles.get(i);
Map<String, String> metadata = parseYamlHeader(file);
String title = metadata.getOrDefault("title", file.getFileName().toString());
String created = metadata.getOrDefault("created", "N/A");
String tags = metadata.getOrDefault("tags", "");

System.out.println("\n[" + (i + 1) + "] " + file.getFileName());
System.out.println(" Title: " + title);
if (!"N/A".equals(created)) System.out.println(" Created: " + created);
if (!tags.isEmpty()) System.out.println(" Tags: " + tags);
}

System.out.println("\n" + noteFiles.size() + " note(s) found.");
return true;
}


// createNote
private static boolean createNote(Path baseDir) {
if (!Files.exists(baseDir)) {
System.err.println("Error: Notes directory does not exist: " + baseDir);
System.err.println("Create it with: mkdir -p ~/.notes/notes");
return false;
}

Path notesPath = baseDir.resolve("notes");
if (!Files.exists(notesPath)) {
try {
Files.createDirectories(notesPath);
} catch (IOException e) {
System.err.println("Error creating notes directory: " + e.getMessage());
return false;
}
}

try {
// Create a new note with timestamp-based filename
String timestamp = java.time.LocalDateTime.now().format(
java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
String filename = "note_" + timestamp + ".md";
Path newNotePath = notesPath.resolve(filename);

// Create note content with YAML header
String noteContent = String.format("""
---
title: New Note
created: %s
tags:
---

""", java.time.LocalDate.now().toString());

Files.writeString(newNotePath, noteContent);
System.out.println("Note created successfully: " + newNotePath);
return true;
} catch (IOException e) {
System.err.println("Error creating note: " + e.getMessage());
return false;
}
}

// readNote
private static boolean readNote(Path baseDir, int noteNumber) {
if (!Files.exists(baseDir)) {
System.err.println("Error: Notes directory does not exist: " + baseDir);
return false;
}

Path searchPath = Files.exists(baseDir.resolve("notes")) ? baseDir.resolve("notes") : baseDir;
List<Path> noteFiles;

try (Stream<Path> walk = Files.walk(searchPath, 1)) {
noteFiles = walk
.filter(Files::isRegularFile)
.filter(p -> {
String name = p.getFileName().toString();
return name.endsWith(".md") || name.endsWith(".note") || name.endsWith(".txt");
})
.sorted()
.collect(Collectors.toList());
} catch (IOException e) {
System.err.println("Error reading notes directory: " + e.getMessage());
return false;
}

// Check if note number is valid
if (noteNumber < 1 || noteNumber > noteFiles.size()) {
System.err.println("Error: Note number " + noteNumber + " not found. Valid range: 1-" + noteFiles.size());
return false;
}

try {
Path notePath = noteFiles.get(noteNumber - 1);
String content = Files.readString(notePath);
System.out.println(content);
return true;
} catch (IOException e) {
System.err.println("Error reading note: " + e.getMessage());
return false;
}
}

// deleteNote
private static boolean deleteNote(Path baseDir, int noteNumber) {
if (!Files.exists(baseDir)) {
System.err.println("Error: Notes directory does not exist: " + baseDir);
return false;
}

Path searchPath = Files.exists(baseDir.resolve("notes")) ? baseDir.resolve("notes") : baseDir;
List<Path> noteFiles;

try (Stream<Path> walk = Files.walk(searchPath, 1)) {
noteFiles = walk
.filter(Files::isRegularFile)
.filter(p -> {
String name = p.getFileName().toString();
return name.endsWith(".md") || name.endsWith(".note") || name.endsWith(".txt");
})
.sorted()
.collect(Collectors.toList());
} catch (IOException e) {
System.err.println("Error reading notes directory: " + e.getMessage());
return false;
}

// Check if note number is valid
if (noteNumber < 1 || noteNumber > noteFiles.size()) {
System.err.println("Error: Note number " + noteNumber + " not found. Valid range: 1-" + noteFiles.size());
return false;
}

try {
Path notePath = noteFiles.get(noteNumber - 1);
Files.delete(notePath);
System.out.println("Note deleted successfully: " + notePath.getFileName());
return true;
} catch (IOException e) {
System.err.println("Error deleting note: " + e.getMessage());
return false;
}
}

// editNote
private static boolean editNote(Path baseDir, int noteNumber) {
if (!Files.exists(baseDir)) {
System.err.println("Error: Notes directory does not exist: " + baseDir);
return false;
}

Path searchPath = Files.exists(baseDir.resolve("notes")) ? baseDir.resolve("notes") : baseDir;
List<Path> noteFiles;

try (Stream<Path> walk = Files.walk(searchPath, 1)) {
noteFiles = walk
.filter(Files::isRegularFile)
.filter(p -> {
String name = p.getFileName().toString();
return name.endsWith(".md") || name.endsWith(".note") || name.endsWith(".txt");
})
.sorted()
.collect(Collectors.toList());
} catch (IOException e) {
System.err.println("Error reading notes directory: " + e.getMessage());
return false;
}

// Check if note number is valid
if (noteNumber < 1 || noteNumber > noteFiles.size()) {
System.err.println("Error: Note number " + noteNumber + " not found. Valid range: 1-" + noteFiles.size());
return false;
}

try {
Path notePath = noteFiles.get(noteNumber - 1);

// Read current content
String currentContent = Files.readString(notePath);
System.out.println("Current note content:");
System.out.println("=".repeat(60));
System.out.println(currentContent);
System.out.println("=".repeat(60));

// Open editor for user input
System.out.print("Enter new content (or type 'quit' on a new line to cancel):\n");
java.util.Scanner scanner = new java.util.Scanner(System.in);
StringBuilder newContent = new StringBuilder();
String line;

while (scanner.hasNextLine()) {
line = scanner.nextLine();
if (line.equals("quit")) {
System.out.println("Edit cancelled.");
return false;
}
newContent.append(line).append("\n");
}

// Write updated content back to file
Files.writeString(notePath, newContent.toString());
System.out.println("Note updated successfully: " + notePath.getFileName());
return true;
} catch (IOException e) {
System.err.println("Error editing note: " + e.getMessage());
return false;
}
}

private static void showHelp() {
String helpText = String.format("""
Future Proof Notes Manager v0.1

Usage: java PhaseNote [command]

Available commands:
help - Display this help information
list - List all notes in the notes directory
create - Create a new note
read - Read a note by number (use list to see note numbers)
edit - Edit a note by number (use list to see note numbers)
delete - Delete a note by number (use list to see note numbers)

Examples:
java PhaseNote list
java PhaseNote read 1
java PhaseNote edit 1
java PhaseNote delete 1

Notes directory: %s

Setup:
mkdir -p ~/.notes/notes
cp test-notes/*.md ~/.notes/notes/
""", NOTES_DIR);
System.out.println(helpText.trim());
}
}
File renamed without changes.