Git Product home page Git Product logo

Comments (18)

tmciver avatar tmciver commented on August 17, 2024

@parsonsmatt I'd like to take a stab at this since I'm not really sure what this project's purpose is and I figure writing the docs would be a good way to find out. :) Perhaps you could describe the purpose in a little more detail and/or provide an example use case.

Looking at the code it seems to me that this app will generate Haskell source code for user-provided "Tasks" in a particular location that are not known to kale at compile time. These tasks would do . . . what? Anything? This seems to be in the spirit of other command line tools like git, for example, that have sub-commands (git branch, git checkout, etc.). In this case it would be kale runMySpecialCommand or kale runThisOtherSpecialCommand. Am I close?

from kale.

parsonsmatt avatar parsonsmatt commented on August 17, 2024

That's the idea!

There's a decent amount of boilerplate associated with writing a command line parsing utility, and most of it can be discovered and automated away. Stuff like optparse-generic goes a really long way to making it declarative and gets rid of 99% of the boilerplate, but we can do better :)

The "big idea" is to discover all the modules with a form:

module Lib.FooTask where

data Args = Args { i am command line arguments for the program }

task :: Args -> IO ()
task args = ...

And create a nice command line interface for calling them. What the users end up doing is totally up to them, this library's purpose is to eliminate the boilerplate of:

module Task where

import qualified Lib.FooTask as FooTask
import qualified Lib.BarTask as BarTask
-- ...

data Command = Foo { fooArgs ... } | Bar { barArgs ... } | ...
  deriving (Generic, ParseRecord)

main :: IO ()
main = do
  cmd <- getRecord "the program"
  case cmd of
    Foo  {..} -> FooTask.task FooTask.Args {..}
    Bar {..} -> BarTask.task BarTask.Args {..}
    ...

from kale.

tmciver avatar tmciver commented on August 17, 2024

Thanks for the speedy response! This is great and is enough to get me started. PR coming your way soon.

from kale.

tmciver avatar tmciver commented on August 17, 2024

I seem to be having a little trouble with Haddock (I've never used it before). I added several docs to functions in Kale.hs and when I run

$ cabal haddock

I see this output:

Running Haddock for kale-0.1.0.0...
Preprocessing library kale-0.1.0.0...
Warning: The documentation for the following packages are not installed. No
links will be generated to these packages: Only-0.1, ansi-terminal-0.7.1.1,
ansi-wl-pprint-0.6.8.1, colour-2.3.3, optparse-applicative-0.14.0.0,
optparse-generic-1.2.3, semigroups-0.18.3, system-filepath-0.4.13.4,
text-1.2.2.2, transformers-compat-0.5.1.4, void-0.7.2
target ‘command’ is not a module name or a source file

And no documentation is generated. Any ideas?

from kale.

parsonsmatt avatar parsonsmatt commented on August 17, 2024

I'd suggest using stack for building documentation. stack haddock works for me on the master branch.

If you want to open a PR, I can take a look at it :)

from kale.

tmciver avatar tmciver commented on August 17, 2024

I have a couple of questions regarding Kale's command line arguments. First, this line takes the first and third command line arguments and ignore the second and fourth. Why is that? What are the second and fourth arguments supposed to be?

On this line it says that Kale doesn't take command line arguments. It seems that this is a misstatement, correct?

from kale.

parsonsmatt avatar parsonsmatt commented on August 17, 2024

Good questions!

The GHC preprocesser step provides some arguments to the executable that's used to process the source file. I don't know what the arguments do exactly -- I copied the structure from hspec-discover.

The arguments that Kale takes are provided by GHC. It doesn't accept any user arguments.

from kale.

tmciver avatar tmciver commented on August 17, 2024

OK. That leads to a question I've had about the intended workflow of Kale. Is Kale expected to be executed as part the client project's build? How exactly? It sounds like you intend for it to be run by hspec, correct?

from kale.

parsonsmatt avatar parsonsmatt commented on August 17, 2024

GHC has a textual preprocessor step that allows you to provide your own way to manipulate the source files. It calls the executable and that executable writes a Haskell source file to disk, which GHC then compiles as usual.

So kale gets called in this step, discovers all the task modules, and then writes a Haskell file that GHC compiles and runs.

from kale.

tmciver avatar tmciver commented on August 17, 2024

@parsonsmatt Thanks for the info. I did not know that GHC had such a textual preprocessing step and some quick googling only seems to lead me to CPP-related stuff but I suspect that is not what's at play here. Can you give more information about this or perhaps a link? In particular, I'm interested to know how you "provide your own way to manipulate the source files." Where do you tell GHC to call Kale's main function?

from kale.

parsonsmatt avatar parsonsmatt commented on August 17, 2024

This file in the example is where it is called. I found the pgmF flag thanks to hspec and it's discovery feature.

from kale.

tmciver avatar tmciver commented on August 17, 2024

I've created test client application for Kale here but when I run stack build, I get the following error:

$ stack build
kaletest-0.1.0.0: configure (lib + exe)
colour-2.3.4: download
kaletest-0.1.0.0: build (lib + exe)
Only-0.1: configure
Only-0.1: build
semigroups-0.18.3: configure
semigroups-0.18.3: build
colour-2.3.4: configure
colour-2.3.4: build
semigroups-0.18.3: copy/register
Only-0.1: copy/register
colour-2.3.4: copy/register
Log files have been written to: /home/tim/workspace/haskell/kaletest/.stack-work/logs/
Progress: 4/13
--  While building custom Setup.hs for package kaletest-0.1.0.0 using:
      /home/tim/.stack/setup-exe-cache/x86_64-linux/Cabal-simple_mPHDZzAJ_2.0.1.0_ghc-8.2.2 --builddir=.stack-work/dist/x86_64-linux/Cabal-2.0.1.0 build lib:kaletest exe:kaletest-exe --ghc-options " -ddump-hi -ddump-to-file -fdiagnostics-color=always"
    Process exited with code: ExitFailure 1
    Logs have been written to: /home/tim/workspace/haskell/kaletest/.stack-work/logs/kaletest-0.1.0.0.log

    Configuring kaletest-0.1.0.0...
    Preprocessing library for kaletest-0.1.0.0..
    Building library for kaletest-0.1.0.0..
    ["src/Lib.hs","src/Lib.hs","/tmp/ghc456_0/ghc_1.hspp"]
    [2 of 3] Compiling Lib              ( src/Lib.hs, .stack-work/dist/x86_64-linux/Cabal-2.0.1.0/build/Lib.o )
    
    /home/tim/workspace/haskell/kaletest/src/Lib.hs:10:1: error:
        Could not find module ‘Kale.Discover’
        Use -v to see a list of the files searched for.

It seems that GHC is looking for a Haskell module and not an executable named kale-discover as I'm expecting. Any idea what I'm doing wrong?

from kale.

parsonsmatt avatar parsonsmatt commented on August 17, 2024

from kale.

tmciver avatar tmciver commented on August 17, 2024

I see. I added kale as a dep to package.yaml and it builds without error now. I was under the impression that the preprocessor specified in {-# OPTIONS_GHC -F -pgmF my-pre-processor #-} could be any old executable on the path in which case the kaletest project would not need to depend on kale at all. Can you tell me why I need to set kale as a dependency?

Also, when stack build completed I expected to see a new file generated by the preprocessor. Is this not a correct expectation? Is that generated file ephemeral?

from kale.

parsonsmatt avatar parsonsmatt commented on August 17, 2024

I don't understand the pgmF flag or how exactly it works. I coped code from hspec 🙂

Yes, the generated file only exists temporarily while GHC compiles and builds it into the executable.

from kale.

tmciver avatar tmciver commented on August 17, 2024

I'm starting to understand this pgmF business a bit better. One thing I tried in an effort to understand things better was to specify these GHC options on the command line instead of in a Lib.hs file like so:

$ stack build --ghc-options="-F -pgmF kale-discover"

but it gives this error:

/home/tim/workspace/haskell/kaletest/src/Lib/Task.hs:8:8: error:
        File name does not match module name:
        Saw: ‘Task’
        Expected: ‘Lib.Task’

This seems to ultimately be due to the way kale generates the module name for the generated Haskell (in the pathToModule function) which only takes the final segment of the path as the module name. This seems to work since the current method of preprocessing is done at the same level as the Lib directory so the generated module is directly under src. (The above method apparently does the preprocessing in the same directory as the module, which makes sense.)

So I wonder if you have a preference for how users might specify the GHC options. You could leave things as is and just tell the user how to specify the options or change things so that the options could be specified in other ways.

from kale.

parsonsmatt avatar parsonsmatt commented on August 17, 2024

Interesting. The -pgmF flag when used liket hat is likely going to apply the preprocessor to all of the files in the project, which isn't what we want.

I would definitely prefer folks to write the GHC options in the file that is going to become the module containing the task executable stuff -- in the same way that hspec-discover only is ever used like

-- test/Spec.hs
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}

from kale.

tmciver avatar tmciver commented on August 17, 2024

Good enough! Yes, I had thought about how that command would run the preprocessor on all the files but forgot to mention it. For that reason I agree that it's a good idea to specify the options as you are doing.

from kale.

Related Issues (11)

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.