# Overview
Provide the most beginner friendly cabal-install CLI possible. Thi…s means that the `cabal` commands by default (read: no arguments) should do the thing that beginners expect to get them to do, from zero to a Haskell program they can run.
_Note: This is related, but an expansion in scope from https://github.com/haskell/cabal/issues/5661_
## Example “Hello World”
Here are the commands that a beginner should need to run to get a working “Hello World” Haskell program that will build and run now, and will always build in the future, regardless of global system changes (like ghc version updates):
```
mkdir myfirstproject && cd myfirstproject
cabal init
cabal run
```
That’s it. No interactive prompt asking them a bunch of questions about licences; if they want a library, executable, or library and executable; if they want a separate `src` directory; base language; or anything else.
## Whose developer experience does this improve?
Beginners. Let’s make it as easy as possible for someone new to the language to get started and hacking on a Haskell program. The easier the onboarding, the better the adoption rate. You could argue that you could invoke ghc directly but you quickly need to start using cabal when you want to start using other packages, so let’s not make them learn something new twice.
Casual users. I often find myself with some idea I want to play with and just want the simplest way to get a basic project up and running. The fewer commands and CLI arguments I need to remember the better.
_**”But what about the power users?”**_
I’ll make the same point I made in #5661, if you’re a power user, you know your way around cabal anyways. If you want to create a package interactively you can run `cabal init -i` (or `--interactive`), or maybe just specify the specific arguments you want to `cabal init` yourself. We should make the simplest experience the easiest in order to appeal to the widest audience possible.
This old default behaviour can also be re-enabled by setting `interactive-init: True` (module bikeshed) in `~/.cabal/config` for those that want the old interactive-by-default workflow.
# Changes
Let me first present a summary of the changes, I’ll explain the rational of them below.
- [x] `cabal init` default to not-interactive (`-n`), and `--interactive-init, -i` is added (#5902).
- Implemented: First question is to initialize a simple project (also available as `--simple`)
- Provide both `--interactive` and `--non-interactive` flags (#5864)
- [x] `cabal init` defaults to `--exe` _(edit: previously `--libandexe`)_ (#5854)
- [ ] `cabal init` pins the `ghc` version via `with-compiler` in `cabal.project` for executables
- [x] `cabal run` is `cabal v2-run` (aka `cabal new-run`) (#5800)
- [x] (minor) `--exe` and `--lib` as shorthands for `--is-executable` and `--is-library` (#5759)
## Default to non-interactive
When someone gets started with Haskell and initialize a project they’re confronted with a large list of questions about what licence they want; what category their package falls into; if they want a binary, executable, or both; if they want their main as a `.hs` or `.lhs` file; where they want their source directory to be, and what “base language” they want.
To a beginner, the majority (IMHO, all) of these questions are confusing at best, all they really want is to start hacking on a Haskell file. By defaulting to non-interactive, the base command gives them what they expect, a minimally configured package that they can run, edit a file, and run it again.
The existing interactive behaviour would still be accessible via an `--interactive, -i` flag. If you’re already familiar with cabal then learning one new flag for interactively creating a package is incredible low overhead. Sure, you may need to change your workflow _slightly_, but I think that’s a pretty low cost to pay for making a beginner's experience better.
Additionally, the old default behaviour can also be re-enabled by setting `interactive-init: True` (module bikeshed) in `~/.cabal/config` for those that want the old interactive-by-default workflow.
### (alternative) "Would you like to initialize a simple project?" as first questions
_Note: This was implemented in #5707._
From the suggestion from @gbaz below, another option is to keep `--interactive` as the default, but move the "What type of project?" question to be the first question, and add a new choice "Executable (Simple Project)" as the default which will skip the rest of the interactive menus and create a bare bones executable.
## Default to executable (with library)
Once again, to offer a simple default initialization behaviour what we really want is a binary. This is actually inline with what Rust switched to in version 1.25 ([blog](https://blog.rust-lang.org/2018/03/29/Rust-1.25.html), see “Cargo Features” section), and they made an incredibly good observation:
_”Cargo’s CLI has one really important change this release: `cargo new` will now default to generating a binary, rather than a library… If you don’t pass one of these flags, in previous versions of Cargo, it would default to `--lib`. We made this decision because each binary (often) depends on many libraries, and so the library case is more common. However, this is incorrect; each library is depended upon by many binaries. Furthermore, when getting started, what you often want is a program you can run and play around with. It’s not just new Rustaceans though; even very long-time community members have said that they find this default surprising. As such, we’re changing it.”_
~Since its good practice to place all of the actually code in a library and have a "dumb main" to ease testing and allow for usage outside of your executable, we initialize a library and executable.~
Initializing both a library and executable with reasonable defaults and directory structure is now handled by the "simple project" initialization, `cabal init --simple`.
## cabal init pins the ghc version for executables
For the full discussion see #5661.
In summary, not pinning the ghc version can result in a working build one day failing to build another day due to a change in global system state (such as the `ghc` on PATH).
## cabal run is cabal v2/new-run
In summary, we want the “new build” to be the default for all the reasons outlined [here](https://cabal.readthedocs.io/en/latest/nix-local-build-overview.html). This is planned for the cabal-install 3.0 release.
## (minor) `--exe` and `--lib` as shorthands
This obviously isn’t critical, the current versions are just really verbose and not inline with other tools.
# Backwards Compatibility
**Default to non-interactive**
_In theory_ this is not backwards compatible since previously running `cabal init` with no arguments would drop you into interactive mode, but after the change it would select sane defaults for you.
_In practice_, this mode would not be used in scripts anyways so this is unlikely to cause issues for any automation, since those scripts would explicitly spell out the arguments to `cabal init`.
If in the past you relied on the default interactive behaviour when manually creating a package you can either use the new `--interactive` (or `-i`) flag, or just edit the `.cabal` file manually.
**Default to executable**
Technically not backwards compatible. The current `cabal init -n` behaviour creates a library, so anyone who previously ran the command in non-interactive mode without manually specifying an `--is-xyz` flag would get different behaviour. I would imagine this isn’t a common case, and those that were relying on the behaviour could slightly adjust their workflows.
**cabal init pins ghc-version**
See discussion in #5661.
**cabal run is cabal v2/new-run**
I don’t think there’s anyone who doesn’t want this. The backwards compatibility of that switch is out of scope here.
**(minor) `--exe` and `--lib` as shorthands**
Simply introducing new aliases, nothing breaking here.
# Timeline / Milestone
I would like to target the cabal-install 3.0 release since this will already include substantial changes (namely, defaulting to new-build). If we're going to make "breaking" changes to the CLI it makes sense to go out in the next major version.
# Edit History
**2018-11-20 9:15PST**
- Add "Default to non-interactive" alternative
- Add "Timeline / Milestone" section
**2018-11-20 17:30PST**
- Add `interactive-init` option to `~/.cabal/config`
**2019-01-20 11:40PST**
- Default to `--exe` instead of `--lib-and-exe`
/cc @23Skidoo @hvr