1068 lines
49 KiB
Markdown
1068 lines
49 KiB
Markdown
# Contributor guide
|
|
|
|
<style>
|
|
#toc > ol > li > a { display:none; }
|
|
#toc > ol > li > ol > li { padding-left:0; }
|
|
</style>
|
|
* toc
|
|
|
|
New contributors are always welcome in the hledger project.
|
|
Jump in! Or [ask us](/docs.html#getting-help) to help you find a task.
|
|
|
|
|
|
## Get started as a...
|
|
|
|
### Funder
|
|
|
|
Become a financial backer to
|
|
sustain and grow this project,
|
|
increase your influence,
|
|
express gratitude,
|
|
build prosperity consciousness,
|
|
and help transform world finance!
|
|
|
|
- Use the donate links on the [home page](/)
|
|
- Configure a recurring donation
|
|
- Contribute or pledge bounties on issues you care about
|
|
- Ask your organization to contribute
|
|
- Work on project sustainability, accountability, fundraising
|
|
|
|
### Tester
|
|
|
|
- Test installation on platforms you have access to
|
|
- Test examples, advice, and links in the docs
|
|
- Run the latest release or developer build in daily use
|
|
- Run [tests](#tests)
|
|
- Run [benchmarks](#benchmarking)
|
|
- Report packaging, documentation, UX, functional, performance issues
|
|
- Report and help analyse problems via irc/mail list/bug tracker
|
|
|
|
When reporting bugs, don't forget to search the tracker for a similar bug report.
|
|
Otherwise, open a new bug by clicking "New issue", or <http://bugs.hledger.org/new>.
|
|
|
|
Enhancement requests are sometimes added to the tracker,but for these consider using
|
|
the IRC channel and mail list (see [Getting help](/docs.html#getting-help)).
|
|
Both are archived and linkable, so the idea won't be lost.
|
|
There is also a collection of wishes at the old [trello board](http://trello.hledger.org).
|
|
|
|
### Developer
|
|
|
|
#### Review code
|
|
|
|
- review and discuss new [pull requests](http://prs.hledger.org) and commits on github
|
|
- build hledger and test the latest changes in your own repo
|
|
- read the existing [code docs and source](#quick-links)
|
|
- send feedback or discuss via [IRC or mail list](/docs.html#helpfeedback)
|
|
|
|
#### Build hledger
|
|
|
|
1. get [`stack`](/download.html#b) and (except on Windows, where stack provides it) [`git`](http://git-scm.com), then:
|
|
2. `git clone http://github.com/simonmichael/hledger hledger && cd hledger && stack install`
|
|
|
|
<div style="margin-left:1em; margin-right:1em; padding:.5em; border:thin solid #ddd; border-radius:.5em;">
|
|
In more detail:
|
|
|
|
**1. Get tools**
|
|
|
|
[`stack`](/download.html#b)
|
|
is the recommended tool for building hledger. You can use cabal-install
|
|
if you prefer, but that requires more expertise;
|
|
the hledger docs assume stack.
|
|
|
|
[`git`](http://git-scm.com) is the version control tool needed to
|
|
fetch the hledger source and submit changes. On Windows, stack will
|
|
install this as well.
|
|
|
|
<!--
|
|
While you're installing, here are some optional extra tools:
|
|
|
|
- `ghcid`: gives real-time feedback as you make code changes, reliable and useful.
|
|
- `hasktags`: generates tag files for quick code navigation in editors like Emacs and vi.
|
|
- `shelltestrunner`: if you want to run hledger's functional tests.
|
|
- [GNU Make](http://www.gnu.org/software/make): if you want to use some convenient [Makefile rules](#make).
|
|
|
|
```shell
|
|
$ stack install ghcid hasktags shelltestrunner
|
|
```
|
|
-->
|
|
|
|
**2. Get the source**
|
|
|
|
```shell
|
|
$ git clone http://github.com/simonmichael/hledger hledger # or git:
|
|
```
|
|
|
|
**3. Build/install**
|
|
|
|
```shell
|
|
$ cd hledger
|
|
$ stack install
|
|
```
|
|
|
|
This builds all the hledger packages, and installs executables in
|
|
`$HOME/.local/bin/` (or the Windows equivalent), which you should
|
|
[add to your `$PATH`](/download.html#b).
|
|
|
|
This can take a while!
|
|
To save time, you can build fewer [packages](/manual.html#official-add-ons), eg just the CLI:
|
|
```shell
|
|
$ stack install hledger
|
|
```
|
|
|
|
You can also build and run in place, without installing executables:
|
|
```shell
|
|
$ stack build; stack exec -- hledger [ARGS]
|
|
```
|
|
|
|
Note stack fetches most required dependencies automatically,
|
|
but not C libraries such as curses or terminfo, which you might need
|
|
to install yourself, using your system's package manager.
|
|
In case of trouble, see [download](/download.html#b).
|
|
|
|
</div>
|
|
|
|
#### Use GHCI
|
|
|
|
These all work from the main hledger source directory (at least).
|
|
|
|
First, ensure all required dependencies are installed with these
|
|
commands. (You might also need to install some system libs like
|
|
terminfo or curses.)
|
|
|
|
```shell
|
|
$ stack test
|
|
$ stack bench
|
|
```
|
|
|
|
Get a GHCI prompt for hledger-lib:
|
|
```shell
|
|
$ cd hledger-lib; stack ghci hledger-lib
|
|
```
|
|
Changing into the package directory isn't actually needed, but it
|
|
enables a custom .ghci script which sets a more useful short prompt.
|
|
|
|
Get a GHCI prompt for hledger:
|
|
```shell
|
|
$ cd hledger; stack ghci hledger
|
|
```
|
|
|
|
Get a GHCI prompt for hledger-ui:
|
|
```shell
|
|
$ cd hledger-ui; stack ghci hledger-ui
|
|
```
|
|
Get a GHCI prompt for hledger-web:
|
|
```shell
|
|
$ cd hledger-web; stack ghci hledger-web
|
|
```
|
|
hledger-web also needs to find some things in its current directory (like the static/ directory).
|
|
This normally just works, if not please [send details](https://github.com/simonmichael/hledger/issues/274).
|
|
|
|
<!--
|
|
Get a GHCI prompt for hledger and hledger-lib:
|
|
```shell
|
|
$ make ghci
|
|
```
|
|
|
|
Get a GHCI prompt for hledger-web, hledger and hledger-lib:
|
|
```shell
|
|
$ make ghci-web
|
|
```
|
|
|
|
For the dev.hs developer script:
|
|
```shell
|
|
$ make ghci-dev
|
|
```
|
|
-->
|
|
|
|
#### Add a test
|
|
|
|
- identify what to test
|
|
- choose the test type: unit ? functional ? benchmark ?
|
|
- currently expected to pass or fail ?
|
|
- figure out where it goes
|
|
- write test, verify expected result
|
|
- get it committed
|
|
|
|
#### Fix a bug or add a feature
|
|
|
|
- research, discuss, validate the issue/feature on irc/list/bug tracker
|
|
- look for related tests, run the tests and check they are passing
|
|
- add a test ?
|
|
- develop a patch
|
|
- include any related issue numbers in the patch name, eg: "fix for blah blah (#NNN)"
|
|
- get it committed
|
|
|
|
#### Get your changes accepted
|
|
|
|
Follow the usual github workflow:
|
|
|
|
- fork the main hledger repo on github,
|
|
- git clone it to your local machine,
|
|
- git commit, after (?) pulling and merging the latest upstream changes
|
|
- git push back to github,
|
|
- open a pull request on github,
|
|
- follow up on any discussion there.
|
|
|
|
If you're new to this process, [help.github.com](http://help.github.com) may be useful.
|
|
|
|
#### Add yourself to the contributor list
|
|
|
|
- after getting something into the master branch, read and sign the [contributor list & agreement](contributors.html). Or, [ask](/docs.html#helpfeedback) to be added.
|
|
- give yourself a high five!
|
|
|
|
### Technical Writer
|
|
|
|
- get familiar with the website and documentation online, review and test
|
|
- get familiar with the site/doc source files (see [Shake.hs](#shake))
|
|
- get the latest hledger source
|
|
- send patches with names prefixed with "doc: " (or "site: ")
|
|
|
|
### Graphics Designer
|
|
|
|
- more/better logos & graphics
|
|
- illustrations and diagrams
|
|
- web design mockups for home page, site, hledger-web UI
|
|
|
|
<!-- ### Product Designer -->
|
|
### Communicator
|
|
|
|
Marketing and market understanding is vital.
|
|
|
|
- clarify project goals, value proposition, brand, mission, story
|
|
- monitor product-market fit
|
|
- identify new opportunities
|
|
- influence developer priorities
|
|
- spread the word!
|
|
|
|
### Maintainer
|
|
|
|
#### Help with issue management
|
|
|
|
- watch tracker activity, report status
|
|
- apply/update labels where needed
|
|
- follow up on dormant issues
|
|
- facilitate a consistently good bug-reporting & PR-contributing experience
|
|
|
|
#### Help with packaging
|
|
|
|
- package hledger for linux distros, macports, etc.
|
|
- develop mac/windows installers
|
|
- find and assist distro packagers/installer developers
|
|
|
|
#### Help with project management
|
|
|
|
- clarify/update goals and principles
|
|
- monitor, report on project progress and performance
|
|
- research, compare and report on successful projects, related projects
|
|
- identify collaboration opportunities
|
|
- marketing, communication, outreach
|
|
- release management, roadmap planning
|
|
|
|
#### Do a major release
|
|
|
|
- review the release how-to in the developer guide
|
|
- and update as needed
|
|
(make site-preview, http://localhost:8000/contributing.html#do-a-major-release)
|
|
|
|
- clean working copy
|
|
- commit/stash/clear any pending changes in working copy
|
|
- merge any commits from other branches & working copies
|
|
- check out master, or release branch.
|
|
Major releases are done in master if possible.
|
|
If not, do as much of the below as is feasible in master,
|
|
then start a release branch (git checkout -b X.Y)
|
|
|
|
- ensure tests pass
|
|
- make unittest
|
|
- make functest
|
|
- make haddocktest
|
|
- make cabalfiletest
|
|
|
|
- update dependencies
|
|
- check & fix any outdated upper bounds
|
|
(dev guide -> quick links -> hackage)
|
|
|
|
- update cabal files
|
|
- */hledger*.cabal
|
|
- descriptions
|
|
- tested-with
|
|
- file lists
|
|
- data-files
|
|
- extra-tmp-files
|
|
- extra-source-files
|
|
- exposed-modules
|
|
- other-modules
|
|
|
|
- update stack.yaml file
|
|
- resolver
|
|
- extra-deps
|
|
- flags
|
|
|
|
- update docs
|
|
- haddocks
|
|
- changelogs
|
|
- man pages
|
|
- site/release-notes.md
|
|
- site/manual.md (commands, options, --help, ledger compatibility..)
|
|
- site/contributing.md
|
|
- site/step-by-step.md
|
|
- site/how-to-*
|
|
- site/faq.md (ledger compatibility)
|
|
- site/download.md
|
|
- site/contributors.md
|
|
- doc/ANNOUNCE
|
|
|
|
- update version
|
|
- edit .version
|
|
- make setversion
|
|
- double-check: cabal files, man pages ?, manual, download, release-notes, devguide..
|
|
- commit
|
|
|
|
- make tarballs/binaries
|
|
- ensure no packages are commented out in Makefile's PACKAGES
|
|
- make cabalsdist
|
|
- [make windows binaries]
|
|
- [make mac binaries]
|
|
|
|
- release tests
|
|
- make haddocktest
|
|
- make cabalfiletest
|
|
- cabal tarballs install into a clean directory without warnings
|
|
- cabal upload --dry reports no problems
|
|
|
|
- tag
|
|
- make tagrelease
|
|
|
|
- publish
|
|
- stack upload hledger-lib; stack upload hledger; stack upload hledger-ui; stack upload hledger-web
|
|
- [wait a day for it to appear in stackage nightly ?]
|
|
- ensure hackage is showing the latest haddocks
|
|
- check the hackage build matrix
|
|
- git push --tags
|
|
- deploy at demo.hledger.org
|
|
- [upload binaries to hledger.org]
|
|
- ensure the website is showing latest docs
|
|
(download links, release notes, manual, how-tos, dev guide links, etc.)
|
|
|
|
- announce
|
|
- review/close open issues in tracker
|
|
- email doc/ANNOUNCE to hledger, haskell-cafe, haskell, [ledger] lists
|
|
- tweet
|
|
- [blog]
|
|
- [reddit]
|
|
- update release notes with announcement link & short description
|
|
|
|
- post-release
|
|
- handle problem reports, support requests
|
|
|
|
|
|
#### Do a minor release
|
|
|
|
Differences from a major release:
|
|
work in a release branch,
|
|
set PACKAGES only to the affected package(s),
|
|
don't run make setversion.
|
|
|
|
1. cleanup
|
|
- review working copies (laptop, server, website) & branches, commit pending changes
|
|
2. document
|
|
- \*/\*.cabal for affected package(s) (descriptions, tested-with, files..)
|
|
- \*/CHANGES for affected package(s)
|
|
- site/release-notes.md
|
|
- site/manual.md (commands, options, --help, ledger compatibility..)
|
|
- site/step-by-step.md
|
|
- site/how-to-*
|
|
3. test
|
|
- make unittest
|
|
- make functest
|
|
- make haddocktest
|
|
4. branch
|
|
- switch to release branch (git checkout X.Y)
|
|
5. version
|
|
- edit .version (don't make setversion)
|
|
- manually bump version for affected package(s): cabal files, manual..
|
|
6. package
|
|
- set Makefile's PACKAGES to affected package(s)
|
|
- make cabalsdist
|
|
7. test
|
|
- install from tarball(s) into a clean directory
|
|
8. tag
|
|
- make tagrelease
|
|
9. push
|
|
- git push --tags
|
|
10. upload
|
|
- make cabalupload
|
|
11. announce
|
|
- [email hledger]
|
|
- [tweet]
|
|
|
|
|
|
|
|
## More about...
|
|
### Project
|
|
|
|
#### Mission
|
|
|
|
Why was hledger created ?
|
|
|
|
Mainly:
|
|
|
|
- to provide a more usable, robust, documented, cross-platform-installable version of Ledger for users
|
|
- to provide a more maintainable and hackable version of Ledger for developers
|
|
|
|
Also:
|
|
|
|
- to provide a useful library and toolbox for finance-minded haskell programmers
|
|
- to explore the suitability of Haskell for such applications
|
|
- to experiment with building a successful time-and-money-solvent project in a thriving ecosystem of financial software projects
|
|
|
|
What is the hledger project's current mission ?
|
|
|
|
1. Provide peace of mind: bring clarity, relief, and peace of mind to folks stressed, confused, overwhelmed by finances.
|
|
2. Educate and empower: help individuals and communities achieve clarity, accountability and mastery with money and time.
|
|
|
|
#### Roles and activities
|
|
|
|
- newcomer/potential user
|
|
- user
|
|
- library user
|
|
- field tester
|
|
- bug wrangler
|
|
- support
|
|
- documentor
|
|
- qa
|
|
- developer
|
|
- packager
|
|
- communicator
|
|
- project manager
|
|
|
|
### Issue tracking
|
|
|
|
The hledger project's issue tracker is on github. It contains:
|
|
|
|
- BUG issues - failures in some part of the hledger project (the main hledger packages, docs, website..)
|
|
- WISH issues - feature proposals, enhancement requests
|
|
- uncategorised issues - we don't know what these are yet
|
|
- pull requests - proposed changes to code and docs
|
|
|
|
Use these shortcut urls for quick access:
|
|
|
|
- <http://bugs.hledger.org> - show open BUG issues
|
|
- <http://wishes.hledger.org> - show open WISH issues
|
|
- <http://issues.hledger.org> - show all issues, open or closed
|
|
- <http://prs.hledger.org> - show open pull requests
|
|
<!-- - <http://bugs.hledger.org/N> - show issue number N -->
|
|
<!-- - <http://bugs.hledger.org/new> - create a new issue -->
|
|
|
|
Labels are used to categorise:
|
|
|
|
- the issue's type: "A BUG" or "A WISH", in shades of red (The A makes it appear as first label)
|
|
- relevant subsystems/topics, in light blue
|
|
- relevant platforms, in light purple
|
|
- resolution if not fixed: "closed:cant-reproduce/duplicate/invalid/wont-fix", in dark grey
|
|
- "bounty", in bright yellow: issues with bountysource funding
|
|
- "easy?", in dim yellow: issues which are probably relatively easy to fix
|
|
- "imported" etc., in white: miscellaneous information
|
|
|
|
Clicking blue topic labels is a good way to review issues in a topic you're interested in.
|
|
|
|
In 2017, milestones are not used much. Projects are being used to organise the roadmap.
|
|
|
|
You might see some experiments in estimate tracking, where
|
|
some issue names might have a suffix noting estimated and spent time.
|
|
Basic format: [ESTIMATEDTOTALTASKTIME|TIMESPENTSOFAR]. Examples:
|
|
```
|
|
[2] two hours estimated, no time spent
|
|
[..] half an hour estimated (a dot is ~a quarter hour, as in timedot format)
|
|
[1d] one day estimated (a day is ~4 hours)
|
|
[1w] one week estimated (a week is ~5 days or ~20 hours)
|
|
[3|2] three hours estimated, about two hours spent so far
|
|
[1|1w|2d] first estimate one hour, second estimate one week, about two days spent so far
|
|
```
|
|
Estimates are always for the total time cost (not time remaining).
|
|
Estimates are not usually changed, a new estimate is added instead.
|
|
Numbers are very approximate, but better than nothing.
|
|
|
|
The [trello board](http://trello.hledger.org) (trello.hledger.org) is a categorised collection of wishlist items,
|
|
this should probably be considered deprecated.
|
|
|
|
### Make
|
|
|
|
A Makefile is provided to make common developer tasks easy to remember,
|
|
and to insulate us a little from the ever-evolving Haskell tools ecosystem.
|
|
Using it is entirely optional, but recommended.
|
|
You'll need [GNU Make](http://www.gnu.org/software/make) installed.
|
|
|
|
The Makefile is self-documenting. Run `make` to see a list of the main make rules:
|
|
|
|
```shell
|
|
$ make
|
|
Makefile:37: -------------------- hledger make rules --------------------
|
|
Makefile:39: make [help] -- list documented rules in this makefile. make -n RULE shows more detail.
|
|
Makefile:204: (INSTALLING:)
|
|
Makefile:206: make install -- download dependencies and install hledger executables to ~/.local/bin or equivalent (with stack)
|
|
Makefile:231: (BUILDING:)
|
|
Makefile:235: make build -- download dependencies and build hledger executables (with stack)
|
|
Makefile:304: make hledgerdev -- quickly build the hledger executable (with ghc and -DDEVELOPMENT)
|
|
...
|
|
```
|
|
|
|
To see what a make rule will do without actually doing it, use the `-n` flag:
|
|
|
|
```shell
|
|
$ make build -n
|
|
stack build
|
|
```
|
|
```shell
|
|
$ make test -n
|
|
(stack test \
|
|
&& echo pkgtest PASSED) || echo pkgtest FAILED
|
|
(stack exec hledger test \
|
|
&& echo builtintest PASSED) || echo builtintest FAILED
|
|
(COLUMNS=80 PATH=`pwd`/bin:/home/simon/src/hledger/bin:/home/simon/.local/bin:/home/simon/.cabal/bin:/opt/ghc/7.10.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/var/lib/gems/1.9.1/bin stack exec -- shelltest --execdir -- -j16 --hide-successes tests \
|
|
&& echo functest PASSED) || echo functest FAILED
|
|
```
|
|
|
|
### Shake
|
|
|
|
`Shake.hs` in the top directory complements the Makefile; it is used for some more complex
|
|
scripts relating to documentation.
|
|
|
|
### Tests
|
|
|
|
Run the package tests of all (or selected) packages.
|
|
Does not include hledger's functional tests.
|
|
```shell
|
|
$ stack test [PKG]
|
|
```
|
|
|
|
Run some hledger unit tests via a built-in hledger command:
|
|
```shell
|
|
$ [stack exec] hledger test
|
|
```
|
|
|
|
Run hledger's functional tests:
|
|
```shell
|
|
$ stack install shelltestrunner
|
|
$ make functest
|
|
```
|
|
|
|
Run both unit and functional tests:
|
|
```shell
|
|
$ make test
|
|
```
|
|
|
|
Test generation of haddock docs:
|
|
```shell
|
|
$ make haddocktest
|
|
```
|
|
|
|
|
|
### Benchmarking
|
|
|
|
Benchmarks are standard performance measurements,
|
|
which we define using `bench` declarations in cabal files.
|
|
There is [one in hledger.cabal](https://github.com/simonmichael/hledger/blob/master/hledger/hledger.cabal#L228),
|
|
with related code and data files in [hledger/bench/](https://github.com/simonmichael/hledger/tree/master/hledger/bench).
|
|
|
|
To run the standard hledger benchmark, use `stack bench hledger`.
|
|
This installs haskell dependencies (but not system dependencies) and rebuilds as needed,
|
|
then runs [hledger/bench/bench.hs](https://github.com/simonmichael/hledger/blob/master/hledger/bench/bench.hs),
|
|
which by default shows quick elapsed-time measurements for several operations on a standard data file:
|
|
|
|
```shell
|
|
$ stack bench hledger
|
|
NOTE: the bench command is functionally equivalent to 'build --bench'
|
|
...
|
|
hledger-0.27: benchmarks
|
|
Running 1 benchmarks...
|
|
Benchmark bench: RUNNING...
|
|
Benchmarking hledger in /Users/simon/src/hledger/hledger with timeit
|
|
read bench/10000x1000x10.journal [1.57s]
|
|
print [1.29s]
|
|
register [1.92s]
|
|
balance [0.21s]
|
|
stats [0.23s]
|
|
Total: 5.22s
|
|
Benchmark bench: FINISH
|
|
```
|
|
|
|
bench.hs has some other modes, which you can use by compiling and running it directly.
|
|
`--criterion` reports more detailed and dependable measurements, but takes longer:
|
|
|
|
```shell
|
|
$ cd hledger; stack exec -- ghc -ibench bench/bench && bench/bench --criterion
|
|
...
|
|
Linking bench/bench ...
|
|
Benchmarking hledger in /Users/simon/src/hledger/hledger with criterion
|
|
benchmarking read bench/10000x1000x10.journal
|
|
time 1.414 s (1.234 s .. 1.674 s)
|
|
0.996 R² (0.989 R² .. 1.000 R²)
|
|
mean 1.461 s (1.422 s .. 1.497 s)
|
|
std dev 59.69 ms (0.0 s .. 62.16 ms)
|
|
variance introduced by outliers: 19% (moderately inflated)
|
|
|
|
benchmarking print
|
|
time 1.323 s (1.279 s .. 1.385 s)
|
|
1.000 R² (0.999 R² .. 1.000 R²)
|
|
mean 1.305 s (1.285 s .. 1.316 s)
|
|
std dev 17.20 ms (0.0 s .. 19.14 ms)
|
|
variance introduced by outliers: 19% (moderately inflated)
|
|
|
|
benchmarking register
|
|
time 1.995 s (1.883 s .. 2.146 s)
|
|
0.999 R² (0.998 R² .. NaN R²)
|
|
mean 1.978 s (1.951 s .. 1.995 s)
|
|
std dev 25.09 ms (0.0 s .. 28.26 ms)
|
|
variance introduced by outliers: 19% (moderately inflated)
|
|
|
|
benchmarking balance
|
|
time 251.3 ms (237.6 ms .. 272.4 ms)
|
|
0.998 R² (0.997 R² .. 1.000 R²)
|
|
mean 260.4 ms (254.3 ms .. 266.5 ms)
|
|
std dev 7.609 ms (3.192 ms .. 9.638 ms)
|
|
variance introduced by outliers: 16% (moderately inflated)
|
|
|
|
benchmarking stats
|
|
time 325.5 ms (299.1 ms .. 347.2 ms)
|
|
0.997 R² (0.985 R² .. 1.000 R²)
|
|
mean 329.2 ms (321.5 ms .. 339.6 ms)
|
|
std dev 11.08 ms (2.646 ms .. 14.82 ms)
|
|
variance introduced by outliers: 16% (moderately inflated)
|
|
```
|
|
|
|
`--simplebench` shows a table of elapsed-time measurements for the commands defined in [bench/default.bench](https://github.com/simonmichael/hledger/blob/master/hledger/bench/default.bench).
|
|
It can also show the results for multiple h/ledger executables side by side, if you tweak the bench.hs code.
|
|
Unlike the other modes, it does not link with the hledger code directly, but runs the "hledger" executable found in $PATH (so ensure that's the one you intend to test).
|
|
|
|
```shell
|
|
$ cd hledger; stack exec -- ghc -ibench bench/bench && bench/bench --simplebench
|
|
Benchmarking /Users/simon/.local/bin/hledger in /Users/simon/src/hledger/hledger with simplebench and shell
|
|
Using bench/default.bench
|
|
Running 4 tests 1 times with 1 executables at 2015-08-23 16:58:59.128112 UTC:
|
|
1: hledger -f bench/10000x1000x10.journal print [3.27s]
|
|
1: hledger -f bench/10000x1000x10.journal register [3.65s]
|
|
1: hledger -f bench/10000x1000x10.journal balance [2.06s]
|
|
1: hledger -f bench/10000x1000x10.journal stats [2.13s]
|
|
|
|
Summary (best iteration):
|
|
|
|
+-----------------------------------------++---------+
|
|
| || hledger |
|
|
+=========================================++=========+
|
|
| -f bench/10000x1000x10.journal print || 3.27 |
|
|
| -f bench/10000x1000x10.journal register || 3.65 |
|
|
| -f bench/10000x1000x10.journal balance || 2.06 |
|
|
| -f bench/10000x1000x10.journal stats || 2.13 |
|
|
+-----------------------------------------++---------+
|
|
```
|
|
|
|
bench's --simplebench mode is based on a standalone tool, [tools/simplebench.hs](https://github.com/simonmichael/hledger/blob/master/tools/simplebench.hs).
|
|
simplebench.hs is a generic benchmarker of one or more executables (specified on the command line) against one or more sets of command-line arguments (specified in a file).
|
|
It has a better command-line interface than bench.hs, so you may find it more convenient
|
|
for comparing multiple hledger versions, or hledger and ledger. Eg:
|
|
|
|
```shell
|
|
$ stack exec -- ghc tools/simplebench
|
|
[1 of 1] Compiling Main ( tools/simplebench.hs, tools/simplebench.o )
|
|
Linking tools/simplebench ...
|
|
```
|
|
```shell
|
|
$ tools/simplebench -h
|
|
tools/simplebench -h
|
|
simplebench: at least one executable needed
|
|
bench [-f testsfile] [-n iterations] [-p precision] executable1 [executable2 ...]
|
|
|
|
Run some functional tests with each of the specified executables,
|
|
where a test is "zero or more arguments supported by all executables",
|
|
and report the best execution times.
|
|
|
|
-f testsfile --testsfile=testsfile file containing tests, one per line, default: bench.tests
|
|
-n iterations --iterations=iterations number of test iterations to run, default: 2
|
|
-p precision --precision=precision show times with this precision, default: 2
|
|
-v --verbose show intermediate results
|
|
-h --help show this help
|
|
|
|
Tips:
|
|
- executables may have arguments if enclosed in quotes
|
|
- tests can be commented out with #
|
|
- results are saved in benchresults.{html,txt}
|
|
```
|
|
```shell
|
|
cd hledger; $ ../tools/simplebench -f bench/default.bench hledger ledger
|
|
Using bench/default.bench
|
|
Running 4 tests 2 times with 2 executables at 2015-08-24 04:24:37.257068 UTC:
|
|
|
|
Summary (best iteration):
|
|
|
|
+-----------------------------------------++---------+--------+
|
|
| || hledger | ledger |
|
|
+=========================================++=========+========+
|
|
| -f bench/10000x1000x10.journal print || 3.24 | 0.43 |
|
|
| -f bench/10000x1000x10.journal register || 3.80 | 3.48 |
|
|
| -f bench/10000x1000x10.journal balance || 2.05 | 0.18 |
|
|
| -f bench/10000x1000x10.journal stats || 2.10 | 0.19 |
|
|
+-----------------------------------------++---------+--------+
|
|
```
|
|
|
|
Finally, for quick, fine-grained performance measurements when troubleshooting or optimising, I use
|
|
[dev.hs](https://github.com/simonmichael/hledger/blob/master/dev.hs).
|
|
|
|
#### Sample journal files
|
|
|
|
Synthetic data files like `examples/100x100x10.journal` are useful for benchmarks and testing.
|
|
The numbers describe the number of transactions, number of accounts, and maximum account depth respectively.
|
|
They are generated by [`tools/generatejournal.hs`](https://github.com/simonmichael/hledger/blob/master/tools/generatejournal.hs).
|
|
They should get built automatically as needed, if not you can use `make samplejournals`:
|
|
|
|
```shell
|
|
$ make samplejournals
|
|
ghc tools/generatejournal.hs
|
|
[1 of 1] Compiling Main ( tools/generatejournal.hs, tools/generatejournal.o )
|
|
Linking tools/generatejournal ...
|
|
tools/generatejournal 100 100 10 >examples/100x100x10.journal
|
|
tools/generatejournal 1000 1000 10 >examples/1000x1000x10.journal
|
|
tools/generatejournal 1000 10000 10 >examples/1000x10000x10.journal
|
|
tools/generatejournal 10000 1000 10 >examples/10000x1000x10.journal
|
|
tools/generatejournal 10000 10000 10 >examples/10000x10000x10.journal
|
|
tools/generatejournal 100000 1000 10 >examples/100000x1000x10.journal
|
|
tools/generatejournal 3 5 5 >examples/ascii.journal
|
|
tools/generatejournal 3 5 5 --chinese >examples/chinese.journal
|
|
tools/generatejournal 3 5 5 --mixed >examples/mixed.journal
|
|
```
|
|
|
|
### Documentation
|
|
|
|
Project documentation lives in a number of places:
|
|
|
|
- `site/*.md` is the hledger.org website content, which is generated with hakyll[-std] and pandoc
|
|
- haddock documentation in the code appears on Hackage
|
|
- short blurbs: cabal files, module headers, HCAR, GSOC project, ..
|
|
- `doc/notes.org` has some old developer notes
|
|
- developer reports (profiles, benchmarks, coverage..) in doc/profs, sometimes published at hledger.org/profs
|
|
|
|
How to prepare changelogs & release notes
|
|
|
|
Draft:
|
|
|
|
- `make changelog-draft >> doc/CHANGES.draft.org` (or `>` if this is the first draft)
|
|
- open this org file and sort the nodes (`C-c ^ a`)
|
|
- categorisation pass 1: go through and add topic prefixes where missing
|
|
- sort the nodes again
|
|
- categorisation pass 2: move significant items to the appropriate package subnode as appropriate; keep "soft" items that might appear in release notes; delete the rest
|
|
- cleanup pass: combine/rewrite items for clarity
|
|
|
|
Changelogs:
|
|
|
|
- choose release version and date
|
|
- add new sections at top of {doc,hledger*}/CHANGES
|
|
- move the items from CHANGES.draft.org to these CHANGES files
|
|
- remove CHANGES.draft.org
|
|
|
|
Release notes:
|
|
|
|
- add a new TOC entry and section in site/release-notes.md
|
|
- copy/rewrite/summarise package changelogs
|
|
- note any other items of interest
|
|
- list release contributors
|
|
- write release summary
|
|
|
|
### Code
|
|
|
|
hledger is a suite of applications, tools and libraries.
|
|
The main hledger code repository is [github.com/simonmichael/hledger](http://github.com/simonmichael/hledger)
|
|
(aka `code.hledger.org`).
|
|
There are also various hledger addons maintained as separate projects with their own repos.
|
|
|
|
Within the main repo, there are a number of separate cabal packages,
|
|
making it easier to pick and choose parts of hledger to install or to package.
|
|
They are:
|
|
|
|
#### hledger-lib
|
|
|
|
[package](http://hackage.haskell.org/package/hledger-lib),
|
|
[exported modules](http://hackage.haskell.org/package/hledger-lib#modules),
|
|
[code](https://github.com/simonmichael/hledger/tree/master/hledger-lib)
|
|
|
|
Core data models, parsing, standard reports, and utilities.
|
|
Most data types are defined in [Hledger.Data.Types](http://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html),
|
|
while functions that operate on them are defined in Hledger.Data.TYPENAME.
|
|
Under [Hledger.Read](https://github.com/simonmichael/hledger/tree/master/hledger-lib/Hledger/Read.hs)
|
|
are parsers for the supported input formats.
|
|
Data files are parsed into a
|
|
[Journal](http://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:Journal),
|
|
which contains a list of
|
|
[Transactions](http://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:Transaction),
|
|
each containing multiple
|
|
[Postings](http://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:Posting)
|
|
of some
|
|
[MixedAmount](http://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:MixedAmount)
|
|
(multiple
|
|
single-[CommoditySymbol](http://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:CommoditySymbol)
|
|
[Amounts](http://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:Amount))
|
|
to some
|
|
[AccountName](http://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:AccountName).
|
|
When needed, the Journal is further processed to derive a
|
|
[Ledger](http://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:Ledger),
|
|
which contains summed
|
|
[Accounts](http://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:Account).
|
|
In [Hledger.Reports](http://hackage.haskell.org/package/hledger-lib/docs/Hledger-Reports.html)
|
|
there are standard reports, which extract useful data from the Journal or Ledger.
|
|
|
|
Here's a diagram of the main data model:
|
|
|
|
<a href="images/data-model.png" class="highslide" onclick="return hs.expand(this)">
|
|
<img src="images/data-model.png" alt="diagram" title="main data types" style="max-width:100%;">
|
|
</a>
|
|
|
|
<!-- generated by plantuml from:
|
|
<uml>
|
|
hide empty members
|
|
hide circle
|
|
skinparam packageStyle Rect
|
|
|
|
Ledger *-- Journal
|
|
Ledger *-- "*" Account
|
|
note top of Ledger: A Journal and all its accounts with their balances.\nUsed for balance report
|
|
note top of Journal: A journal file and parsed transactions & directives.\nUsed for print & register reports
|
|
note bottom of Account: An account's name, balance (inclusive &\nexclusive), parent and child accounts
|
|
Account o-- "*" Account :subaccounts, parent
|
|
Journal o-- File
|
|
File o-- "*" File :include
|
|
Journal *-- "*" MarketPrice
|
|
Journal *-- "*" Transaction
|
|
MarketPrice -- Date
|
|
MarketPrice -- Amount
|
|
Transaction -- Date
|
|
Transaction *-- "*" Posting
|
|
Transaction o-- "*" Tag
|
|
Posting o- "*" Tag
|
|
Posting -- "0..1" Date
|
|
Account -- AccountName
|
|
Posting -- AccountName
|
|
Account -- "2" MixedAmount
|
|
Posting -- MixedAmount
|
|
MixedAmount *-- "*" Amount
|
|
Amount -- CommoditySymbol
|
|
Amount -- Quantity
|
|
Amount -- Price
|
|
Amount -- AmountStyle
|
|
</uml>
|
|
-->
|
|
|
|
#### hledger
|
|
|
|
[package](http://hackage.haskell.org/package/hledger),
|
|
[exported modules](http://hackage.haskell.org/package/hledger#modules),
|
|
[code](https://github.com/simonmichael/hledger/tree/master/hledger),
|
|
[manual](/manual.html#hledger)
|
|
|
|
hledger's command line interface, and command line options and utilities for other hledger tools.
|
|
|
|
Try tracing the execution of a hledger command:
|
|
|
|
1. [Hledger.Cli.Main:main](https://github.com/simonmichael/hledger/blob/master/hledger/Hledger/Cli/Main.hs#L302)
|
|
parses the command line to select a command, then
|
|
2. gives it to
|
|
[Hledger.Cli.Utils:withJournalDo](https://github.com/simonmichael/hledger/blob/master/hledger/Hledger/Cli/Utils.hs#L73),
|
|
which runs it after doing all the initial parsing.
|
|
3. Parsing code is under
|
|
[hledger-lib:Hledger.Read](https://github.com/simonmichael/hledger/tree/master/hledger-lib/Hledger/Read.hs),
|
|
eg [Hledger.Read.JournalReader](https://github.com/simonmichael/hledger/tree/master/hledger-lib/Hledger/Read/JournalReader.hs).
|
|
4. Commands extract useful information from the parsed data model using
|
|
[hledger-lib:Hledger.Reports](https://github.com/simonmichael/hledger/tree/master/hledger-lib/Hledger/Reports),
|
|
and
|
|
5. render in plain text for console output (or another output format, like CSV).
|
|
6. Everything uses the data types and utilities from
|
|
[hledger-lib:Hledger.Data](https://github.com/simonmichael/hledger/tree/master/hledger-lib/Hledger/Data)
|
|
and [hledger-lib:Hledger.Utils](https://github.com/simonmichael/hledger/blob/master/hledger-lib/Hledger/Utils.hs).
|
|
|
|
#### hledger-ui
|
|
|
|
[package](http://hackage.haskell.org/package/hledger-ui),
|
|
<!-- [exported modules](http://hackage.haskell.org/package/hledger-ui#modules), -->
|
|
[code](https://github.com/simonmichael/hledger/tree/master/hledger-ui),
|
|
[manual](/manual.html#hledger-ui)
|
|
|
|
A curses-style text interface.
|
|
|
|
#### hledger-web
|
|
|
|
[package](http://hackage.haskell.org/package/hledger-web),
|
|
[exported modules](http://hackage.haskell.org/package/hledger-web#modules),
|
|
[code](https://github.com/simonmichael/hledger/tree/master/hledger-web),
|
|
[manual](/manual.html#hledger-web)
|
|
|
|
A web interface.
|
|
hledger-web starts a web server built with the yesod framework,
|
|
and (by default) opens a web browser view on it.
|
|
It reads the journal file(s) at startup and again whenever they change.
|
|
It can also write (append) new transactions to the journal file.
|
|
|
|
There are two main views, which can be filtered with
|
|
[queries](/manual.html#queries):
|
|
|
|
- [/journal](http://demo.hledger.org/journal), showing general journal entries (like `hledger print`)
|
|
|
|
- [/register](http://demo.hledger.org/register?q=inacct:Expenses:Food),
|
|
showing transactions affecting an account (slightly different from
|
|
hledger's [register](/manual.html#register) command, which shows postings).
|
|
|
|
There is also:
|
|
|
|
- a sidebar (toggled by pressing `s`) showing the chart of accounts (like `hledger balance`)
|
|
- an [add form](http://demo.hledger.org/journal?add=1) for adding new transactions (press `a`)
|
|
- a help dialog showing quick help and keybindings (press `h` or click ?)
|
|
|
|
Most of the action is in
|
|
|
|
- [config/routes](https://github.com/simonmichael/hledger/tree/master/hledger-web/config/routes)
|
|
- [templates/default-layout-wrapper.hamlet](https://github.com/simonmichael/hledger/tree/master/hledger-web/templates/default-layout-wrapper.hamlet)
|
|
- [Foundation](https://github.com/simonmichael/hledger/tree/master/hledger-web/Foundation.hs)
|
|
- [Handler.*](https://github.com/simonmichael/hledger/tree/master/hledger-web/Handler)
|
|
- [static/hledger.js](https://github.com/simonmichael/hledger/tree/master/hledger-web/static/hledger.js)
|
|
- [static/hledger.css](https://github.com/simonmichael/hledger/tree/master/hledger-web/static/hledger.css)
|
|
|
|
Handler module and function names end with R, like the yesod-generated route type they deal with.
|
|
|
|
Dynamically generated page content is mostly inline hamlet.
|
|
Lucius/Julius files and widgets generally are not used, except for the default layout.
|
|
|
|
Here are some ways to run it during development:
|
|
|
|
- `yesod devel`: runs in developer mode, rebuilds automatically when config, template, static or haskell files change
|
|
(but only files in the hledger-web package):
|
|
```shell
|
|
$ (cd hledger-web; yesod devel)
|
|
```
|
|
|
|
- [yesod-fast-devel](https://hackage.haskell.org/package/yesod-fast-devel)
|
|
may be a good alternative, also reloads the browser page
|
|
|
|
- `stack ghci`: runs the server in developer mode from GHCI.
|
|
Changes to static files like hledger.js will be visible on page reload;
|
|
to see other changes, restart it as shown.
|
|
```shell
|
|
$ (cd hledger-web; stack ghci hledger-web)
|
|
hledger-web> :main --serve # restart: ctrl-c, :r, enter, ctrl-p, ctrl-p, enter
|
|
```
|
|
|
|
- `make ghci-web`: runs the server in developer mode from GHCI, also
|
|
interprets the hledger-lib and hledger packages so that :reload picks
|
|
up changes in those packages too:
|
|
```shell
|
|
$ make ghci-web
|
|
ghci> :main --serve
|
|
```
|
|
(This rule also creates symbolic links to hledger-web's `config`, `messages`, `static` and `templates`
|
|
directories, needed in developer mode, so it can run from the top directory. This may not work on Windows.)
|
|
|
|
#### hledger-api
|
|
|
|
[package](http://hackage.haskell.org/package/hledger-api),
|
|
<!-- [exported modules](http://hackage.haskell.org/package/hledger-api#modules), -->
|
|
[code](https://github.com/simonmichael/hledger/tree/master/hledger-api),
|
|
[manual](/manual.html#hledger-api)
|
|
|
|
A web API server. Uses the servant framework.
|
|
|
|
### Quality
|
|
|
|
Relevant tools include:
|
|
|
|
- unit tests (HUnit, make unittest)
|
|
- functional tests (shelltestrunner, make functest)
|
|
- performance tests (simplebench, make bench)
|
|
- documentation tests (make haddocktest + manual)
|
|
- ui tests (manual)
|
|
- installation tests (manual)
|
|
- code reviews
|
|
|
|
### Code review
|
|
|
|
- Code review party 2014/7/21-25:
|
|
[discussion](http://thread.gmane.org/gmane.comp.finance.ledger.hledger/1070)<!-- missing ,
|
|
[log](http://hledger.org/static/irc-20140725-code-review.html) -->
|
|
- Dev sprint/party 2015/10/10:
|
|
[discussion](http://thread.gmane.org/gmane.comp.finance.ledger.hledger/1254)<!-- ircbrowse down ,
|
|
[pre-chat](http://ircbrowse.net/day/hledger/2015/10/10),
|
|
[log](http://ircbrowse.net/day/hledger/2015/10/11) -->
|
|
|
|
## Quick links
|
|
|
|
<style>
|
|
tr {
|
|
border-top:thin solid #bbb;
|
|
}
|
|
</style>
|
|
<!-- | hledger.org | [combined release notes](release notes), [pre-compiled binaries](download) | -->
|
|
<!-- [web ui demo](http://demo.hledger.org/register?q=inacct%3Aassets%3Abank%3Achecking+sym%3A\%24) -->
|
|
<!-- [](https://travis-ci.org/simonmichael/hledger) -->
|
|
<!-- [](http://packdeps.haskellers.com/feed?needle=hledger) -->
|
|
<!-- [](http://bugs.hledger.org) -->
|
|
<!-- [](https://github.com/simonmichael/hledger/issues?q=label:bounty) -->
|
|
|
|
|
|-------------------------|----------------------------------------------------------------------------|
|
|
| IRC | Join [#hledger](http://irc.hledger.org) ([chat log](http://ircbrowse.net/browse/hledger); see also [#ledger](http://webchat.freenode.net?channels=ledger&randomnick=1)) |
|
|
| Mail list | [list.hledger.org](http://list.hledger.org) ([Gmane](http://dir.gmane.org/gmane.comp.finance.ledger.hledger)) |
|
|
| Twitter | [#hledger](https://twitter.com/search?q=%23hledger&src=typd&f=realtime), see also [#ledgercli](https://twitter.com/search?q=%23ledgercli&src=typd&f=realtime), [#plaintextaccounting](https://twitter.com/search?q=%23plaintextaccounting&src=typd&f=realtime), <a href="https://twitter.com/ledgertips">@LedgerTips</a> |
|
|
| hledger-web demo | [demo.hledger.org](http://demo.hledger.org) |
|
|
| hledger-api demo | [demo.hledger.org/api](http://demo.hledger.org/api/swagger.json), [in swagger editor](http://editor.swagger.io/#/?import=demo.hledger.org/api/swagger.json&no-proxy)
|
|
| Trello | [old backlog/wishlist planning board](http://trello.hledger.org) |
|
|
| Github | [simonmichael/hledger](http://github.com/simonmichael/hledger) (alias: code.hledger.org), [forks](http://forked.yannick.io/simonmichael/hledger) <br> [commits](http://github.com/simonmichael/hledger/commits), <!-- [unreleased commits](https://github.com/simonmichael/hledger/compare/0.23...master), [release branch commits](https://github.com/simonmichael/hledger/compare/master...0.23), --> [COMMITS!](http://starlogs.net/#simonmichael/hledger) <br> [open bugs](http://bugs.hledger.org), [open wishes](http://wishes.hledger.org), [open unknowns](https://github.com/simonmichael/hledger/issues?utf8=✓&q=is%3Aissue%20is%3Aopen%20-label%3A%22A%20BUG%22%20-label%3A%22A%20WISH%22%20), [open pull requests](http://prs.hledger.org), [all issues](https://github.com/simonmichael/hledger/issues?q=) <br> [issues with bounty tag](https://github.com/simonmichael/hledger/issues?q=label:bounty), [bountysource bounties](https://github.com/simonmichael/hledger/issues?q=%22Add%20to%20the%20bounty%20at%20Bountysource%22%20OR%20%22claim%20the%20bounty%20on%20Bountysource%22%20OR%20%22bounty%20on%20this%20issue%20has%20been%20claimed%20at%20Bountysource%22%20), [codemill bounties](https://github.com/simonmichael/hledger/issues?q=codemill), [codefund bounties](https://github.com/simonmichael/hledger/issues?utf8=✓&q=codefund) <br> stars: <a class="github-button" href="https://github.com/simonmichael/hledger" data-icon="octicon-star" data-count-href="/simonmichael/hledger/stargazers" data-count-api="/repos/simonmichael/hledger#stargazers_count" data-count-aria-label="# stargazers on GitHub" aria-label="Star simonmichael/hledger on GitHub"></a> (#99 of ~30k [starred haskell projects](https://github.com/search?o=desc&q=language%3AHaskell+stars%3A%3E440&ref=searchresults&s=stars&type=Repositories) in 2016/04, #71 in 2016/12, #65 in 2017/3, #64 in 2017/5, #75 in 2017/8) <br> [{width=520 height=170}](https://waffle.io/simonmichael/hledger/metrics) |
|
|
| Travis CI | [{height=20}](https://travis-ci.org/simonmichael/hledger)
|
|
| Appveyor CI | <a name=appveyor></a>[{height=20}](https://ci.appveyor.com/project/simonmichael/hledger) [latest developer builds](https://ci.appveyor.com/project/simonmichael/hledger/build/artifacts)
|
|
| Hackage | packages: [hledger-lib](http://hackage.haskell.org/package/hledger-lib), [hledger](http://hackage.haskell.org/package/hledger), [hledger-ui](http://hackage.haskell.org/package/hledger-ui), [hledger-web](http://hackage.haskell.org/package/hledger-web), [hledger-api](http://hackage.haskell.org/package/hledger-api), [hledger-diff](http://hackage.haskell.org/package/hledger-diff), [hledger-iadd](http://hackage.haskell.org/package/hledger-iadd), [hledger-interest](http://hackage.haskell.org/package/hledger-interest), [hledger-irr](http://hackage.haskell.org/package/hledger-irr), [\*hledger\*](http://hackage.haskell.org/packages/search?terms=hledger) <!-- [](http://hackage.haskell.org/package/hledger) --> <!-- 2017/4 not updating <br> GHC compatibility: [hledger-lib](http://matrix.hackage.haskell.org/package/hledger-lib), [hledger](http://matrix.hackage.haskell.org/package/hledger), [hledger-ui](http://matrix.hackage.haskell.org/package/hledger-ui), [hledger-web](http://matrix.hackage.haskell.org/package/hledger-web), [hledger-api](http://matrix.hackage.haskell.org/package/hledger-api) --> <br> reverse deps: [hledger-lib](http://packdeps.haskellers.com/reverse/hledger-lib), [hledger](http://packdeps.haskellers.com/reverse/hledger), [hledger-ui](http://packdeps.haskellers.com/reverse/hledger-ui), [hledger-web](http://packdeps.haskellers.com/reverse/hledger-web), [hledger-api](http://packdeps.haskellers.com/reverse/hledger-api) <br> [{height=20}](http://packdeps.haskellers.com/feed?needle=hledger-lib) [{height=20}](http://packdeps.haskellers.com/feed?needle=hledger) [{height=20}](http://packdeps.haskellers.com/feed?needle=hledger-ui) [{height=20}](http://packdeps.haskellers.com/feed?needle=hledger-web) [{height=20}](http://packdeps.haskellers.com/feed?needle=hledger-api) |
|
|
| Stackage | [build-constraints.yaml](https://github.com/fpco/stackage/blob/master/build-constraints.yaml), [open hledger-related issues](https://github.com/fpco/stackage/search?q=hledger+is%3Aopen&type=Issues) |
|
|
| Debian | source packages: [haskell-hledger-lib](http://tracker.debian.org/pkg/haskell-hledger-lib), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=haskell-hledger-lib), [haskell-hledger](http://tracker.debian.org/pkg/haskell-hledger), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=haskell-hledger), [haskell-hledger-ui](http://tracker.debian.org/pkg/haskell-hledger-ui), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=haskell-hledger-ui), [haskell-hledger-web](http://tracker.debian.org/pkg/haskell-hledger-web), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=haskell-hledger-web) <br> binary packages: <br> stable [hledger](https://packages.debian.org/stable/hledger), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger;dist=stable), <!-- [hledger-ui](https://packages.debian.org/stable/hledger-ui), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-ui;dist=stable), --> [hledger-web](https://packages.debian.org/stable/hledger-web), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-web;dist=stable) <br> testing [hledger](https://packages.debian.org/testing/hledger), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger;dist=testing), <!-- [hledger-ui](https://packages.debian.org/testing/hledger-ui), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-ui;dist=testing), --> [hledger-web](https://packages.debian.org/testing/hledger-web), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-web;dist=testing) <br> unstable [hledger](https://packages.debian.org/unstable/hledger), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger;dist=unstable), [hledger-ui](https://packages.debian.org/unstable/hledger-ui), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-ui;dist=unstable), [hledger-web](https://packages.debian.org/unstable/hledger-web), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-web;dist=unstable) <br> experimental [hledger](https://packages.debian.org/experimental/hledger), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger;dist=experimental), [hledger-ui](https://packages.debian.org/experimental/hledger-ui), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-ui;dist=experimental), [hledger-web](https://packages.debian.org/experimental/hledger-web), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-web;dist=experimental) <br> all [\*hledger\*](https://packages.debian.org/search?searchon=names&keywords=hledger) <br> popularity stats: [hledger](https://qa.debian.org/popcon.php?package=haskell-hledger), [hledger-ui](https://qa.debian.org/popcon.php?package=haskell-hledger-ui), [hledger-web](https://qa.debian.org/popcon.php?package=haskell-hledger-web) <br> [PTS help](https://www.debian.org/doc/manuals/developers-reference/resources.html#pkg-tracking-system) |
|
|
| Ubuntu | source packages: [haskell-hledger-lib](https://launchpad.net/ubuntu/+source/haskell-hledger-lib), [bugs](https://bugs.launchpad.net/ubuntu/+source/haskell-hledger-lib), [haskell-hledger](https://launchpad.net/ubuntu/+source/haskell-hledger), [bugs](https://bugs.launchpad.net/ubuntu/+source/haskell-hledger), [haskell-hledger-ui](https://launchpad.net/ubuntu/+source/haskell-hledger-ui), [bugs](https://bugs.launchpad.net/ubuntu/+source/haskell-hledger-ui), [haskell-hledger-web](https://launchpad.net/ubuntu/+source/haskell-hledger-web), [bugs](https://bugs.launchpad.net/ubuntu/+source/haskell-hledger-web) <br> binary packages: [\*hledger\*](http://packages.ubuntu.com/search?suite=all&searchon=names&keywords=hledger) |
|
|
| Gentoo | [hledger](http://gpo.zugaina.org/dev-haskell/hledger), [hledger-web](http://gpo.zugaina.org/dev-haskell/hledger-web), [\*hledger\*](http://gpo.zugaina.org/Search?search=hledger) |
|
|
| Fedora | [hledger](https://apps.fedoraproject.org/packages/hledger), [\*hledger\*](https://apps.fedoraproject.org/packages/s/hledger), [hledger (package db)](https://admin.fedoraproject.org/pkgdb/package/hledger/), [Haskell SIG](http://fedoraproject.org/wiki/Haskell_SIG) |
|
|
| Void Linux | [hledger\*](https://github.com/voidlinux/void-packages/search?utf8=✓&q=hledger) |
|
|
| Nix | [\*hledger\*](http://hydra.nixos.org/search?query=hledger) |
|
|
| Homebrew | [hledger](https://github.com/Homebrew/homebrew-core/blob/master/Formula/hledger.rb) |
|
|
| Sandstorm | [hledger web app & reviews](https://apps.sandstorm.io/app/8x12h6p0x0nrzk73hfq6zh2jxtgyzzcty7qsatkg7jfg2mzw5n90), [issues](https://github.com/simonmichael/hledger/issues?utf8=✓&q=label%3A%22platform%3A%20sandstorm%22%20)
|
|
| Reference | [GHC Can I Use](http://damianfral.github.io/ghcaniuse/) |
|
|
|
|
<!-- list the debian packages for clarity:
|
|
3 source:
|
|
haskell-hledger-lib
|
|
haskell-hledger
|
|
haskell-hledger-web
|
|
8 binary:
|
|
hledger
|
|
hledger-web
|
|
libghc-hledger-dev
|
|
libghc-hledger-doc
|
|
libghc-hledger-prof
|
|
libghc-hledger-lib-dev
|
|
libghc-hledger-lib-doc
|
|
libghc-hledger-lib-prof
|
|
-->
|
|
|
|
<!-- old/future links -->
|
|
<!-- [haddock coverage](http://hledger.org/profs/haddock-coverage), -->
|
|
<!-- [unit test coverage](http://hledger.org/profs/coverage/hpc_index_fun.html), -->
|
|
<!-- [benchmark](http://hledger.org/profs/latest.bench) -->
|
|
<!-- [profile](http://hledger.org/profs/latest.prof), -->
|
|
<!-- [heap](http://hledger.org/profs/latest.ps) -->
|
|
<!-- [developer notes](http://github.com/simonmichael/hledger/NOTES.org)\ -->
|
|
<!-- [browse dev API docs](http://hledger.org/api/frames.html) -->
|
|
<!-- [How to clone it](contributing#set-up-for-development) -->
|
|
<!-- [hledger-web dev demo](http://demo.hledger.org:5001) -->
|
|
|
|
<!-- hoogle search form
|
|
<script type="text/javascript" src="http://haskell.org/hoogle/datadir/resources/jquery-1.4.2.js"></script>
|
|
<script type="text/javascript" src="http://haskell.org/hoogle/datadir/resources/hoogle.js"></script>
|
|
<form action="http://haskell.org/hoogle/" method="get" style="display:inline; margin:0; padding:0;">
|
|
<input type="hidden" name="prefix" value="+hledger +hledger-lib +hledger-web +hledger-vty +hledger-chart" />
|
|
<span style="white-space:nowrap;"
|
|
><input type="text" name="hoogle" id="hoogle" accesskey="1" size="30"
|
|
/><input type="submit" value="search API with hoogle"
|
|
/></span>
|
|
</form>
|
|
-->
|
|
|
|
|
|
<!-- <script async defer src="https://buttons.github.io/buttons.js"></script> -->
|