Giter Club home page Giter Club logo

hi's Introduction

hi Build StatusCoverage StatusHackage

Generate scaffold for a Haskell project

Overview

This application generates a scaffold for Haskell project from a Git repository. The template can be specified by Git repository. hi-hspec will be used as a default template.

Usage

Basic Example

$ hi foo-bar-baz
Creating new project with git repository:git://github.com/fujimura/hi-hspec.git
    create  foo-bar-baz/.gitignore
    create  foo-bar-baz/LICENSE
    create  foo-bar-baz/README.md
    create  foo-bar-baz/foo-bar-baz.cabal
    create  foo-bar-baz/src/Foo/Bar/Baz.hs
    create  foo-bar-baz/src/Foo/Bar/Baz/Internal.hs
    create  foo-bar-baz/test/Foo/Bar/BazSpec.hs
    create  foo-bar-baz/test/Spec.hs

Specifying template

Specifying repository in GitHub has a shorthand like this:

$ hi foo-bar-baz --repository gh:fujimura/hi-flat
Creating new project from repository: [email protected]:fujimura/hi-flat.git
    create  foo-bar-baz/.gitignore
    create  foo-bar-baz/LICENSE
    create  foo-bar-baz/Main.hs
    create  foo-bar-baz/Foo/Bar/Baz.hs
    create  foo-bar-baz/README.md
    create  foo-bar-baz/foo-bar-baz.cabal

Options

  -h,--help                Show this help text
  -v,--version             Print version information
  -p,--package-name ARG    Name of package
  -m,--moduleName ARG      Name of Module
  -a,--author ARG          Name of the project's author
  -e,--email ARG           Email address of the maintainer
  -r,--repository ARG      Template repository
  --configuration-file ARG Use specified configuration file
  --initialize-git-repository
                           Initialize with git repository
  --after-command ARG      The command to be run after generation

Templates

Available templates

Please see https://github.com/fujimura/hi/wiki#available-templates and feel free to add yours!

How to make your own template

Template is used for templating.

Available variables:

  • $packageName : name of package, like 'hi'
  • $moduleName : name of module, like 'Hi'
  • $author : name of author, like 'Fujimura Daisuke'
  • $email : email address of maintainer, like '[email protected]'

'package-name' and 'ModuleName' in filepath will be replaced with given variable.

Files under package-name will be used as the source of generated files. Files in root directory will not be copied.

Motivation

I'm tired to organize directory structure for every new Haskell project which has some test. This library is heavily inspired by grunt-init.

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

hi's People

Contributors

adetokunbo avatar cdepillabout avatar fujimura avatar joefiorini avatar sol avatar timmytofu avatar trofi 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  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  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  avatar

Watchers

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

hi's Issues

more verbose usage output

It would be nice if the usage of hi was more verbose. I'm imaging something like this:

$ hi
Usage: hi [OPTION...]
Generate a haskell project based on a template from github.

  -p package-name  --package-name=package-name      Name of package
  -m Module.Name   --module-name=Module.Name        Name of Module
  -a NAME          --author=NAME                    Name of the project's author
  -e EMAIL         --email=EMAIL                    Email address of the maintainer
  -r REPOSITORY    --repository=REPOSITORY          Template repository    ( optional ) 
                   --configuration-file=CONFIGFILE  Run with configuration file
  -v               --version                        Show version number

If repository is not provided, it defaults to the repository at https://github.com/fujimura/hi-hspec.

Examples
    hi --package-name "foo-bar" --module-name "Foo.Bar" --author "you" --email "[email protected]"

$

I will send a pull request for this.

Allow templates to be plain old cabal packages

This is a cool tool, but I think it would be even nicer if it the templates were allowed to be regular cabal packages.

When there is no package-name.cabal.template hi could look for a ".cabal" file my-template.cabal (where my-template is the name of the template). It should be easy to locate as it will be the only ".cabal" file.

Instead of requiring...

Name:                   $packageName
Author:                 $author <$email>

...

Library
  Exposed-Modules:      $moduleName
  Other-Modules:        $moduleName.Internal

allow...

Name:                   my-template
Author:                 Hamish Mackenzie <[email protected]>

...

Library
  Exposed-Modules:      Module.Name
  Other-Modules:        Module.Name.Internal

We can still easily replace name and author (just find the line starting with "Author:"). I think other top level cabal properties should be handled in a similar way. The module names might be harder to handle and maybe we would need a hi.info file or something could tell you which modules to rename.

I think there are a lot of advantages to this approach

  • Users can see the info about the template (who is the author, what version is it)
  • Template packages could be uploaded to hackage to make them visible and haddock docs available
  • Hi could just run "cabal unpack" to download the template package
  • Users could "cabal install" the template package and try it out
  • Many existing packages would be valid hi templates (like hello)
  • To make a new template from an existing one just run "hi" on it and make the changes you want in your new template
  • Because the template is a valid package you can use cabal build (and cabal test) to check it
  • cabal-src-install can be used to install templates locally

accept --help flag

It would be nice for hi to accept the --help flag without saying hi: unrecognized option '--help'.

I will try to implement this and send a push request for it.

Remove config file

Name and email can be provided from .gitconfig, so config file is not necessary required.

Say "Hi!" to your new Haskell project

I've been looking at hi a couple of times by now. I love the idea, but I still never felt comfortable with the interface. Today I just started hacking to see if I can get it to do what I want, but by now I think this will require more profound conceptual changes.

Here is a short outline on how my future favorite scaffolding tool would behave:

# hi takes the package name as first argument
~/sandbox$ hi nifty-tool
# generate files in ~/sandbox/nifty-tool
# assume --package-name=nifty-tool
# make some sane assumption about --module-name
# if package name is omitted, the name of the current directory is assumed
~/sandbox/nifty-tool$ hi 
# generate files in ~/sandbox/nifty-tool
# assume --package-name=nifty-tool
# make some sane assumption about --module-name
# it should still be possible to specify --module-name
~/sandbox$ hi nifty-tool -m Nifty.Tool
# generate files in ~/sandbox/nifty-tool
# assume --package-name=nifty-tool
# assume --module-name=Nifty.Tool

If you like this approach, I'd be happy to hack on it. One thing we may want to change is how templates are organized. Looking at https://github.com/fujimura/hi-hspec, the templates are put under package-name/. This does not fit well if we want to be able to initialize projects in the current working directory. I would tend to put them under template/ instead.

And while we are at it, what about versioning templates for forward compatibility. We could use directories to achieve this, e.g. put the templates under template-v0/ for now. If we make breaking changes to how templates are interpreted, we bump the template version number, e.g. use template-v1/. A template repository can support multiple versions of hi by providing multiple template versions (e.g. https://github.com/fujimura/hi-hspec could provide two directories template-v0 and template-v1 so that it can be used with an old version and a new version of hi at the same time).

Generate files in `package-name` directory

Currently it's accomplished by having packageName in template. But, it seems to be a bit tricky way and there's no reason to not do it by the library itself.

To archive this, it's inevitable to change directory structure of templates. This will cause some unexpected behaviour for old hi users. Obviously it's a downside but this change will benefit further development of this library.

use a more powerful templating language

I would like there to be an option like --disable-tests, which sets a boolean $include_tests to false. Then, the package-name.cabal.template file could look something like this:

Name: $packageName
Version: 0.0.0
Author: $author<$email>
Maintainer: $author<$email>
License: BSD3
License-File: LICENSE
-- Synopsis:
-- Description:
Cabal-Version: >= 1.10
Build-Type: Simple

Library
  Default-Language: Haskell2010
  HS-Source-Dirs: src
  GHC-Options: -Wall
  Exposed-Modules: $moduleName
  Other-Modules: $moduleName.Internal
  Build-Depends: base >= 4 && < 5

{if $include_tests}
Test-Suite spec
  Type: exitcode-stdio-1.0
  Default-Language: Haskell2010
  Hs-Source-Dirs: src
                      , test
  Ghc-Options: -Wall
  Main-Is: Spec.hs
  Build-Depends: base
                      , hspec
{endif}

This doesn't seem possible with the current template library, but it would be a nice feature to have.

A similar option could be set for an executable section.

Support other VCS

Hi uses git to clone template repo at this moment.
At least I'd like to support Mercurial and Darcs.

License always names 'Fujimura Daisuke' in 3rd clause

Invoking hi like this
hi -p 'Foo' -m 'Foo.Bar' -a 'Horst Schlemmer' -e '[email protected]'
creates a LICENSE like this

Copyright (c) 2013, Horst Schlemmer

All rights reserved.
...
    * Neither the name of Fujimura Daisuke nor the names of other
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.
...

I expected 'Fujimura Daisuke' to be replaced by 'Horst Schlemmer'.

Tested with 55b02b1.

New directory nesting

In version 0.0.8.2 the template would be cloned at the top level, now it's a level deeper. For example, if I used to have a package named foo in a repo that looked like bar/baz, I could clone it in my current directory and get bar/baz (writing into any existing bar directory), now I get foo/bar/baz. Is there any way to force the old behavior? This change has broken all my scripts.

`cabal install hi` fails

Quite new to Haskell, please correct me if I am doing it wrong (there was no "installation" on the README).

Here is the output, on OS X 10.11.6:

$ cabal install hi
Resolving dependencies...
Configuring hi-1.2.0.1...
Building hi-1.2.0.1...
Failed to install hi-1.2.0.1
Build log ( /Users/nicolas.ha/.cabal/logs/hi-1.2.0.1.log ):
cabal: Entering directory '/var/folders/yr/v0tf__1d5pl2gs55bkqczcpw0000gr/T/cabal-tmp-10436/hi-1.2.0.1'
Configuring hi-1.2.0.1...
Building hi-1.2.0.1...
Preprocessing library hi-1.2.0.1...
[ 1 of 12] Compiling Hi.Config ( src/Hi/Config.hs, dist/build/Hi/Config.o )
[ 2 of 12] Compiling Hi.CommandLineOption ( src/Hi/CommandLineOption.hs, dist/build/Hi/CommandLineOption.o )

src/Hi/CommandLineOption.hs:23:39: error:
• Variable not in scope: (<>) :: Mod f0 a0 -> Mod f1 a1 -> t0
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:23:62: error:
• Variable not in scope:
(<>) :: t0 -> Mod f2 a2 -> Mod OptionFields String
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:26:39: error:
• Variable not in scope: (<>) :: Mod f3 a3 -> Mod f4 a4 -> t2
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:26:62: error:
• Variable not in scope: (<>) :: t2 -> Mod f5 a5 -> t1
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:26:85: error:
• Variable not in scope:
(<>) :: t1 -> Mod f6 a6 -> Mod OptionFields String
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:27:39: error:
• Variable not in scope: (<>) :: Mod f7 a7 -> Mod f8 a8 -> t3
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:27:64: error:
• Variable not in scope:
(<>) :: t3 -> Mod f9 a9 -> Mod OptionFields String
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:28:39: error:
• Variable not in scope: (<>) :: Mod f10 a10 -> Mod f11 a11 -> t4
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:28:62: error:
• Variable not in scope:
(<>) :: t4 -> Mod f12 a12 -> Mod OptionFields String
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:29:39: error:
• Variable not in scope: (<>) :: Mod f13 a13 -> Mod f14 a14 -> t5
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:29:62: error:
• Variable not in scope:
(<>) :: t5 -> Mod f15 a15 -> Mod OptionFields String
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:30:39: error:
• Variable not in scope: (<>) :: Mod f16 a16 -> Mod f17 a17 -> t7
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:30:62: error:
• Variable not in scope: (<>) :: t7 -> Mod f18 a18 -> t6
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:30:92: error:
• Variable not in scope:
(<>) :: t6 -> Mod f19 String -> Mod OptionFields String
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:31:62: error:
• Variable not in scope:
(<>) :: Mod f20 a19 -> Mod f21 a20 -> Mod OptionFields String
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:32:62: error:
• Variable not in scope:
(<>) :: Mod f22 a21 -> Mod f23 a22 -> Mod FlagFields Bool
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)

src/Hi/CommandLineOption.hs:33:62: error:
• Variable not in scope:
(<>) :: Mod f24 a23 -> Mod f25 a24 -> Mod OptionFields String
• Perhaps you meant one of these:
‘<$>’ (imported from Options.Applicative),
‘<*’ (imported from Options.Applicative),
‘<|>’ (imported from Options.Applicative)
cabal: Leaving directory '/var/folders/yr/v0tf__1d5pl2gs55bkqczcpw0000gr/T/cabal-tmp-10436/hi-1.2.0.1'
cabal: Error: some packages failed to install:
hi-1.2.0.1 failed during the building phase. The exception was:
ExitFailure 1

Run setup by default

  • Initialise git repository
  • Setup cabal sandbox
  • cabal install --only-dependencies --enable-tests

`cabal install hi` fails due to `optparse-applicative`

This fails:

cabal install hi

This works:

$ cabal install hi --constraint="optparse-applicative<0.16"

Suggestions:

  • quick fix: make a revision on hackage adding the missing upper bound
  • long-term fix: fix the error and switch to optparse-applicative >= 0.16

Further details

Error:

cabal install hi
...
[11 of 12] Compiling Hi.Cli           ( src/Hi/Cli.hs, dist/build/hi/hi-tmp/Hi/Cli.o )

src/Hi/Cli.hs:48:30: error:
    • Couldn't match expected type ‘ParseError’
                  with actual type ‘Maybe String -> ParseError’
    • Probable cause: ‘ShowHelpText’ is applied to too few arguments
      In the third argument of ‘parserFailure’, namely ‘ShowHelpText’
      In the second argument of ‘($)’, namely
        ‘parserFailure pprefs pinfo ShowHelpText mempty’
      In the expression:
        handleParseResult . Failure
          $ parserFailure pprefs pinfo ShowHelpText mempty
   |
48 |   parserFailure pprefs pinfo ShowHelpText mempty
   |                              ^^^^^^^^^^^^
cabal: Failed to build exe:hi from hi-1.2.0.2.

See similar issue at commercialhaskell/stack#5379.

specify directory name for new projects

It would be nice to have an option like --directory-name. It would be intended to let you set a different directory name than the package name. So, for instance, your top-level directory could get created with the name foo, even though your package name is bar-baz.

--directory-name would default to being the same as --package-name if not specified explicity.

If I implemented this would you be willing to accept the patch?

Upload master to hackage

Latest version of hi in hackage (1.2.0.1) is incompatible with optparse-applicative >= 0.13, so it's difficult to build it with recent stack snapshots.

Could you upload the master version in this repository to hackage? Thanks in advance.

Can't specify the repository in relative path

$ hi foo -r ../hi-hspec
Creating new project with git repository:../hi-hspec
fatal: repository '../hi-hspec' does not exist
callCommand: git clone --no-checkout --quiet ../hi-hspec ./ (exit 128): failed

Works with full path.

$ hi foo -r /Users/fujimuradaisuke/.ghq/github.com/fujimura/hi-hspec
Creating new project with git repository:/Users/fujimuradaisuke/.ghq/github.com/fujimura/hi-hspec
    create  foo/README.md
    create  foo/.gitignore
    create  foo/LICENSE
    create  foo/README.md
    create  foo/foo.cabal
    create  foo/src/Foo.hs
    create  foo/src/Foo/Internal.hs
    create  foo/test/FooSpec.hs
    create  foo/test/Spec.hs

Creates README.md in current working directory

If you use hi with the default template https://github.com/fujimura/hi-hspec, e.g. hi -m Foo you get the following list of files in the current working directory:

README.md
foo/.gitignore
foo/LICENSE
foo/README.md
foo/foo.cabal
foo/src/Foo.hs
foo/src/Foo/Internal.hs
foo/test/FooSpec.hs
foo/test/Spec.hs

Note that here are both README.md and foo/README.md. We could solve this by using a subdirectory as template root (see #41).

how to include a file in the template without substitution

I need to include a guard file in the template and I tried copy the file into package-name directory, and it isn't copied into the project folder, I have to name the file to file.template, but this will require to escape the "$" sign in the file, would it make sense to copy everything under package-name directory into project folder and only substitute the files which has ".template" extension?

Creates an extra readme

Running hi creates two READMEs, one in the project folder and one outside. I always end up deleting the one outside.

0.1.0 spec

Current spec of hi has some troubles(#26, #34). I'd like to cleanup them and want to release it as 0.1.0.

There are some plans in my mind:

Plan A

  • Files will be generated in current directory
  • Template should have package-name directory
  • All files in package-name directory is copied
  • If a file in template reposity has .template extension, arguments will be replaced.

Pros

Cons

  • A bit complex

Plan B

  • Files will be generated in the value of --package-name option
  • Thus, template should not have package-name directory
  • All files in template repository is copied
  • If a file in template repositoy has .template extension, arguments will be replaced

Pros

  • Simple
  • Approachable to #30

Cons

  • No backward compatibility
  • No extra file like README in template repository

Plan B'

  • Same as B, except
    • Template should have package-name directory
    • All files in package-name directory is copied

Pros

  • Has backward compatibility

Cons

  • Still complex

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.