Git Product home page Git Product logo

kale's Introduction

kale

Build Status Coverage Status

A tool for creating command line interfaces.

Beginners Welcome!

This is a great project to contribute to if you'd like experience working on a real-world practical Haskell codebase. There are a number of issues in the issue tracker, each of which should have enough information to get you started. If you need more information or would like advice on implementing, feel free to post a comment and I'll be happy to help out.

Developing

To hack on kale, you'll need the stack build tool. If you'd prefer to use another tool, please make an issue and file a pull request.

The example directory contains an example project. This acts as both documentation and an integration test. While hacking, you can run make test to run the unit tests and build the example project.

You can run make lint to run hlint over the project.

For a super fast reload and test runner, use make ghcid.

kale's People

Contributors

colinwahl avatar naddleman avatar parsonsmatt avatar tmciver avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

kale's Issues

Instead of hardcoding values, use a Config type

Right now, a ton of things are hardcoded. This is less than ideal. A Config type would be a better way to centralize these points of configuration.

data Config = Config 
  { configMainIs :: String -- ^ Name of the main function to be exported.
  , ...
  }
  • Add a Config data type to the library
  • For hardcoded values, refer to the Config instead.
  • (optional): Refactor the library to use ReaderT Config IO a instead of Config -> IO a as the type of functions.

Search for and import an Import module

As noted in #1, if a user uses non-Prelude types for arguments, they'll be out of scope when copying them into the arguments datatype.

For a Foo module with the preprocessor, we should search for Foo.Import, and import that. That module will need to provide all of the types for the import to work.

Use a Syntax data type instead of smashing strings together

Right now, the rendering function looks something like:

unlines
  [ "module " ++ something ++ " where"
  , "import Kale.Discovery"
  , makeSomeString
  , "woo i love strings"
  ]

This kinda sucks! Instead, let's write some limited data types that represents the syntax we want.

data Syntax = ...

data Import = Import Module (Maybe Qualified)

Etc. Finally, we'll write a function render :: Syntax -> String that will be used to turn this into valid Haskell.

Write more types!

Use newtype over the various Strings that are being passed around to make it difficult to mix them up.

Write more tests!

There's a ton of String -> String crap going on in here. Going to need more tests to make sure it's right.

Load configuration

Issue #10 says that we need to have a configuration data type. How do we load that configuration?

Idea: allow the user to specify a config-as-Haskell code that is imported from a specific location.

I think I'm mostly a fan of 3, as we already need to provide the user a way to import a module to provide relevant types (as raised in issue #1). If that module contains a kaleConfig value, then we can import it and use it.

Depending on the type of kaleConfig, we could handle it in different ways:

  1. kaleConfig :: Config = just use this
  2. kaleConfig :: Config -> Config = given the defaults, modify them like this
  3. kaleConfig :: IO Config = bind this out of IO
  4. kaleConfig :: Config -> IO Config = given the defaults, load this configuration

Command line arguments should work for positional arguments, too.

Currently, the argument parser only accepts named arguments:

module AsdfTask where

data Args = Args { foo :: String }

generates a command line task used like asdf --foo hello

We should also accept positional arguments:

module PosTask where

data Args = Args String Int

which generates a command line task like pos hello 10

Command Line Arguments

kale needs to be able to handle parsing command line arguments, implicitly.

Current strategy

Search for a data Args = Args data type. If it is not present, then we ignore it. If it is not a product type, then we should fail loudly, probably.

Extract the text of the record. So data Args = Args Int gives us Int. data Args = Args { userName :: String } is {userName :: String }. data Args = Args { fooId :: Int <?> "The Foo's ID" } gives us { fooId :: Int <?> "The Foo's ID" }.

Paste the text of the arguments to the record into the creation of that variant of the sum type. So if we have

module FooTask where

data Args = Args { userName :: String }

then the generated code should do:

data Command
  = Foo { userName :: String }

A problem with this is that any duplicate fields need to share a type.

Then, we'll need to transform the Command arguments into the Args constructor:

case cmd of
  Foo {..} -> FooTask.task FooTask.Args {..}

is probably sufficient. hooray for recordwildcards!

Write documentation

This project needs:

  1. Haddock API documentation.
  2. Example projects
  3. Tutorials on getting started
  4. A solid README

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.