technically works... lesgoo

This commit is contained in:
mtgmonkey 2025-06-05 19:15:04 -04:00
parent e134f20fca
commit 17ac128890
6 changed files with 797 additions and 582 deletions

View file

@ -12,10 +12,20 @@
devShells.${system} = { devShells.${system} = {
default = pkgs.mkShell { default = pkgs.mkShell {
nativeBuildInputs = [ nativeBuildInputs = [
pkgs.elmPackages.elm-format
pkgs.elm2nix pkgs.elm2nix
pkgs.elmPackages.elm
pkgs.elmPackages.elm-format
pkgs.elmPackages.elm-json pkgs.elmPackages.elm-json
pkgs.elmPackages.elm-review
pkgs.tokei
]; ];
shellHook = ''
${pkgs.elmPackages.fetchElmDeps {
elmPackages = import ./src/elm2nix/elm-srcs.nix;
elmVersion = "0.19.1";
registryDat = ./src/elm2nix/registry.dat;
}}
'';
}; };
}; };
}; };

View file

@ -1,14 +1,53 @@
module Cli exposing (..) module Cli exposing (..)
{- ( Command
, CommandErr
, FilledCommand
, FilledFlag
, FilledFlagOption
, FilledOption
, Flag
, FlagOption
, Option
, getFlag
, getFlagOption
, getOption
, mkCommand
, parseInput
)
-}
type alias Parameter =
type alias Option =
{ name : String { name : String
} }
type alias FilledParameter = type alias FilledOption =
{ name : String { name : String
, content : String , value : Maybe String
}
type alias Flag =
{ name : String
}
type alias FilledFlag =
{ name : String
, value : Bool
}
type alias FlagOption =
{ name : String
}
type alias FilledFlagOption =
{ name : String
, value : Maybe String
} }
@ -18,13 +57,17 @@ type alias DirtyCommand =
type alias Command = type alias Command =
{ name : String { name : String
, params : List Parameter , opts : List Option
, flags : List Flag
, flagOpts : List FlagOption
} }
type alias FilledCommand = type alias FilledCommand =
{ name : String { name : String
, params : List FilledParameter , opts : List FilledOption
, flags : List FilledFlag
, flagOpts : List FilledFlagOption
} }
@ -34,40 +77,49 @@ type alias CommandErr =
, argumentErr : Maybe ArgumentErr , argumentErr : Maybe ArgumentErr
} }
type ArgumentErr type ArgumentErr
= MissingArgs = MissingArgs
| TooManyArgs | TooManyArgs
| UnrecognisedFlag
parseInput : List Command -> String -> Result CommandErr FilledCommand parseInput : List Command -> String -> Result CommandErr FilledCommand
parseInput commands input = parseInput commands input =
let let
tokens = tokens =
List.map String.trim (String.split " " input) String.words input
tail =
case List.tail tokens of
Just t ->
t
Nothing ->
[]
in in
case List.head tokens of case List.head tokens of
Just maybeCommand -> Just maybeCommand ->
case List.head (List.filter (isCommand maybeCommand) commands) of case List.head (List.filter (isCommand maybeCommand) commands) of
Just command -> Just command ->
case applyArguments command.params tokens of case applyArguments command tail of
Ok list -> Ok filledCommand ->
Ok Ok filledCommand
{ name = command.name
, params = list
}
Err err -> Err err ->
Err { command = Just command Err
{ command = Just command
, got = input , got = input
, argumentErr = Just err , argumentErr = Just err
} }
Nothing -> Nothing ->
Err Err
{ command = Nothing { command = Nothing
, got = input , got = input
, argumentErr = Nothing , argumentErr = Nothing
} }
Nothing -> Nothing ->
Err Err
{ command = Nothing { command = Nothing
@ -76,22 +128,151 @@ parseInput commands input =
} }
applyArguments : List Parameter -> List String -> Result ArgumentErr (List FilledParameter) mkCommand : Command -> Command
applyArguments params inputs = mkCommand command =
if List.length params > List.length inputs then { command | flags = List.append command.flags [ { name = "--help" } ] }
Err MissingArgs
else if List.length params < List.length inputs then
flagsFromTokens : List String -> List String
flagsFromTokens tokens =
tokens
|> List.filter isFlag
flagOptionsFromTokens : List String -> List String
flagOptionsFromTokens flags =
flags
|> List.filter isFlagOption
nonFlagsFromTokens : List String -> List String
nonFlagsFromTokens tokens =
tokens
|> List.filter (not << isFlag)
|> List.filter (not << isFlagOption)
isFlag : String -> Bool
isFlag str =
String.startsWith "--" str && not (String.contains "=" str)
isFlagOption : String -> Bool
isFlagOption str =
String.startsWith "--" str && isOnlyOnce "=" str
isOnlyOnce : String -> String -> Bool
isOnlyOnce a b =
1 == List.length (String.indices a b)
applyArguments : Command -> List String -> Result ArgumentErr FilledCommand
applyArguments command tokens =
let
opts =
command.opts
flags =
command.flags
flagOpts =
command.flagOpts
flagIns =
flagsFromTokens tokens
flagOptIns =
flagOptionsFromTokens tokens
nonFlagIns =
nonFlagsFromTokens tokens
in
if List.length opts < List.length nonFlagIns then
Err TooManyArgs Err TooManyArgs
else
Ok (List.map2 applyParameter params inputs)
else if List.any (\m -> not (List.member { name = m } flags)) flagIns then
Err UnrecognisedFlag
else if
List.any
(\m ->
not
(List.member
{ name =
case List.head (String.split "=" m) of
Just head ->
head
applyParameter : Parameter -> String -> FilledParameter Nothing ->
applyParameter param input = ""
{ name = param.name
, content = input
} }
flagOpts
)
)
flagOptIns
then
Err UnrecognisedFlag
else
let
optionInputs =
expandList (List.map Just nonFlagIns) (List.length opts)
in
Ok
{ name = command.name
, opts = List.map2 applyOption opts optionInputs
, flags = List.map (fillFlag flagIns) flags
, flagOpts = List.map (fillFlagOption flagOptIns) flagOpts
}
applyOption : Option -> Maybe String -> FilledOption
applyOption option input =
{ name = option.name
, value = input
}
fillFlag : List String -> Flag -> FilledFlag
fillFlag flagTokens flag =
if List.member flag.name flagTokens then
{ name = flag.name
, value = True
}
else
{ name = flag.name
, value = False
}
fillFlagOption : List String -> FlagOption -> FilledFlagOption
fillFlagOption flagOptIns flagOption =
let
flag =
case flagOptIns
|> List.filter (\m->String.contains flagOption.name m)
|> List.head
of
Just head ->
Just <| String.dropLeft (1 + String.length flagOption.name) head
Nothing ->
Nothing
in
{ name = flagOption.name
, value = flag
}
expandList : List (Maybe String) -> Int -> List (Maybe String)
expandList input len =
if List.length input >= len then
List.take len input
else
expandList (List.append input [ Nothing ]) len
isCommand : String -> Command -> Bool isCommand : String -> Command -> Bool
@ -101,3 +282,36 @@ isCommand name command =
else else
False False
getOption : FilledCommand -> String -> FilledOption
getOption command name =
case List.head <| List.filter (\m->m.name == name) command.opts of
Just head ->
head
Nothing ->
{ name = name
, value = Nothing
}
getFlag : FilledCommand -> String -> FilledFlag
getFlag command name =
case List.head <| List.filter (\m->m.name == name) command.flags of
Just head ->
head
Nothing ->
{ name = name
, value = False
}
getFlagOption : FilledCommand -> String -> FilledFlagOption
getFlagOption command name =
case List.head <| List.filter (\m->m.name == name) command.flagOpts of
Just head ->
head
Nothing ->
{ name = name
, value = Nothing
}

View file

@ -1,12 +1,111 @@
module Commands exposing (..) module Commands exposing (..)
import Cli exposing (Command) import Cli exposing (Command, mkCommand)
greet : Command commands : List Command
greet = commands =
{ name = "greet" [ help
, params = [ , clear
{ name = "name" , colors
} ] , cookies
, debug
, environment
, hello
, todo
]
help : Command
help =
{ name = "help"
, opts =
[ { name = "command" }
]
, flags = []
, flagOpts = []
} }
|> mkCommand
clear : Command
clear =
{ name = "clear"
, opts = []
, flags = []
, flagOpts = []
}
|> mkCommand
colors : Command
colors =
{ name = "colors"
, opts =
[ { name = "show" }
]
, flags = []
, flagOpts = []
}
|> mkCommand
cookies : Command
cookies =
{ name = "cookies"
, opts =
[ { name = "show" }
]
, flags = []
, flagOpts =
[ { name = "--keepFont" }
, { name = "--keepPrompt" }
, { name = "--keepTheme" }
]
}
|> mkCommand
debug : Command
debug =
{ name = "debug"
, opts = []
, flags = []
, flagOpts = []
}
|> mkCommand
environment : Command
environment =
{ name = "environment"
, opts =
[ { name = "show" }
]
, flags = []
, flagOpts =
[ { name = "--theme" }
, { name = "--fontsize" }
, { name = "--prompt" }
]
}
|> mkCommand
hello : Command
hello =
{ name = "hello"
, opts = []
, flags = []
, flagOpts = []
}
|> mkCommand
todo : Command
todo =
{ name = "todo"
, opts = []
, flags = []
, flagOpts = []
} |> mkCommand

31
src/ElmTypes.elm Normal file
View file

@ -0,0 +1,31 @@
module ElmTypes exposing (Model)
import Browser
import Browser.Navigation as Nav
import Cli
import Json.Encode as E
import Url
type alias Model =
{ key : Nav.Key
, url : Url.Url
, theme : Theme
, font : Font
, cookiesKept : CookiesKept
, prompt : Prompt
, content : List (Html Msg)
, cliContent : String
}
type Msg
= LinkClicked Browser.UrlRequest
| UrlChanged Url.Url
| TakeInput String
| NoInitFocus
| ReceivedStorage E.Value
type alias CommandRunner =
Model -> List String -> ( Model, Cmd Msg )

File diff suppressed because it is too large Load diff

37
src/Types.elm Normal file
View file

@ -0,0 +1,37 @@
module Types exposing (..)
import Browser
import Browser.Navigation
import Cli
import ElmskellTypes.Generated.Types exposing (..)
import Html.Styled
import Json.Encode
import Url
type Msg
= LinkClicked Browser.UrlRequest
| UrlChanged Url.Url
| TakeInput String
| NoInitFocus
| ReceivedStorage Json.Encode.Value
type alias Model =
{ key : Browser.Navigation.Key
, url : Url.Url
, theme : Theme
, font : Font
, cookiesKept : CookiesKept
, prompt : Prompt
, content : List (Html.Styled.Html Msg)
, cliContent : String
}
type alias CommandRunner_ =
Model -> List String -> ( Model, Cmd Msg )
type alias CommandRunner =
Model -> Cli.FilledCommand -> ( Model, Cmd Msg )