create and select entries
This commit is contained in:
@@ -14,7 +14,8 @@
|
|||||||
// Assign entries to the Systems that care about them
|
// Assign entries to the Systems that care about them
|
||||||
(doFor =>id entry entries
|
(doFor =>id entry entries
|
||||||
(system.checkEntryInOrOut this entry))
|
(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
|
(defmethod :Entry createEntry [:Entry->Dynamic initializer] // initializer returns Dynamic so ->:Void isn't required
|
||||||
(let [e (_newEntry)]
|
(let [e (_newEntry)]
|
||||||
@@ -34,7 +35,17 @@
|
|||||||
(Path.join [archiveDir "entries" (e.id.withExtension "json")])
|
(Path.join [archiveDir "entries" (e.id.withExtension "json")])
|
||||||
(Json.stringify e)))
|
(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 []
|
(defun :Entry _newEntry []
|
||||||
(object
|
(object
|
||||||
|
@@ -4,6 +4,7 @@ import kiss.Prelude;
|
|||||||
import kiss.List;
|
import kiss.List;
|
||||||
import kiss.Operand;
|
import kiss.Operand;
|
||||||
import haxe.Constraints;
|
import haxe.Constraints;
|
||||||
|
import uuid.Uuid;
|
||||||
|
|
||||||
enum CommandArgType {
|
enum CommandArgType {
|
||||||
SelectedEntry;
|
SelectedEntry;
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
(load "Lib.kiss")
|
||||||
|
|
||||||
(defmethod :Void _collectAndValidateArg [:CommandArg arg :Dynamic->Void continuation]
|
(defmethod :Void _collectAndValidateArg [:CommandArg arg :Dynamic->Void continuation]
|
||||||
(case arg.type
|
(case arg.type
|
||||||
(SelectedEntry
|
(SelectedEntry
|
||||||
@@ -67,7 +69,9 @@
|
|||||||
(< max entries.length))
|
(< max entries.length))
|
||||||
|
|
||||||
(ui.reportError "The requested command expects between $min and $max entries. You chose: $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]
|
(defmethod :Void->Void _composeArgCollector [:Array<Dynamic> collectedArgs :CommandArg arg :Void->Void lastCollector]
|
||||||
(lambda :Void []
|
(lambda :Void []
|
||||||
@@ -90,18 +94,17 @@
|
|||||||
(groups (expList args) 2)
|
(groups (expList args) 2)
|
||||||
methodArgs
|
methodArgs
|
||||||
(for [name type] argPairs
|
(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
|
// and maybe adds back precise pattern matching instead of relying
|
||||||
// on partial string matching
|
// on partial string matching
|
||||||
(let [expAsStr (Std.string type)]
|
(exprCase type
|
||||||
(cond
|
((exprOr SelectedEntry OneEntry) `:nat.Entry ,name)
|
||||||
((< -1 (max (expAsStr.indexOf "SelectedEntry") (expAsStr.indexOf "OneEntry"))) `:nat.Entry ,name)
|
((exprOr (SelectedEntries _ _) (Entries _ _)) `:Array<nat.Entry> ,name)
|
||||||
((< -1 (max (expAsStr.indexOf "SelectedEntries") (expAsStr.indexof "Entries"))) `:Array<nat.Entry> ,name)
|
((Text _ _) `:String ,name)
|
||||||
((< -1 (expAsStr.indexOf "Text")) `:String ,name)
|
((Number _ _ _) `:Float ,name)))
|
||||||
((< -1 (expAsStr.indexOf "Number")) `:Float ,name))))
|
|
||||||
commandArgs
|
commandArgs
|
||||||
(for [name type] argPairs
|
(for [name type] argPairs
|
||||||
~`(object name ,(symbolName name) type ,type))]
|
`(object name ,(symbolName name) type ,type))]
|
||||||
`{
|
`{
|
||||||
(defmethod ,name [,@methodArgs] ,@body)
|
(defmethod ,name [,@methodArgs] ,@body)
|
||||||
(dictSet commands ,(symbolName name) (object args [,@commandArgs] handler (the Function ,name)))}))
|
(dictSet commands ,(symbolName name) (object args [,@commandArgs] handler (the Function ,name)))}))
|
||||||
@@ -115,13 +118,15 @@
|
|||||||
(defcommand selectEntry [e OneEntry]
|
(defcommand selectEntry [e OneEntry]
|
||||||
(set selectedEntries [e]))
|
(set selectedEntries [e]))
|
||||||
|
|
||||||
/*
|
|
||||||
(defcommand selectEntries [entries (Entries null null)]
|
(defcommand selectEntries [entries (Entries null null)]
|
||||||
(set selectedEntries entries))
|
(set selectedEntries entries))
|
||||||
*/
|
|
||||||
|
|
||||||
(defcommand selectLastChangeSet []
|
(defcommand selectLastChangeSet []
|
||||||
(set selectedEntries lastChangeSet))
|
(set selectedEntries lastChangeSet))
|
||||||
|
|
||||||
|
(defcommand printSelectedEntries [entries (SelectedEntries null null)]
|
||||||
|
(doFor e entries (ui.displayMessage (archive.fullString e))))
|
||||||
|
|
||||||
/*(defcommand createEntry [name (Text null null)]
|
(defcommand createEntry [name (Text null null)]
|
||||||
~name)*/)
|
(archive.createEntry ->e
|
||||||
|
(addComponent archive e Name name))))
|
@@ -6,12 +6,12 @@ interface ArchiveUI {
|
|||||||
/**
|
/**
|
||||||
* Prompt the user to enter text
|
* 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
|
* 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
|
* Prompt the user to choose a single Entry
|
||||||
@@ -21,13 +21,18 @@ interface ArchiveUI {
|
|||||||
/**
|
/**
|
||||||
* Prompt the user to choose multiple Entries
|
* 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
|
* Update the interface to reflect changes made to Entries through commands
|
||||||
*/
|
*/
|
||||||
function handleChanges(changeSet:ChangeSet):Void;
|
function handleChanges(changeSet:ChangeSet):Void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the user something useful
|
||||||
|
*/
|
||||||
|
function displayMessage(message:String):Void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the user that something is wrong
|
* Tell the user that something is wrong
|
||||||
*/
|
*/
|
||||||
|
@@ -5,6 +5,7 @@ import kiss.List;
|
|||||||
import kiss.Operand;
|
import kiss.Operand;
|
||||||
import sys.FileSystem;
|
import sys.FileSystem;
|
||||||
import nat.ArchiveController.CommandArgType;
|
import nat.ArchiveController.CommandArgType;
|
||||||
|
using StringTools;
|
||||||
|
|
||||||
@:build(kiss.Kiss.build())
|
@:build(kiss.Kiss.build())
|
||||||
class CLI implements ArchiveUI {}
|
class CLI implements ArchiveUI {}
|
||||||
|
@@ -1,14 +1,20 @@
|
|||||||
|
(load "Lib.kiss")
|
||||||
|
|
||||||
(defun :Void main []
|
(defun :Void main []
|
||||||
(let [[archiveDir] (Sys.args)
|
(let [[archiveDir] (Sys.args)
|
||||||
controller
|
controller
|
||||||
(new ArchiveController
|
(new ArchiveController
|
||||||
(new Archive archiveDir)
|
(new Archive archiveDir)
|
||||||
(new CLI))]
|
(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 [])
|
(defnew [])
|
||||||
|
|
||||||
(defmethod :Void enterText [prompt resolve &opt minLength maxLength]
|
(defmethod :Void enterText [prompt resolve minLength maxLength]
|
||||||
(Sys.print "$prompt ")
|
(Sys.print "$prompt ")
|
||||||
(loop
|
(loop
|
||||||
(let [entered (.toString (.readLine (Sys.stdin)))]
|
(let [entered (.toString (.readLine (Sys.stdin)))]
|
||||||
@@ -17,7 +23,7 @@
|
|||||||
{(resolve entered)
|
{(resolve entered)
|
||||||
(break)}))))
|
(break)}))))
|
||||||
|
|
||||||
(defmethod :Void enterNumber [prompt resolve &opt min max inStepsOf]
|
(defmethod :Void enterNumber [prompt resolve min max &opt inStepsOf]
|
||||||
(Sys.print "$prompt ")
|
(Sys.print "$prompt ")
|
||||||
(loop
|
(loop
|
||||||
(let [entered (Std.parseFloat (.toString (.readLine (Sys.stdin))))]
|
(let [entered (Std.parseFloat (.toString (.readLine (Sys.stdin))))]
|
||||||
@@ -29,12 +35,28 @@
|
|||||||
{(resolve entered)
|
{(resolve entered)
|
||||||
(break)}))))
|
(break)}))))
|
||||||
|
|
||||||
(defmethod :Void chooseEntry [prompt archive resolve]
|
(defmethod :Void chooseEntry [prompt :Archive archive resolve]
|
||||||
(resolve null))
|
// 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 []))
|
(resolve []))
|
||||||
|
|
||||||
(defmethod handleChanges [changeSet])
|
(defmethod handleChanges [changeSet])
|
||||||
|
|
||||||
|
(defmethod :Void displayMessage [message]
|
||||||
|
(print message))
|
||||||
|
|
||||||
(defmethod :Void reportError [error] ~error)
|
(defmethod :Void reportError [error] ~error)
|
@@ -3,7 +3,7 @@ package nat;
|
|||||||
import kiss.Prelude;
|
import kiss.Prelude;
|
||||||
|
|
||||||
typedef EntryChecker = (Archive, Entry) -> Bool;
|
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())
|
@:build(kiss.Kiss.build())
|
||||||
class System {}
|
class System {}
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
(defprop :Map<String,Entry> entries (new Map))
|
(defprop :Map<String,Entry> entries (new Map))
|
||||||
|
|
||||||
(defmethod :Void process [:Archive archive]
|
(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
|
(defnew [&prop :EntryChecker canProcessEntry
|
||||||
&prop :EntryProcessor processEntry]
|
&prop :EntryProcessor processEntry]
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
(load "../Lib.kiss")
|
(load "../Lib.kiss")
|
||||||
|
|
||||||
// TODO make a &super annotation that passes an argument to the super constructor
|
(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
|
||||||
(defnew [&prop :String tagFilterString
|
// TODO make a &super annotation that passes an argument to the super constructor
|
||||||
&prop :EntryProcessor processor]
|
:EntryProcessor processor]
|
||||||
[]
|
[]
|
||||||
(super
|
(super
|
||||||
(lambda [:Archive archive :Entry e] (tagsMatch archive e tagFilterString))
|
(lambda [:Archive archive :Entry e] (tagsMatch archive e tagFilterString))
|
||||||
|
Reference in New Issue
Block a user