# Code
hledger is a suite of applications, tools and libraries. The main hledger code repository is [github.com/simonmichael/hledger](https://github.com/simonmichael/hledger) (shortcut url `code.hledger.org`). There are also various hledger addons maintained as separate projects with their own repos. ## hledger packages 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](https://hackage.haskell.org/package/hledger-lib), [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](https://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](https://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:Journal), which contains a list of [Transactions](https://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:Transaction), each containing multiple [Postings](https://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:Posting) of some [MixedAmount](https://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:MixedAmount) (multiple single-[CommoditySymbol](https://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:CommoditySymbol) [Amounts](https://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:Amount)) to some [AccountName](https://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:AccountName). When needed, the Journal is further processed to derive a [Ledger](https://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:Ledger), which contains summed [Accounts](https://hackage.haskell.org/package/hledger-lib/docs/Hledger-Data-Types.html#t:Account). In [Hledger.Reports](https://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: diagram ### hledger [package](https://hackage.haskell.org/package/hledger), [code](https://github.com/simonmichael/hledger/tree/master/hledger), [manual](https://hledger.org/hledger.html) 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](https://hackage.haskell.org/package/hledger-ui), [code](https://github.com/simonmichael/hledger/tree/master/hledger-ui), [manual](https://hledger.org/hledger-ui.html) A terminal interface. ### hledger-web [package](https://hackage.haskell.org/package/hledger-web), [code](https://github.com/simonmichael/hledger/tree/master/hledger-web), [manual](https://hledger.org/hledger-web.html) 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](https://hledger.org/hledger.html#queries): - [/journal](https://demo.hledger.org/journal), showing general journal entries (like `hledger print`) - [/register](https://demo.hledger.org/register?q=inacct:Expenses:Food), showing transactions affecting an account (slightly different from hledger's [register](https://hledger.org/hledger.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](https://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): ```cli $ (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. ```cli $ (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: ```cli $ 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.) ## 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](https://thread.gmane.org/gmane.comp.finance.ledger.hledger/1070) - Dev sprint/party 2015/10/10: [discussion](https://thread.gmane.org/gmane.comp.finance.ledger.hledger/1254)