Add 'doc/haskellerz/' from commit '79beb34b900b5d35b065e145d6200d227de16945'
git-subtree-dir: doc/haskellerz git-subtree-mainline:684af10643git-subtree-split:79beb34b90
This commit is contained in:
commit
4013a81af8
22
doc/haskellerz/Makefile
Normal file
22
doc/haskellerz/Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
SLUG=haskellerz
|
||||
|
||||
TYPES=\
|
||||
slidy \
|
||||
revealjs \
|
||||
# dzslides \
|
||||
# s5 \
|
||||
# slideous \
|
||||
|
||||
default: build open watch
|
||||
|
||||
open:
|
||||
open *.html
|
||||
|
||||
build:
|
||||
for T in $(TYPES); do pandoc --slide-level=2 -s -t $$T $(SLUG).md -o $(SLUG).$$T.html; done
|
||||
|
||||
watch:
|
||||
ls *.md | entr bash -c 'make -s build && date'
|
||||
|
||||
clean:
|
||||
rm -f $(SLUG).*.html
|
||||
50
doc/haskellerz/README.org
Normal file
50
doc/haskellerz/README.org
Normal file
@ -0,0 +1,50 @@
|
||||
* Haskellerz talk 2021-04-29
|
||||
|
||||
** blurb
|
||||
Inside hledger: an architectural tour and how-to
|
||||
|
||||
hledger is a suite of CLI, TUI and WUI tools, file formats, and
|
||||
documentation for doing accounting with plain text. It is something
|
||||
that's not yet common: an end-user application written in Haskell,
|
||||
that aims to be easy to install, robust and pleasing to use, on all
|
||||
major platforms, including by non-techies.
|
||||
|
||||
I have been building and growing hledger and the hledger project for
|
||||
about 15 years. In this talk I will, after a quick intro to plain text
|
||||
accounting and hledger, give a tour of hledger's architecture,
|
||||
codebase, significant evolutions, and some design principles. Then
|
||||
I'll give some practical tips on how to: add your own custom hledger
|
||||
commands; use hledger from your own app; troubleshoot hledger
|
||||
behaviour; investigate bugs; and create effective pull requests. This
|
||||
will hopefully go smoothly, and the Q&A we can go deeper on whatever
|
||||
you like.
|
||||
|
||||
Simon: https://joyful.com
|
||||
hledger: https://hledger.org
|
||||
Plain Text Accounting: https://plaintextaccounting.org
|
||||
|
||||
** preliminary outline
|
||||
*** Inside hledger: an architectural tour and how-to
|
||||
**** quick intro to accounting, plain text accounting, hledger
|
||||
10m
|
||||
**** project goals
|
||||
**** a look at the essential functionality in its earliest/simplest form
|
||||
**** a fast run through the evolution since then
|
||||
**** a tour of the codebase and project today (2021Q2)
|
||||
**** design principles
|
||||
25m
|
||||
|
||||
**** how to script hledger
|
||||
**** how to integrate hledger in your app
|
||||
***** run cli, capture csv/json
|
||||
***** run hledger-web, use http-json api
|
||||
***** link with hledger-lib and/or other hledger packages, call public functions
|
||||
**** how to investigate a hledger bug
|
||||
***** basic troubleshooting - docs, comparison, minimisation, reproduction, support
|
||||
***** code debugging
|
||||
**** how to submit a pull request
|
||||
25m
|
||||
|
||||
**** Q & A
|
||||
30m
|
||||
|
||||
353
doc/haskellerz/haskellerz.md
Normal file
353
doc/haskellerz/haskellerz.md
Normal file
@ -0,0 +1,353 @@
|
||||
% Inside hledger: an architectural tour and how-to
|
||||
% Simon Michael
|
||||
% April 29, 2021
|
||||
|
||||
# Introductions
|
||||
|
||||
`0:00 (10m)`
|
||||
|
||||
## Who am I ?
|
||||
|
||||
Simon Michael\
|
||||
Independent software consultant and developer.\
|
||||
<!-- Currently based in Hawaii. -->
|
||||
<https://joyful.com>
|
||||
|
||||
Started in the home computer era (Ireland, 80s). ZX-80, Pet, VIC, C64, Amiga, PC, Mac, VAX/VMS, unix..
|
||||
|
||||
FOSS fan, contributor, project leader. Two big projects:
|
||||
|
||||
- **Zwiki**, 1996-2006, wiki engine, Python/Zope
|
||||
|
||||
- **hledger**, 2006-present, accounting tool, Haskell
|
||||
|
||||
## Overview of talk
|
||||
|
||||
- A quick intro to plain text accounting and hledger. (10m)
|
||||
|
||||
- A tour of hledger's
|
||||
architecture,
|
||||
codebase,
|
||||
evolutions,
|
||||
and design principles. (25m)
|
||||
|
||||
- How to script and develop hledger:
|
||||
custom commands,
|
||||
calling from other apps,
|
||||
troubleshooting,
|
||||
bug investigation,
|
||||
effective pull requests. (25m)
|
||||
|
||||
- Q&A to go deeper on whatever you like. (30m)
|
||||
|
||||
|
||||
## What's Plain Text Accounting ?
|
||||
|
||||
A name I proposed (and a website I built) to help unify and grow the
|
||||
communities around
|
||||
Ledger, hledger, Beancount and similar accounting
|
||||
tools.
|
||||
|
||||
<https://plaintextaccounting.org>
|
||||
|
||||
## The PTA ecosystem
|
||||
|
||||
The "big three" apps:
|
||||
|
||||
* **Ledger** - John Wiegley's pioneering command line accounting app,
|
||||
inspiration for all the rest.\
|
||||
C++, 2003-present
|
||||
|
||||
* **hledger** - Simon Michael's rewrite/remix.\
|
||||
Haskell, 2007-present
|
||||
|
||||
* **Beancount** - Martin Blais' variant.\
|
||||
Python, 2008-present
|
||||
|
||||
Many more apps and add-on tools - <https://plaintextaccounting.org/#software>
|
||||
|
||||
|
||||
## What's hledger ?
|
||||
|
||||
A suite of
|
||||
tools,
|
||||
file formats,
|
||||
and documentation
|
||||
for doing "plain text accounting".
|
||||
|
||||
<https://hledger.org>
|
||||
|
||||
## hledger project goals
|
||||
|
||||
I was a Ledger user and new Haskeller. I started hledger with many goals:
|
||||
|
||||
- acquire a more robust, usable, evolving incarnation of Ledger
|
||||
- develop a consistent, effective accounting habit
|
||||
- get better at Haskell
|
||||
- find out if Haskell was good for end-user apps and maintainer productivity
|
||||
- grow a useful, long-lasting, financially sustainable FOSS accounting project
|
||||
|
||||
## An end-user Haskell application
|
||||
|
||||
hledger is something that's not yet common:
|
||||
|
||||
An end user application (ie: not a programming tool),
|
||||
written in Haskell, that aims to be
|
||||
|
||||
- easy to install,
|
||||
- dependable,
|
||||
- and pleasing to use,
|
||||
- on all major platforms,
|
||||
- by non-techies as well as power users.
|
||||
|
||||
## A successful FOSS project
|
||||
|
||||
15 years, 134 contributors, 80-100 chatters, some number of happy
|
||||
users, useful to me every week.
|
||||
|
||||
Reasonably successful.
|
||||
|
||||
Not fulfilling my original goal of being financially
|
||||
self-sustaining and minimally time-consuming !
|
||||
|
||||
## Tools
|
||||
|
||||
* hledger
|
||||
* hledger-ui
|
||||
* hledger-web
|
||||
* hledger-iadd
|
||||
* hledger-interest
|
||||
* etc.
|
||||
|
||||
## File formats
|
||||
|
||||
* journal
|
||||
* csv
|
||||
* timeclock
|
||||
* timedot
|
||||
|
||||
## Documentation
|
||||
|
||||
* introductory
|
||||
* reference
|
||||
* cookbook
|
||||
* developer
|
||||
|
||||
|
||||
# Architecture
|
||||
|
||||
`0:10 (25m)`
|
||||
|
||||
## A fast run through the evolution
|
||||
|
||||
- First commit
|
||||
- First types
|
||||
- First report
|
||||
- Balance report
|
||||
- Multi-column balance report
|
||||
- Stateful parser
|
||||
- Web interface
|
||||
- Curses interface
|
||||
- Package split
|
||||
- Speed, features
|
||||
- General currency conversion
|
||||
- Valuation
|
||||
- Always documentation
|
||||
|
||||
## A tour of the codebase and project today (2021Q2)
|
||||
|
||||
|
||||
## Design principles
|
||||
|
||||
|
||||
# How to..
|
||||
|
||||
`0:35 (25m)`
|
||||
|
||||
## Script hledger
|
||||
|
||||
|
||||
|
||||
* <https://hledger.org/scripting.html>
|
||||
|
||||
## Integrate hledger in your app
|
||||
|
||||
* Run cli, capture csv/json
|
||||
|
||||
* Run hledger-web, use http-json api
|
||||
|
||||
* Link with hledger-lib and/or other hledger packages, call public functions
|
||||
|
||||
## Investigate a hledger bug
|
||||
|
||||
* Basic troubleshooting - docs, comparison, minimisation, reproduction, support
|
||||
|
||||
* Code debugging
|
||||
|
||||
## How to submit a pull request
|
||||
|
||||
* <https://hledger.org/CONTRIBUTING.html#pull-requests>
|
||||
|
||||
# Q & A
|
||||
|
||||
`1:00 (30m)`
|
||||
|
||||
# End
|
||||
|
||||
`1:30`
|
||||
|
||||
```
|
||||
$ git shortlog -s
|
||||
Aerex
|
||||
Aiken Cairncross
|
||||
Alejandro García Montoro
|
||||
Aleksandar Dimitrov
|
||||
Alex Chen
|
||||
Alvaro Fernando García
|
||||
Amarandus
|
||||
Amitai Burstein
|
||||
Andreas Pauley
|
||||
Andrew Jones
|
||||
Andriy Mykhaylyk
|
||||
Arnout Engelen
|
||||
Ben Boeckel
|
||||
Ben Creasy
|
||||
Boyd Kelly
|
||||
Brian Scott
|
||||
Brian Wignall
|
||||
Bryan Richter
|
||||
Caleb Maclennan
|
||||
Carel Fellinger
|
||||
Carl Richard Theodor Schneider
|
||||
Carlos Lopez-Camey
|
||||
Christian G. Warden
|
||||
Christoph Nicolai
|
||||
Clint Adams
|
||||
Colin Woodbury
|
||||
Damien Cassou
|
||||
David Reaver
|
||||
David Zhang
|
||||
Dmitry Astapov
|
||||
Dominik Süß
|
||||
Doug Goldstein
|
||||
Eli Flanagan
|
||||
Elijah Caine
|
||||
Eric Kow
|
||||
Eric Mertens
|
||||
Everett Hildenbrandt
|
||||
Evilham
|
||||
Felix Van der Jeugt
|
||||
Felix Yan
|
||||
Fun Ilrys (Nissar Chababy)
|
||||
Gabriel Ebner
|
||||
Gaith Hallak
|
||||
Gergely Risko
|
||||
Hans-Peter Deifel
|
||||
Henning Thielemann
|
||||
Imuli
|
||||
Jacek Generowicz
|
||||
Jacob Weisz
|
||||
Jakob Schöttl
|
||||
Jakub Zárybnický
|
||||
Jan Zerebecki
|
||||
Jeff Richards
|
||||
Jesse Rosenthal
|
||||
Joachim Breitner
|
||||
Joe Horsnell
|
||||
Johann Klähn
|
||||
Johannes Gerer
|
||||
John Wiegley
|
||||
Joseph Weston
|
||||
Joshua Chia
|
||||
Joshua Kehn
|
||||
Judah Jacobson
|
||||
Julien Moutinho
|
||||
Justin Le
|
||||
Kyle Marek-Spartz
|
||||
Luca Molteni
|
||||
Léo Gaspard
|
||||
M Parker
|
||||
Malte Brandy
|
||||
Mark Hansen
|
||||
Marko Kocić
|
||||
Martin Michlmayr
|
||||
Mateus Furquim
|
||||
Matthias Kauer
|
||||
Max Bolingbroke
|
||||
Michael Kainer
|
||||
Michael Sanders
|
||||
Michael Snoyman
|
||||
Michael Walker
|
||||
Mick Dekkers
|
||||
Mitchell Rosen
|
||||
Moritz Kiefer
|
||||
Mykola Orliuk
|
||||
Nadrieril
|
||||
Nicholas Niro
|
||||
Nick Ingolia
|
||||
Nicolas Wavrant
|
||||
Nikhil Jha
|
||||
Nissar Chababy
|
||||
Nolan Darilek
|
||||
Oliver Braun
|
||||
Omari Norman
|
||||
Pavan Rikhi
|
||||
Pavlo Kerestey
|
||||
Peter Simons
|
||||
Pia Mancini
|
||||
Rick Lupton
|
||||
Roman Cheplyaka
|
||||
Rui Chen
|
||||
Ryan Desfosses
|
||||
Sam Doshi
|
||||
Sam Jeeves
|
||||
Samuel May
|
||||
Sergei Trofimovich
|
||||
Sergey Astanin
|
||||
Shubham Lagwankar
|
||||
Simon Hengel
|
||||
Simon Michael
|
||||
SpicyCat
|
||||
Stefano Rodighiero
|
||||
Stephen Morgan
|
||||
Steven R. Baker
|
||||
TANIGUCHI Kohei
|
||||
Thomas R. Koll
|
||||
Tim Docker
|
||||
Timofey ZAKREVSKIY
|
||||
Trygve Laugstøl
|
||||
Vladimir Sorokin
|
||||
Vladimir Zhelezov
|
||||
Wad
|
||||
Xinruo Sun
|
||||
afarrow
|
||||
agander
|
||||
aragaer
|
||||
awjchen
|
||||
azure-pipelines[bot]
|
||||
flip111
|
||||
gwern
|
||||
jeevcat
|
||||
jungle-boogie
|
||||
legrostdg
|
||||
trevorriles
|
||||
zieone
|
||||
```
|
||||
|
||||
<!--
|
||||
https://pandoc.org/MANUAL.html#slide-shows
|
||||
|
||||
By default, the slide level is the highest heading level in the
|
||||
hierarchy that is followed immediately by content, and not another
|
||||
heading, somewhere in the document. In the example above, level-1
|
||||
headings are always followed by level-2 headings, which are followed
|
||||
by content, so the slide level is 2. This default can be overridden
|
||||
using the --slide-level option.
|
||||
|
||||
The document is carved up into slides according to the following rules:
|
||||
A horizontal rule always starts a new slide.
|
||||
A heading at the slide level always starts a new slide.
|
||||
Headings below the slide level in the hierarchy create headings within a slide.
|
||||
Headings above the slide level in the hierarchy create “title slides,” which just contain the section title and help to break the slide show into sections. Non-slide content under these headings will be included on the title slide (for HTML slide shows) or in a subsequent slide with the same title (for beamer).
|
||||
-->
|
||||
|
||||
390
doc/haskellerz/haskellerz.revealjs.html
Normal file
390
doc/haskellerz/haskellerz.revealjs.html
Normal file
@ -0,0 +1,390 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="pandoc">
|
||||
<meta name="author" content="Simon Michael">
|
||||
<meta name="dcterms.date" content="2021-04-29">
|
||||
<title>Inside hledger: an architectural tour and how-to</title>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
|
||||
<link rel="stylesheet" href="https://unpkg.com/reveal.js@^4//dist/reset.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/reveal.js@^4//dist/reveal.css">
|
||||
<style>
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
span.underline{text-decoration: underline;}
|
||||
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
ul.task-list{list-style: none;}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<link rel="stylesheet" href="https://unpkg.com/reveal.js@^4//dist/theme/black.css" id="theme">
|
||||
</head>
|
||||
<body>
|
||||
<div class="reveal">
|
||||
<div class="slides">
|
||||
|
||||
<section id="title-slide">
|
||||
<h1 class="title">Inside hledger: an architectural tour and how-to</h1>
|
||||
<p class="author">Simon Michael</p>
|
||||
<p class="date">April 29, 2021</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<section id="introductions" class="title-slide slide level1">
|
||||
<h1>Introductions</h1>
|
||||
<p><code>0:00 (10m)</code></p>
|
||||
</section>
|
||||
<section id="who-am-i" class="slide level2">
|
||||
<h2>Who am I ?</h2>
|
||||
<p>Simon Michael<br />
|
||||
Independent software consultant and developer.<br />
|
||||
<!-- Currently based in Hawaii. --> <a href="https://joyful.com" class="uri">https://joyful.com</a></p>
|
||||
<p>Started in the home computer era (Ireland, 80s). ZX-80, Pet, VIC, C64, Amiga, PC, Mac, VAX/VMS, unix..</p>
|
||||
<p>FOSS fan, contributor, project leader. Two big projects:</p>
|
||||
<ul>
|
||||
<li><p><strong>Zwiki</strong>, 1996-2006, wiki engine, Python/Zope</p></li>
|
||||
<li><p><strong>hledger</strong>, 2006-present, accounting tool, Haskell</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="overview-of-talk" class="slide level2">
|
||||
<h2>Overview of talk</h2>
|
||||
<ul>
|
||||
<li><p>A quick intro to plain text accounting and hledger. (10m)</p></li>
|
||||
<li><p>A tour of hledger’s architecture, codebase, evolutions, and design principles. (25m)</p></li>
|
||||
<li><p>How to script and develop hledger: custom commands, calling from other apps, troubleshooting, bug investigation, effective pull requests. (25m)</p></li>
|
||||
<li><p>Q&A to go deeper on whatever you like. (30m)</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="whats-plain-text-accounting" class="slide level2">
|
||||
<h2>What’s Plain Text Accounting ?</h2>
|
||||
<p>A name I proposed (and a website I built) to help unify and grow the communities around Ledger, hledger, Beancount and similar accounting tools.</p>
|
||||
<p><a href="https://plaintextaccounting.org" class="uri">https://plaintextaccounting.org</a></p>
|
||||
</section>
|
||||
<section id="the-pta-ecosystem" class="slide level2">
|
||||
<h2>The PTA ecosystem</h2>
|
||||
<p>The “big three” apps:</p>
|
||||
<ul>
|
||||
<li><p><strong>Ledger</strong> - John Wiegley’s pioneering command line accounting app, inspiration for all the rest.<br />
|
||||
C++, 2003-present</p></li>
|
||||
<li><p><strong>hledger</strong> - Simon Michael’s rewrite/remix.<br />
|
||||
Haskell, 2007-present</p></li>
|
||||
<li><p><strong>Beancount</strong> - Martin Blais’ variant.<br />
|
||||
Python, 2008-present</p></li>
|
||||
</ul>
|
||||
<p>Many more apps and add-on tools - <a href="https://plaintextaccounting.org/#software" class="uri">https://plaintextaccounting.org/#software</a></p>
|
||||
</section>
|
||||
<section id="whats-hledger" class="slide level2">
|
||||
<h2>What’s hledger ?</h2>
|
||||
<p>A suite of tools, file formats, and documentation for doing “plain text accounting”.</p>
|
||||
<p><a href="https://hledger.org" class="uri">https://hledger.org</a></p>
|
||||
</section>
|
||||
<section id="hledger-project-goals" class="slide level2">
|
||||
<h2>hledger project goals</h2>
|
||||
<p>I was a Ledger user and new Haskeller. I started hledger with many goals:</p>
|
||||
<ul>
|
||||
<li>acquire a more robust, usable, evolving incarnation of Ledger</li>
|
||||
<li>develop a consistent, effective accounting habit</li>
|
||||
<li>get better at Haskell</li>
|
||||
<li>find out if Haskell was good for end-user apps and maintainer productivity</li>
|
||||
<li>grow a useful, long-lasting, financially sustainable FOSS accounting project</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="an-end-user-haskell-application" class="slide level2">
|
||||
<h2>An end-user Haskell application</h2>
|
||||
<p>hledger is something that’s not yet common:</p>
|
||||
<p>An end user application (ie: not a programming tool), written in Haskell, that aims to be</p>
|
||||
<ul>
|
||||
<li>easy to install,</li>
|
||||
<li>dependable,</li>
|
||||
<li>and pleasing to use,</li>
|
||||
<li>on all major platforms,</li>
|
||||
<li>by non-techies as well as power users.</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="a-successful-foss-project" class="slide level2">
|
||||
<h2>A successful FOSS project</h2>
|
||||
<p>15 years, 134 contributors, 80-100 chatters, some number of happy users, useful to me every week.</p>
|
||||
<p>Reasonably successful.</p>
|
||||
<p>Not fulfilling my original goal of being financially self-sustaining and minimally time-consuming !</p>
|
||||
</section>
|
||||
<section id="tools" class="slide level2">
|
||||
<h2>Tools</h2>
|
||||
<ul>
|
||||
<li>hledger</li>
|
||||
<li>hledger-ui</li>
|
||||
<li>hledger-web</li>
|
||||
<li>hledger-iadd</li>
|
||||
<li>hledger-interest</li>
|
||||
<li>etc.</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="file-formats" class="slide level2">
|
||||
<h2>File formats</h2>
|
||||
<ul>
|
||||
<li>journal</li>
|
||||
<li>csv</li>
|
||||
<li>timeclock</li>
|
||||
<li>timedot</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="documentation" class="slide level2">
|
||||
<h2>Documentation</h2>
|
||||
<ul>
|
||||
<li>introductory</li>
|
||||
<li>reference</li>
|
||||
<li>cookbook</li>
|
||||
<li>developer</li>
|
||||
</ul>
|
||||
</section></section>
|
||||
<section>
|
||||
<section id="architecture" class="title-slide slide level1">
|
||||
<h1>Architecture</h1>
|
||||
<p><code>0:10 (25m)</code></p>
|
||||
</section>
|
||||
<section id="a-fast-run-through-the-evolution" class="slide level2">
|
||||
<h2>A fast run through the evolution</h2>
|
||||
<ul>
|
||||
<li>First commit</li>
|
||||
<li>First types</li>
|
||||
<li>First report</li>
|
||||
<li>Balance report</li>
|
||||
<li>Multi-column balance report</li>
|
||||
<li>Stateful parser</li>
|
||||
<li>Web interface</li>
|
||||
<li>Curses interface</li>
|
||||
<li>Package split</li>
|
||||
<li>Speed, features</li>
|
||||
<li>General currency conversion</li>
|
||||
<li>Valuation</li>
|
||||
<li>Always documentation</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="a-tour-of-the-codebase-and-project-today-2021q2" class="slide level2">
|
||||
<h2>A tour of the codebase and project today (2021Q2)</h2>
|
||||
</section>
|
||||
<section id="design-principles" class="slide level2">
|
||||
<h2>Design principles</h2>
|
||||
</section></section>
|
||||
<section>
|
||||
<section id="how-to.." class="title-slide slide level1">
|
||||
<h1>How to..</h1>
|
||||
<p><code>0:35 (25m)</code></p>
|
||||
</section>
|
||||
<section id="script-hledger" class="slide level2">
|
||||
<h2>Script hledger</h2>
|
||||
<ul>
|
||||
<li><a href="https://hledger.org/scripting.html" class="uri">https://hledger.org/scripting.html</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="integrate-hledger-in-your-app" class="slide level2">
|
||||
<h2>Integrate hledger in your app</h2>
|
||||
<ul>
|
||||
<li><p>Run cli, capture csv/json</p></li>
|
||||
<li><p>Run hledger-web, use http-json api</p></li>
|
||||
<li><p>Link with hledger-lib and/or other hledger packages, call public functions</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="investigate-a-hledger-bug" class="slide level2">
|
||||
<h2>Investigate a hledger bug</h2>
|
||||
<ul>
|
||||
<li><p>Basic troubleshooting - docs, comparison, minimisation, reproduction, support</p></li>
|
||||
<li><p>Code debugging</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="how-to-submit-a-pull-request" class="slide level2">
|
||||
<h2>How to submit a pull request</h2>
|
||||
<ul>
|
||||
<li><a href="https://hledger.org/CONTRIBUTING.html#pull-requests" class="uri">https://hledger.org/CONTRIBUTING.html#pull-requests</a></li>
|
||||
</ul>
|
||||
</section></section>
|
||||
<section id="q-a" class="title-slide slide level1">
|
||||
<h1>Q & A</h1>
|
||||
<p><code>1:00 (30m)</code></p>
|
||||
</section>
|
||||
|
||||
<section id="end" class="title-slide slide level1">
|
||||
<h1>End</h1>
|
||||
<p><code>1:30</code></p>
|
||||
<pre><code>$ git shortlog -s
|
||||
Aerex
|
||||
Aiken Cairncross
|
||||
Alejandro García Montoro
|
||||
Aleksandar Dimitrov
|
||||
Alex Chen
|
||||
Alvaro Fernando García
|
||||
Amarandus
|
||||
Amitai Burstein
|
||||
Andreas Pauley
|
||||
Andrew Jones
|
||||
Andriy Mykhaylyk
|
||||
Arnout Engelen
|
||||
Ben Boeckel
|
||||
Ben Creasy
|
||||
Boyd Kelly
|
||||
Brian Scott
|
||||
Brian Wignall
|
||||
Bryan Richter
|
||||
Caleb Maclennan
|
||||
Carel Fellinger
|
||||
Carl Richard Theodor Schneider
|
||||
Carlos Lopez-Camey
|
||||
Christian G. Warden
|
||||
Christoph Nicolai
|
||||
Clint Adams
|
||||
Colin Woodbury
|
||||
Damien Cassou
|
||||
David Reaver
|
||||
David Zhang
|
||||
Dmitry Astapov
|
||||
Dominik Süß
|
||||
Doug Goldstein
|
||||
Eli Flanagan
|
||||
Elijah Caine
|
||||
Eric Kow
|
||||
Eric Mertens
|
||||
Everett Hildenbrandt
|
||||
Evilham
|
||||
Felix Van der Jeugt
|
||||
Felix Yan
|
||||
Fun Ilrys (Nissar Chababy)
|
||||
Gabriel Ebner
|
||||
Gaith Hallak
|
||||
Gergely Risko
|
||||
Hans-Peter Deifel
|
||||
Henning Thielemann
|
||||
Imuli
|
||||
Jacek Generowicz
|
||||
Jacob Weisz
|
||||
Jakob Schöttl
|
||||
Jakub Zárybnický
|
||||
Jan Zerebecki
|
||||
Jeff Richards
|
||||
Jesse Rosenthal
|
||||
Joachim Breitner
|
||||
Joe Horsnell
|
||||
Johann Klähn
|
||||
Johannes Gerer
|
||||
John Wiegley
|
||||
Joseph Weston
|
||||
Joshua Chia
|
||||
Joshua Kehn
|
||||
Judah Jacobson
|
||||
Julien Moutinho
|
||||
Justin Le
|
||||
Kyle Marek-Spartz
|
||||
Luca Molteni
|
||||
Léo Gaspard
|
||||
M Parker
|
||||
Malte Brandy
|
||||
Mark Hansen
|
||||
Marko Kocić
|
||||
Martin Michlmayr
|
||||
Mateus Furquim
|
||||
Matthias Kauer
|
||||
Max Bolingbroke
|
||||
Michael Kainer
|
||||
Michael Sanders
|
||||
Michael Snoyman
|
||||
Michael Walker
|
||||
Mick Dekkers
|
||||
Mitchell Rosen
|
||||
Moritz Kiefer
|
||||
Mykola Orliuk
|
||||
Nadrieril
|
||||
Nicholas Niro
|
||||
Nick Ingolia
|
||||
Nicolas Wavrant
|
||||
Nikhil Jha
|
||||
Nissar Chababy
|
||||
Nolan Darilek
|
||||
Oliver Braun
|
||||
Omari Norman
|
||||
Pavan Rikhi
|
||||
Pavlo Kerestey
|
||||
Peter Simons
|
||||
Pia Mancini
|
||||
Rick Lupton
|
||||
Roman Cheplyaka
|
||||
Rui Chen
|
||||
Ryan Desfosses
|
||||
Sam Doshi
|
||||
Sam Jeeves
|
||||
Samuel May
|
||||
Sergei Trofimovich
|
||||
Sergey Astanin
|
||||
Shubham Lagwankar
|
||||
Simon Hengel
|
||||
Simon Michael
|
||||
SpicyCat
|
||||
Stefano Rodighiero
|
||||
Stephen Morgan
|
||||
Steven R. Baker
|
||||
TANIGUCHI Kohei
|
||||
Thomas R. Koll
|
||||
Tim Docker
|
||||
Timofey ZAKREVSKIY
|
||||
Trygve Laugstøl
|
||||
Vladimir Sorokin
|
||||
Vladimir Zhelezov
|
||||
Wad
|
||||
Xinruo Sun
|
||||
afarrow
|
||||
agander
|
||||
aragaer
|
||||
awjchen
|
||||
azure-pipelines[bot]
|
||||
flip111
|
||||
gwern
|
||||
jeevcat
|
||||
jungle-boogie
|
||||
legrostdg
|
||||
trevorriles
|
||||
zieone</code></pre>
|
||||
<!--
|
||||
https://pandoc.org/MANUAL.html#slide-shows
|
||||
|
||||
By default, the slide level is the highest heading level in the
|
||||
hierarchy that is followed immediately by content, and not another
|
||||
heading, somewhere in the document. In the example above, level-1
|
||||
headings are always followed by level-2 headings, which are followed
|
||||
by content, so the slide level is 2. This default can be overridden
|
||||
using the --slide-level option.
|
||||
|
||||
The document is carved up into slides according to the following rules:
|
||||
A horizontal rule always starts a new slide.
|
||||
A heading at the slide level always starts a new slide.
|
||||
Headings below the slide level in the hierarchy create headings within a slide.
|
||||
Headings above the slide level in the hierarchy create “title slides,” which just contain the section title and help to break the slide show into sections. Non-slide content under these headings will be included on the title slide (for HTML slide shows) or in a subsequent slide with the same title (for beamer).
|
||||
-->
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://unpkg.com/reveal.js@^4//dist/reveal.js"></script>
|
||||
|
||||
// reveal.js plugins
|
||||
<script src="https://unpkg.com/reveal.js@^4//plugin/notes/notes.js"></script>
|
||||
<script src="https://unpkg.com/reveal.js@^4//plugin/search/search.js"></script>
|
||||
<script src="https://unpkg.com/reveal.js@^4//plugin/zoom/zoom.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
// Full list of configuration options available at:
|
||||
// https://revealjs.com/config/
|
||||
Reveal.initialize({
|
||||
// Push each slide change to the browser history
|
||||
history: true,
|
||||
|
||||
// reveal.js plugins
|
||||
plugins: [
|
||||
RevealNotes,
|
||||
RevealSearch,
|
||||
RevealZoom
|
||||
]
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
363
doc/haskellerz/haskellerz.slidy.html
Normal file
363
doc/haskellerz/haskellerz.slidy.html
Normal file
@ -0,0 +1,363 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="Content-Style-Type" content="text/css" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="author" content="Simon Michael" />
|
||||
<meta name="date" content="2021-04-29" />
|
||||
<title>Inside hledger: an architectural tour and how-to</title>
|
||||
<style type="text/css">
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
span.underline{text-decoration: underline;}
|
||||
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
ul.task-list{list-style: none;}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" media="screen, projection, print"
|
||||
href="https://www.w3.org/Talks/Tools/Slidy2/styles/slidy.css" />
|
||||
<script src="https://www.w3.org/Talks/Tools/Slidy2/scripts/slidy.js"
|
||||
charset="utf-8" type="text/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="slide titlepage">
|
||||
<h1 class="title">Inside hledger: an architectural tour and how-to</h1>
|
||||
<p class="author">
|
||||
Simon Michael
|
||||
</p>
|
||||
<p class="date">April 29, 2021</p>
|
||||
</div>
|
||||
<div id="introductions" class="title-slide slide section level1">
|
||||
<h1>Introductions</h1>
|
||||
<p><code>0:00 (10m)</code></p>
|
||||
</div>
|
||||
<div id="who-am-i" class="slide section level2">
|
||||
<h1>Who am I ?</h1>
|
||||
<p>Simon Michael<br />
|
||||
Independent software consultant and developer.<br />
|
||||
<!-- Currently based in Hawaii. --> <a href="https://joyful.com" class="uri">https://joyful.com</a></p>
|
||||
<p>Started in the home computer era (Ireland, 80s). ZX-80, Pet, VIC, C64, Amiga, PC, Mac, VAX/VMS, unix..</p>
|
||||
<p>FOSS fan, contributor, project leader. Two big projects:</p>
|
||||
<ul>
|
||||
<li><p><strong>Zwiki</strong>, 1996-2006, wiki engine, Python/Zope</p></li>
|
||||
<li><p><strong>hledger</strong>, 2006-present, accounting tool, Haskell</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="overview-of-talk" class="slide section level2">
|
||||
<h1>Overview of talk</h1>
|
||||
<ul>
|
||||
<li><p>A quick intro to plain text accounting and hledger. (10m)</p></li>
|
||||
<li><p>A tour of hledger’s architecture, codebase, evolutions, and design principles. (25m)</p></li>
|
||||
<li><p>How to script and develop hledger: custom commands, calling from other apps, troubleshooting, bug investigation, effective pull requests. (25m)</p></li>
|
||||
<li><p>Q&A to go deeper on whatever you like. (30m)</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="whats-plain-text-accounting" class="slide section level2">
|
||||
<h1>What’s Plain Text Accounting ?</h1>
|
||||
<p>A name I proposed (and a website I built) to help unify and grow the communities around Ledger, hledger, Beancount and similar accounting tools.</p>
|
||||
<p><a href="https://plaintextaccounting.org" class="uri">https://plaintextaccounting.org</a></p>
|
||||
</div>
|
||||
<div id="the-pta-ecosystem" class="slide section level2">
|
||||
<h1>The PTA ecosystem</h1>
|
||||
<p>The “big three” apps:</p>
|
||||
<ul>
|
||||
<li><p><strong>Ledger</strong> - John Wiegley’s pioneering command line accounting app, inspiration for all the rest.<br />
|
||||
C++, 2003-present</p></li>
|
||||
<li><p><strong>hledger</strong> - Simon Michael’s rewrite/remix.<br />
|
||||
Haskell, 2007-present</p></li>
|
||||
<li><p><strong>Beancount</strong> - Martin Blais’ variant.<br />
|
||||
Python, 2008-present</p></li>
|
||||
</ul>
|
||||
<p>Many more apps and add-on tools - <a href="https://plaintextaccounting.org/#software" class="uri">https://plaintextaccounting.org/#software</a></p>
|
||||
</div>
|
||||
<div id="whats-hledger" class="slide section level2">
|
||||
<h1>What’s hledger ?</h1>
|
||||
<p>A suite of tools, file formats, and documentation for doing “plain text accounting”.</p>
|
||||
<p><a href="https://hledger.org" class="uri">https://hledger.org</a></p>
|
||||
</div>
|
||||
<div id="hledger-project-goals" class="slide section level2">
|
||||
<h1>hledger project goals</h1>
|
||||
<p>I was a Ledger user and new Haskeller. I started hledger with many goals:</p>
|
||||
<ul>
|
||||
<li>acquire a more robust, usable, evolving incarnation of Ledger</li>
|
||||
<li>develop a consistent, effective accounting habit</li>
|
||||
<li>get better at Haskell</li>
|
||||
<li>find out if Haskell was good for end-user apps and maintainer productivity</li>
|
||||
<li>grow a useful, long-lasting, financially sustainable FOSS accounting project</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="an-end-user-haskell-application" class="slide section level2">
|
||||
<h1>An end-user Haskell application</h1>
|
||||
<p>hledger is something that’s not yet common:</p>
|
||||
<p>An end user application (ie: not a programming tool), written in Haskell, that aims to be</p>
|
||||
<ul>
|
||||
<li>easy to install,</li>
|
||||
<li>dependable,</li>
|
||||
<li>and pleasing to use,</li>
|
||||
<li>on all major platforms,</li>
|
||||
<li>by non-techies as well as power users.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="a-successful-foss-project" class="slide section level2">
|
||||
<h1>A successful FOSS project</h1>
|
||||
<p>15 years, 134 contributors, 80-100 chatters, some number of happy users, useful to me every week.</p>
|
||||
<p>Reasonably successful.</p>
|
||||
<p>Not fulfilling my original goal of being financially self-sustaining and minimally time-consuming !</p>
|
||||
</div>
|
||||
<div id="tools" class="slide section level2">
|
||||
<h1>Tools</h1>
|
||||
<ul>
|
||||
<li>hledger</li>
|
||||
<li>hledger-ui</li>
|
||||
<li>hledger-web</li>
|
||||
<li>hledger-iadd</li>
|
||||
<li>hledger-interest</li>
|
||||
<li>etc.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="file-formats" class="slide section level2">
|
||||
<h1>File formats</h1>
|
||||
<ul>
|
||||
<li>journal</li>
|
||||
<li>csv</li>
|
||||
<li>timeclock</li>
|
||||
<li>timedot</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="documentation" class="slide section level2">
|
||||
<h1>Documentation</h1>
|
||||
<ul>
|
||||
<li>introductory</li>
|
||||
<li>reference</li>
|
||||
<li>cookbook</li>
|
||||
<li>developer</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="architecture" class="title-slide slide section level1">
|
||||
<h1>Architecture</h1>
|
||||
<p><code>0:10 (25m)</code></p>
|
||||
</div>
|
||||
<div id="a-fast-run-through-the-evolution" class="slide section level2">
|
||||
<h1>A fast run through the evolution</h1>
|
||||
<ul>
|
||||
<li>First commit</li>
|
||||
<li>First types</li>
|
||||
<li>First report</li>
|
||||
<li>Balance report</li>
|
||||
<li>Multi-column balance report</li>
|
||||
<li>Stateful parser</li>
|
||||
<li>Web interface</li>
|
||||
<li>Curses interface</li>
|
||||
<li>Package split</li>
|
||||
<li>Speed, features</li>
|
||||
<li>General currency conversion</li>
|
||||
<li>Valuation</li>
|
||||
<li>Always documentation</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="a-tour-of-the-codebase-and-project-today-2021q2" class="slide section level2">
|
||||
<h1>A tour of the codebase and project today (2021Q2)</h1>
|
||||
</div>
|
||||
<div id="design-principles" class="slide section level2">
|
||||
<h1>Design principles</h1>
|
||||
</div>
|
||||
|
||||
<div id="how-to.." class="title-slide slide section level1">
|
||||
<h1>How to..</h1>
|
||||
<p><code>0:35 (25m)</code></p>
|
||||
</div>
|
||||
<div id="script-hledger" class="slide section level2">
|
||||
<h1>Script hledger</h1>
|
||||
<ul>
|
||||
<li><a href="https://hledger.org/scripting.html" class="uri">https://hledger.org/scripting.html</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="integrate-hledger-in-your-app" class="slide section level2">
|
||||
<h1>Integrate hledger in your app</h1>
|
||||
<ul>
|
||||
<li><p>Run cli, capture csv/json</p></li>
|
||||
<li><p>Run hledger-web, use http-json api</p></li>
|
||||
<li><p>Link with hledger-lib and/or other hledger packages, call public functions</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="investigate-a-hledger-bug" class="slide section level2">
|
||||
<h1>Investigate a hledger bug</h1>
|
||||
<ul>
|
||||
<li><p>Basic troubleshooting - docs, comparison, minimisation, reproduction, support</p></li>
|
||||
<li><p>Code debugging</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="how-to-submit-a-pull-request" class="slide section level2">
|
||||
<h1>How to submit a pull request</h1>
|
||||
<ul>
|
||||
<li><a href="https://hledger.org/CONTRIBUTING.html#pull-requests" class="uri">https://hledger.org/CONTRIBUTING.html#pull-requests</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="q-a" class="title-slide slide section level1">
|
||||
<h1>Q & A</h1>
|
||||
<p><code>1:00 (30m)</code></p>
|
||||
</div>
|
||||
|
||||
<div id="end" class="title-slide slide section level1">
|
||||
<h1>End</h1>
|
||||
<p><code>1:30</code></p>
|
||||
<pre><code>$ git shortlog -s
|
||||
Aerex
|
||||
Aiken Cairncross
|
||||
Alejandro García Montoro
|
||||
Aleksandar Dimitrov
|
||||
Alex Chen
|
||||
Alvaro Fernando García
|
||||
Amarandus
|
||||
Amitai Burstein
|
||||
Andreas Pauley
|
||||
Andrew Jones
|
||||
Andriy Mykhaylyk
|
||||
Arnout Engelen
|
||||
Ben Boeckel
|
||||
Ben Creasy
|
||||
Boyd Kelly
|
||||
Brian Scott
|
||||
Brian Wignall
|
||||
Bryan Richter
|
||||
Caleb Maclennan
|
||||
Carel Fellinger
|
||||
Carl Richard Theodor Schneider
|
||||
Carlos Lopez-Camey
|
||||
Christian G. Warden
|
||||
Christoph Nicolai
|
||||
Clint Adams
|
||||
Colin Woodbury
|
||||
Damien Cassou
|
||||
David Reaver
|
||||
David Zhang
|
||||
Dmitry Astapov
|
||||
Dominik Süß
|
||||
Doug Goldstein
|
||||
Eli Flanagan
|
||||
Elijah Caine
|
||||
Eric Kow
|
||||
Eric Mertens
|
||||
Everett Hildenbrandt
|
||||
Evilham
|
||||
Felix Van der Jeugt
|
||||
Felix Yan
|
||||
Fun Ilrys (Nissar Chababy)
|
||||
Gabriel Ebner
|
||||
Gaith Hallak
|
||||
Gergely Risko
|
||||
Hans-Peter Deifel
|
||||
Henning Thielemann
|
||||
Imuli
|
||||
Jacek Generowicz
|
||||
Jacob Weisz
|
||||
Jakob Schöttl
|
||||
Jakub Zárybnický
|
||||
Jan Zerebecki
|
||||
Jeff Richards
|
||||
Jesse Rosenthal
|
||||
Joachim Breitner
|
||||
Joe Horsnell
|
||||
Johann Klähn
|
||||
Johannes Gerer
|
||||
John Wiegley
|
||||
Joseph Weston
|
||||
Joshua Chia
|
||||
Joshua Kehn
|
||||
Judah Jacobson
|
||||
Julien Moutinho
|
||||
Justin Le
|
||||
Kyle Marek-Spartz
|
||||
Luca Molteni
|
||||
Léo Gaspard
|
||||
M Parker
|
||||
Malte Brandy
|
||||
Mark Hansen
|
||||
Marko Kocić
|
||||
Martin Michlmayr
|
||||
Mateus Furquim
|
||||
Matthias Kauer
|
||||
Max Bolingbroke
|
||||
Michael Kainer
|
||||
Michael Sanders
|
||||
Michael Snoyman
|
||||
Michael Walker
|
||||
Mick Dekkers
|
||||
Mitchell Rosen
|
||||
Moritz Kiefer
|
||||
Mykola Orliuk
|
||||
Nadrieril
|
||||
Nicholas Niro
|
||||
Nick Ingolia
|
||||
Nicolas Wavrant
|
||||
Nikhil Jha
|
||||
Nissar Chababy
|
||||
Nolan Darilek
|
||||
Oliver Braun
|
||||
Omari Norman
|
||||
Pavan Rikhi
|
||||
Pavlo Kerestey
|
||||
Peter Simons
|
||||
Pia Mancini
|
||||
Rick Lupton
|
||||
Roman Cheplyaka
|
||||
Rui Chen
|
||||
Ryan Desfosses
|
||||
Sam Doshi
|
||||
Sam Jeeves
|
||||
Samuel May
|
||||
Sergei Trofimovich
|
||||
Sergey Astanin
|
||||
Shubham Lagwankar
|
||||
Simon Hengel
|
||||
Simon Michael
|
||||
SpicyCat
|
||||
Stefano Rodighiero
|
||||
Stephen Morgan
|
||||
Steven R. Baker
|
||||
TANIGUCHI Kohei
|
||||
Thomas R. Koll
|
||||
Tim Docker
|
||||
Timofey ZAKREVSKIY
|
||||
Trygve Laugstøl
|
||||
Vladimir Sorokin
|
||||
Vladimir Zhelezov
|
||||
Wad
|
||||
Xinruo Sun
|
||||
afarrow
|
||||
agander
|
||||
aragaer
|
||||
awjchen
|
||||
azure-pipelines[bot]
|
||||
flip111
|
||||
gwern
|
||||
jeevcat
|
||||
jungle-boogie
|
||||
legrostdg
|
||||
trevorriles
|
||||
zieone</code></pre>
|
||||
<!--
|
||||
https://pandoc.org/MANUAL.html#slide-shows
|
||||
|
||||
By default, the slide level is the highest heading level in the
|
||||
hierarchy that is followed immediately by content, and not another
|
||||
heading, somewhere in the document. In the example above, level-1
|
||||
headings are always followed by level-2 headings, which are followed
|
||||
by content, so the slide level is 2. This default can be overridden
|
||||
using the --slide-level option.
|
||||
|
||||
The document is carved up into slides according to the following rules:
|
||||
A horizontal rule always starts a new slide.
|
||||
A heading at the slide level always starts a new slide.
|
||||
Headings below the slide level in the hierarchy create headings within a slide.
|
||||
Headings above the slide level in the hierarchy create “title slides,” which just contain the section title and help to break the slide show into sections. Non-slide content under these headings will be included on the title slide (for HTML slide shows) or in a subsequent slide with the same title (for beamer).
|
||||
-->
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue
Block a user