Open straight-shoota opened 4 years ago
Personally, I like that give me all you got principle as it follows now, because it's very easy to delete unwanted config files, but it would take some effort to obtain them in case of need.
Do we need a wizard? Personally, I think it doesn't worth the complexity, because if crystal init
stays the way it is now, it's really easy to choose between app
and lib
and give a project name.
What if you deleted some file, but found yourself in need of it after a while? Just run new crystal init
somewhere else and copy the needed file(s) over.
License file? Make it empty. That way a user will be reminded of it, but woun't feel forced to use exact license.
Makefile? It's a very personal thing, it would be hard to come up with a pattern that suits the most.
Having an initializer directly by default in the language itself is a problem. The idea is nice, but it should be a different project from the language:
I think it can perfectly be a community project, with a modular approach to meet everyone's need.
@j8r I guess technically it could be split from the compiler. But it's important to distribute crystal init
with the compiler and stdlib, because it follows a batteries included approach that's very welcoming to new users. Wanna start using Crystal? Just install it and run crystal init
to setup a default project. There should be no need to refer to some other application you need to install first to get this IMO very basic feature.
It might be option though, to move crystal init
to shards init
. But IMO it's good as it stands now. shards init
deals with what's specific to shards' dependency manangement and crystal init
sets up a full Crystal project. The difference here is that shards
is actually not exclusive to Crystal, it can be used for other languages, too.
@sudo-nice There's a perfectly valid reason for initializing a git repository: It's necessary if you want your project to be available in the shards ecosystem, because shards
builds on top of git
for dependency retrieval.
License file? Make it empty.
That would be really bad user experience. It would undoubtedly be better to have no license file at all instead of an empty one.
Makefile? It's a very personal thing, it would be hard to come up with a pattern that suits the most.
I disagree. It may be opinionated, but that's inevitable. It should be very much possible to compile a set of default recipies that's good for most use cases, at least as a start. See my example. What do you think doesn't fit there?
Just run new crystal init somewhere else and copy the needed file(s) over.
Sure that works. But it's way nicer if it would just be an option to do this in place, and also take the existing configuration into account, instead of needing to call crystal init
with the same parameters as originally.
@j8r crystal init
is something that people mention in blog posts as one of the things they really like about Crystal. Wanna start? Just call crystal init
and you get the basic structure of a project. I use it all the timee.
It could be crystal-init
@asterite , and included by default in the distribution. I don't see any harm.
Look at crystal deps
moved to shards
, the result would be the same.
@straight-shoota
There's a perfectly valid reason for initializing a git repository
I have no problem with git at all, and I like the way it is now, but if some kind of wizard is to take place one day, it might be good to consider options other than git.
It would undoubtedly be better to have no license file at all instead of an empty one.
You might be right. Then which options do we have?
Pts. 1-3 are pretty good because they are really easy to maintain. But p.4 will require relatively large amount of fork and still there is no guarantee to cover all the possible demands:
Seems too complicated.
What do you think doesn't fit there?
I have no complains about the Makefile you linked, it looks pretty good, but I won't use it because it's not of my taste. Is it better to have a default Makefile rather than not having one? I guess, yes, because it's really easy to delete or overwrite one, when you know what you're doing, but for a newbie it might be a start.
But it's way nicer if it would just be an option to do this in place, and also take the existing configuration into account, instead of needing to call
crystal init
with the same parameters as originally.
Sounds really good, but how often does one need it?
@j8r separating the tool from the compiler is irrelevant to the discussion of improving crystal init
Pts. 1-3 are pretty good because they are really easy to maintain. But p.4 will require relatively large amount of fork and still there is no guarantee to cover all the possible demands:
I don't see a huge issue with maintenance. Once it's set up properly, there shouldn't be much work required, assuming we'll stick with a minimal set of OSS licenses (everything else wouldn't make any sense).
- which license to include?
Probably the big three AGPLv3, LGPLv3, Apache. Maybe MIT, although as I understand it, Apache is mostly similar and a bit more explicit, so there's little reason to choose MIT over Apache (except for length of license text, but that shouldn't matter really).
- which one should be default?
Maybe none? It could be required to select one explicitly, that's not a big deal.
- how to include my own license?
You select no license
for crystal init
and paste your custom license manually.
- are several license revisions to be supported?
What would be the purpose of that?
Sounds really good, but how often does one need it?
Currently, that's not pretty useful. But when there's support for a bunch of ci providers, for example, it would be great to have a way to easily initialize additional ones when necessary. This makes it really easy to only carry what you need.
@asterite I think it is, because there won't be any issue of having a full-featured project. Here we are talking about compromises, because of size limitation by keeping it inside the compiler.
@straight-shoota We can include ISC, it's simpler than MIT and also the default in the NPM ecosystem.
- which license to include?
I'd go for the top 10, including MIT - since it is popular, no matter our opinion on similarities.
Here we are talking about compromises, because of size limitation by keeping it inside the compiler.
No, we're not. All limitations are about keeping the tool as much focused as possible and they apply whether it's a compiler component or not.
I won't go into more detail regarding which licenses to include. Those specifics need to be figured out later.
I like the way Nim's nimble
handles the license issue. It specifically asks you in the wizard which license you want. We could have the top option in the list be "No license" so that it doesn't show any favoritism towards a specific one, but I love having license generation built in.
I like the ideas and thoughts put together, but have different opinion only on Makefile
as that would require different domain knowledge and make things look Cish style (IMHO). Crystal community always love to refer to how things work in Ruby, in Ruby they have Rake , should Crystal have something Cake
?
My opinion would be to have build system written using same language that is crystal, as that is the norm in other languages like Python setup.py
etc.
@naqvis personally I like the way nim handles things with nimble, and how Zig handles things with their own build system. Zig especially has a whole build system defined that's much more powerful than what gnu make provides. It would be cool to have the same functionality in Crystal, but I have a feeling it's not something we're likely to get pre-v1 without someone outside of the core team taking time to implement it.
My opinion would be to have build system written using same language that is crystal, as that is the norm in other languages like Python setup.py etc.
I'm not sure how much of a norm that is and it probably mostly applies to interpreted languages. I'm not aware of many build systems where the recipies are based on compiled languages. Even for interpreted languages, I'm highly skeptical of the benefits of everyone doing there own thing when a general purpose build system would fit for all. And make is the undisputed standard system.
Still, I wouldn't make this feature the most important topic in this discussion. I mostly brought it up as an example of future enhancements and to broaden the ideas on what crystal init
could do.
I'm not sure how much of a norm that is and it probably mostly applies to interpreted languages. I'm not aware of many build systems where the recipies are based on compiled languages. Even for interpreted languages, I'm highly skeptical of the benefits of everyone doing there own thing when a general purpose build system would fit for all. And make is the undisputed standard system.
Rust, OCaml, Nim, Zig and list goes on and none of them qualify as interpreted languages.
Still, I wouldn't make this feature the most important topic in this discussion. I mostly brought it up as an example of future enhancements and to broaden the ideas on what crystal init could do.
As stated in my initial post, I highly appreciate and thanks for the thoughts/idea put together and all of them definitely make sense. I only have different opinion on the build system.
Hi, I know I'm late to the discussion but what do you guys think of delegating the project structure with crystal init
to the community by simply allowing a template as a url to command.
I summarized it in this forum topic but in case you don't want to click:
What would you guys think about allowing crystal init to receive as an argument a URL with a project template? of course, some files in the project would require to be ECR templates so the project name is properly inserted. As a bonus, there could be a flag like template-arguments in which the user could pass a list of key value pairs with parameters for the project.
Ultimately, it could look like:
$ crystal init myapp --url=http://github.com/coolframework/template --template-arguments db_engine=postgres
Of course you could question how is this useful or why is it required. I believe there are several advantages:
I like to think that crystal best practices would tend to evolve faster than the language. Or at least there could be useful setup that can be shared with others (I thought about this when adding GitHub Actions for publishing a CLI App I created, and thought there should be a simple way to share that with others).
Organizations could leverage this by providing their users with pre-approved project templates for say, micro services, that serve some standard.
It gives framework creators the leverage for creating boilerplate without creating that infrastructure themselves (think about rails, in which you need rails for setting up a rails project in which rails is included as a dependency).
I believe this removes the burden of the core team for constantly updating the default project template (even if this is not a frequent activity, someone has to do it) and provides other advantages without adding too much complexity to the init
command.
Related forum post, which has a poll: https://forum.crystal-lang.org/t/poll-how-do-you-use-crystal-init/2921.
TL;DR: roughly half the people would like additional features, and roughly half are fine with the tool as-is.
Didn't see it mentioned before, but this sounds a lot like what bundle gem
in Ruby-land already does, and we can take insipration from there - https://bundler.io/man/bundle-gem.1.html
in Ruby they have Rake , should Crystal have something
Cake
?
IMHO not a wheel worth re-inventing.
The variety of build tools across languages is a bug, not a feature.
In some languages merely figuring out how to list or run the tasks
can already be an exercise in frustration. (npm run
, yarn run
, gulp
,
or what's the flavor of the day here?)
And it only goes downhill when questions like "how to pass arguments?" arise or when the tool barfs up some obscure internal error.
Instead of inventing yet another tool to do "largely the same just with yet another syntax that no one is familiar with", I'd much prefer if Crystal just standardizes on Make, as @straight-shoota suggested.
Make may be old and crummy, but it's ubiquitous, nearly everyone has either already used it or can learn the basics in 5 minutes.
crystal init
is a tool for easily setting up a Crystal project. It's obviously opinionated and won't serve everyone's needs. But it can still be improved to fit more use cases and help more people get stared with a new project.Since its inception in #534, there have only been little changes to the general behaviour of
crystal init
. A few details where fixed and improved since then.A few things I'd like to set for debate:
Wizard
A great addition towards usability would be to provide an interactive wizard which guides the user through configuration instead of asking to provide everything as command line options. The rationale here is that
crystal init
is generally used pretty rarely (most people don't start a new project every other day), but especially often by beginners (for their first steps with crystal). So it should be easy to use and not require to be familiar with every detail about it. Right now, you need to be aware thatcrystal init
expects at least two arguments to specify the project type (app or library) and name. The choice of type might already be unexpected and overwhelming for new users. The idea would be to ask the user about everything that's not specified in the command line and guide them through the process.crystal init
is most commonly used interactively anyway, and for non-interactive usage it should be possible to specify everything on the command line. Example flow:License
I don't like that
crystal init
imposes the MIT license on its users. Of course, that can easily be removed and replaced. And in general it's a good idea to promote adding a license to a project, and making it an open source license. Still, having that MIT license in place doesn't have any value if the author doesn't mean it. Simply placing it removes any thought about choosing an appropriate license. That's usually not the main concern when starting a new project, but you should at least put some thought into that. And one might even question the legal effect of an autogenerated license application.So I'd prefer to be more agnostic in that regard. IMO it's a bad practice to assume and impose any intention on licensing. It's too important. My idea would be to provide templates for several common open source licenses ({A,L}GL, Apache) and let the user choose either by CLI option or interactive question (if not option).
Makefile
I like to use a
Makefile
for my shards which is responsible for managing all tasks for development, testing and building. And we also use it in most crystal-lang repos. It's a great tool to improve workflow. It also serves as a documentation because you don't need to know which commands are necessary for specific tasks. This becomes even more important when more tools than justcrystal
andshards
are involved. It would be a great enhancement (at least for me ^_^) if a good defaultMakefile
template was automatically initialized bycrystal init
.A generalized example: https://gist.github.com/straight-shoota/275685fcb8187062208c0871318c4a23
CI
Currently, a
.travis-ci.yml
is initialized by default. There should be other options as well (circle-ci, gitlab-ci, github actions). I doubt it would be useful to install all of them by default (because you likely won't use more than one or two providers anyway), but rather let the user select. We also have great guides for travis and circle now at https://crystal-lang.org/reference/guides/continuous_integration.html. Still it's great to have it autogenerated. The template could be enhanced by some featured mentioned in the guides (for example testing against latest). Also a link to the respective guide could be mentioned in the config file.Incremental additions
Another useful feature would be to update an existing project folder. Especially when individual files can be optionally selected, it would be great to have simple method to add some optional files later to an existing project. For example, a circle-ci config file in a project that was only initialized with travis config. This would also be a way to upgrade the default configuration from a previous installment of the
crystal init
program. Whencrystal init
is run against an existing project this could work interactively and ask about individual files. Currently, you can only overwrite or skip all existing files.WDYT? Any other suggestions are welcome.