create and select entries

This commit is contained in:
2021-06-26 21:42:04 -06:00
parent 8d98ca136c
commit e4e152d26c
9 changed files with 76 additions and 29 deletions

View File

@@ -14,7 +14,8 @@
// Assign entries to the Systems that care about them
(doFor =>id entry entries
(system.checkEntryInOrOut this entry))
(systems.push system))
(systems.push system)
system)
(defmethod :Entry createEntry [:Entry->Dynamic initializer] // initializer returns Dynamic so ->:Void isn't required
(let [e (_newEntry)]
@@ -34,7 +35,17 @@
(Path.join [archiveDir "entries" (e.id.withExtension "json")])
(Json.stringify e)))
// TODO adding or removing components or files should save the Entry and re-check it in or out of systems
(defmethod fullData [:Entry e]
(object
id e.id
components
(for =>type id e.components
=>type (haxe.Json.parse (File.getContent (haxe.io.Path.join [archiveDir "components" "$(dictGet e.components type).json"]))))
files
e.files))
(defmethod fullString [:Entry e]
(haxe.Json.stringify (fullData e) null "\t"))
(defun :Entry _newEntry []
(object

View File

@@ -4,6 +4,7 @@ import kiss.Prelude;
import kiss.List;
import kiss.Operand;
import haxe.Constraints;
import uuid.Uuid;
enum CommandArgType {
SelectedEntry;

View File

@@ -1,3 +1,5 @@
(load "Lib.kiss")
(defmethod :Void _collectAndValidateArg [:CommandArg arg :Dynamic->Void continuation]
(case arg.type
(SelectedEntry
@@ -67,7 +69,9 @@
(< max entries.length))
(ui.reportError "The requested command expects between $min and $max entries. You chose: $entries.length")
(continuation selectedEntries)))))))
(continuation selectedEntries)))
min
max))))
(defmethod :Void->Void _composeArgCollector [:Array<Dynamic> collectedArgs :CommandArg arg :Void->Void lastCollector]
(lambda :Void []
@@ -90,18 +94,17 @@
(groups (expList args) 2)
methodArgs
(for [name type] argPairs
// TODO write a macroCase macro that simplifies this terrible mess,
// TODO write an exprCase macro that simplifies this terrible mess,
// and maybe adds back precise pattern matching instead of relying
// on partial string matching
(let [expAsStr (Std.string type)]
(cond
((< -1 (max (expAsStr.indexOf "SelectedEntry") (expAsStr.indexOf "OneEntry"))) `:nat.Entry ,name)
((< -1 (max (expAsStr.indexOf "SelectedEntries") (expAsStr.indexof "Entries"))) `:Array<nat.Entry> ,name)
((< -1 (expAsStr.indexOf "Text")) `:String ,name)
((< -1 (expAsStr.indexOf "Number")) `:Float ,name))))
(exprCase type
((exprOr SelectedEntry OneEntry) `:nat.Entry ,name)
((exprOr (SelectedEntries _ _) (Entries _ _)) `:Array<nat.Entry> ,name)
((Text _ _) `:String ,name)
((Number _ _ _) `:Float ,name)))
commandArgs
(for [name type] argPairs
~`(object name ,(symbolName name) type ,type))]
`(object name ,(symbolName name) type ,type))]
`{
(defmethod ,name [,@methodArgs] ,@body)
(dictSet commands ,(symbolName name) (object args [,@commandArgs] handler (the Function ,name)))}))
@@ -115,13 +118,15 @@
(defcommand selectEntry [e OneEntry]
(set selectedEntries [e]))
/*
(defcommand selectEntries [entries (Entries null null)]
(set selectedEntries entries))
*/
(defcommand selectLastChangeSet []
(set selectedEntries lastChangeSet))
(defcommand printSelectedEntries [entries (SelectedEntries null null)]
(doFor e entries (ui.displayMessage (archive.fullString e))))
/*(defcommand createEntry [name (Text null null)]
~name)*/)
(defcommand createEntry [name (Text null null)]
(archive.createEntry ->e
(addComponent archive e Name name))))

View File

@@ -6,12 +6,12 @@ interface ArchiveUI {
/**
* Prompt the user to enter text
*/
function enterText(prompt:String, resolve:(String) -> Void, ?minLength:Int, ?maxLength:Float):Void;
function enterText(prompt:String, resolve:(String) -> Void, minLength:Int, maxLength:Float):Void;
/**
* Prompt the user to enter a number
*/
function enterNumber(prompt:String, resolve:(Float) -> Void, ?min:Float, ?max:Float, ?inStepsOf:Float):Void;
function enterNumber(prompt:String, resolve:(Float) -> Void, min:Float, max:Float, ?inStepsOf:Float):Void;
/**
* Prompt the user to choose a single Entry
@@ -21,13 +21,18 @@ interface ArchiveUI {
/**
* Prompt the user to choose multiple Entries
*/
function chooseEntries(prompt:String, archive:Archive, resolve:(Array<Entry>) -> Void, ?min:Int, ?max:Float):Void;
function chooseEntries(prompt:String, archive:Archive, resolve:(Array<Entry>) -> Void, min:Int, max:Float):Void;
/**
* Update the interface to reflect changes made to Entries through commands
*/
function handleChanges(changeSet:ChangeSet):Void;
/**
* Tell the user something useful
*/
function displayMessage(message:String):Void;
/**
* Tell the user that something is wrong
*/

View File

@@ -5,6 +5,7 @@ import kiss.List;
import kiss.Operand;
import sys.FileSystem;
import nat.ArchiveController.CommandArgType;
using StringTools;
@:build(kiss.Kiss.build())
class CLI implements ArchiveUI {}

View File

@@ -1,14 +1,20 @@
(load "Lib.kiss")
(defun :Void main []
(let [[archiveDir] (Sys.args)
controller
(new ArchiveController
(new Archive archiveDir)
(new CLI))]
(controller.runCommand (dictGet controller.commands "selectEntry"))))
(loop
(Sys.print ">> ")
(let [command
(.trim (.toString (.readLine (Sys.stdin))))]
(controller.runCommand (dictGet controller.commands command))))))
(defnew [])
(defmethod :Void enterText [prompt resolve &opt minLength maxLength]
(defmethod :Void enterText [prompt resolve minLength maxLength]
(Sys.print "$prompt ")
(loop
(let [entered (.toString (.readLine (Sys.stdin)))]
@@ -17,7 +23,7 @@
{(resolve entered)
(break)}))))
(defmethod :Void enterNumber [prompt resolve &opt min max inStepsOf]
(defmethod :Void enterNumber [prompt resolve min max &opt inStepsOf]
(Sys.print "$prompt ")
(loop
(let [entered (Std.parseFloat (.toString (.readLine (Sys.stdin))))]
@@ -29,12 +35,28 @@
{(resolve entered)
(break)}))))
(defmethod :Void chooseEntry [prompt archive resolve]
(resolve null))
(defmethod :Void chooseEntry [prompt :Archive archive resolve]
// TODO allow narrowing down with a tag string
(enterText "entry name for $prompt"
->name {
(let [matchingEntries []]
(.process (archive.addSystem
(stringComponentSystem archive Name name
(lambda [archive e]
(matchingEntries.push e)))) archive)
(defmethod :Void chooseEntries [prompt archive resolve &opt min max]
(case (the Array<Entry> matchingEntries)
([e] (resolve e))
// TODO disambiguate entries with the same names by listing stringified versions of them and using enterNumber
(multipleEntries (throw "ambiguous between multiple entries"))))}
0 Math.POSITIVE_INFINITY))
(defmethod :Void chooseEntries [prompt archive resolve min max]
(resolve []))
(defmethod handleChanges [changeSet])
(defmethod :Void displayMessage [message]
(print message))
(defmethod :Void reportError [error] ~error)

View File

@@ -3,7 +3,7 @@ package nat;
import kiss.Prelude;
typedef EntryChecker = (Archive, Entry) -> Bool;
typedef EntryProcessor = (Archive, Entry) -> Void;
typedef EntryProcessor = (Archive, Entry) -> Dynamic; // Whatever value is returned will be dropped, but this is easier than requiring ->:Void
@:build(kiss.Kiss.build())
class System {}

View File

@@ -1,7 +1,9 @@
(defprop :Map<String,Entry> entries (new Map))
(defmethod :Void process [:Archive archive]
(doFor e (entries.iterator) (processEntry archive e)))
(doFor e (entries.iterator)
(processEntry archive e)
(archive.refreshEntry e)))
(defnew [&prop :EntryChecker canProcessEntry
&prop :EntryProcessor processEntry]

View File

@@ -1,8 +1,8 @@
(load "../Lib.kiss")
// TODO make a &super annotation that passes an argument to the super constructor
(defnew [&prop :String tagFilterString
&prop :EntryProcessor processor]
(defnew [&prop :String tagFilterString // This doesn't need to be a &prop because it will be captured by the lambda, but maybe it will be useful to query from the system later
// TODO make a &super annotation that passes an argument to the super constructor
:EntryProcessor processor]
[]
(super
(lambda [:Archive archive :Entry e] (tagsMatch archive e tagFilterString))