Merge branch 'master' into 1984-source-name-and-position-for-forecast

This commit is contained in:
Simon Michael 2023-01-23 16:04:00 -10:00 committed by GitHub
commit 9497472e64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 130 additions and 14 deletions

View File

@ -376,5 +376,21 @@ tests_AccountName = testGroup "AccountName" [
accountNameInferType "revenues" @?= Just Revenue
accountNameInferType "revenue" @?= Just Revenue
accountNameInferType "income" @?= Just Revenue
,testCase "joinAccountNames" $ do
joinAccountNames "assets" "cash" @?= "assets:cash"
joinAccountNames "assets:cash" "a" @?= "assets:cash:a"
joinAccountNames "assets" "(cash)" @?= "(assets:cash)"
joinAccountNames "assets" "[cash]" @?= "[assets:cash]"
joinAccountNames "(assets)" "cash" @?= "(assets:cash)"
joinAccountNames "" "assets" @?= "assets"
joinAccountNames "assets" "" @?= "assets"
,testCase "concatAccountNames" $ do
concatAccountNames ["assets", "cash"] @?= "assets:cash"
concatAccountNames ["assets:cash", "a"] @?= "assets:cash:a"
concatAccountNames ["assets", "(cash)"] @?= "(assets:cash)"
concatAccountNames ["assets", "[cash]"] @?= "[assets:cash]"
concatAccountNames ["(assets)", "cash"] @?= "(assets:cash)"
concatAccountNames ["", "assets"] @?= ":assets"
concatAccountNames ["assets", ""] @?= "assets:"
]

View File

@ -433,7 +433,7 @@ addAccountDeclaration (a,cmt,tags,pos) = do
modify' (\j ->
let
decls = jdeclaredaccounts j
d = (a, nullaccountdeclarationinfo{
d = (textUnbracket a, nullaccountdeclarationinfo{
adicomment = cmt
,aditags = tags
,adideclarationorder = length decls + 1 -- gets renumbered when Journals are finalised or merged

View File

@ -53,6 +53,7 @@ where
import Data.Char (digitToInt)
import Data.Default (def)
import Data.Maybe (catMaybes)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
@ -175,12 +176,17 @@ isDoubleQuoted :: Text -> Bool
isDoubleQuoted s =
T.length s >= 2 && T.head s == '"' && T.last s == '"'
-- | Remove all matching pairs of square brackets and parentheses from the text.
textUnbracket :: Text -> Text
textUnbracket s
| T.null s = s
| T.head s == '[' && T.last s == ']' = T.init $ T.tail s
| T.head s == '(' && T.last s == ')' = T.init $ T.tail s
| otherwise = s
textUnbracket s = T.drop stripN $ T.dropEnd stripN s
where
matchBracket :: Char -> Maybe Char
matchBracket '(' = Just ')'
matchBracket '[' = Just ']'
matchBracket _ = Nothing
expectedClosingBrackets = catMaybes $ takeWhile (/= Nothing) $ matchBracket <$> T.unpack s
stripN = length $ takeWhile (uncurry (==)) $ zip expectedClosingBrackets $ reverse $ T.unpack s
-- | Join several multi-line strings as side-by-side rectangular strings of the same height, top-padded.
-- Treats wide characters as double width.
@ -271,5 +277,18 @@ tests_Text = testGroup "Text" [
quoteIfSpaced "mimi's cafe" @?= "\"mimi's cafe\""
quoteIfSpaced "\"alex\" cafe" @?= "\"\\\"alex\\\" cafe\""
quoteIfSpaced "le'shan's cafe" @?= "\"le'shan's cafe\""
quoteIfSpaced "\"be'any's\" cafe" @?= "\"\\\"be'any's\\\" cafe\""
quoteIfSpaced "\"be'any's\" cafe" @?= "\"\\\"be'any's\\\" cafe\"",
testCase "textUnbracket" $ do
textUnbracket "()" @?= ""
textUnbracket "(a)" @?= "a"
textUnbracket "(ab)" @?= "ab"
textUnbracket "[ab]" @?= "ab"
textUnbracket "([ab])" @?= "ab"
textUnbracket "(()b)" @?= "()b"
textUnbracket "[[]b]" @?= "[]b"
textUnbracket "[()b]" @?= "()b"
textUnbracket "[([]())]" @?= "[]()"
textUnbracket "[([[[()]]])]" @?= ""
textUnbracket "[([[[(]]])]" @?= "("
textUnbracket "[([[[)]]])]" @?= ")"
]

View File

@ -1129,15 +1129,47 @@ But if you accidentally leave only one space (or tab) before the amount, the amo
## Account names
Account names typically have several parts separated by a full colon, from
which hledger derives a hierarchical chart of accounts. They can be
anything you like, but in finance there are traditionally five top-level
accounts: `assets`, `liabilities`, `revenue`, `expenses`, and `equity`.
Accounts are the main way of categorising things in hledger.
As in Double Entry Bookkeeping, they can represent real world accounts (such as a bank account),
or more abstract categories such as "money borrowed from Frank" or "money spent on electricity".
Account names may contain single spaces, eg: `assets:accounts receivable`.
Because of this, they must always be followed by **two or more spaces** (or newline).
You can use any account names you like, but we usually start with the traditional accounting categories,
which in english are `assets`, `liabilities`, `equity`, `revenues`, `expenses`.
(You might see these referred to as A, L, E, R, X for short.)
Account names can be [aliased](#account-aliases).
For more precise reporting, we usually divide the top level accounts into more detailed subaccounts,
by writing a full colon between account name parts.
For example, from the account names `assets:bank:checking` and `expenses:food`,
hledger will infer this hierarchy of five accounts:
```
assets
assets:bank
assets:bank:checking
expenses
expenses:food
```
Shown as an outline, the hierarchical tree structure is more clear:
```
assets
bank
checking
expenses
food
```
hledger reports can summarise the account tree to any depth,
so you can go as deep as you like with subcategories,
but keeping your account names relatively simple may be best when starting out.
Account names may be capitalised or not; they may contain letters, numbers, symbols, or single spaces.
Note, when an account name and an amount are written on the same line,
they must be separated by **two or more spaces** (or tabs).
Parentheses or brackets enclosing the full account name indicate [virtual postings](#virtual-postings),
described below.
Parentheses or brackets internal to the account name have no special meaning.
Account names can be altered temporarily or permanently by [account aliases](#account-aliases).
## Amounts
@ -1769,6 +1801,12 @@ They are written as the word `account` followed by a hledger-style [account name
account assets:bank:checking
```
Note, however, that account names declared in the account directive are stripped of surrounding brackets and parentheses.
The above directive is thus equivalent to this:
```journal
account (assets:bank:checking)
```
### Account comments
Text following **two or more spaces** and `;` at the end of an account directive line,

View File

@ -68,6 +68,29 @@ account Expenses:Food
$ hledger -f- accounts
Expenses:Food
# 5. It unbrackets account names.
<
account (a)
account (a:aa)
account (a:(aaa))
account [b]
account [b:bb]
account [b:[bbb]]
account [([c])]
account [([c:cc])]
account [([c:[ccc]])]
$ hledger -f- accounts
a
a:aa
a:(aaa)
b
b:bb
b:[bbb]
c
c:cc
c:[ccc]
# TODO
# a trailing : should give a clear error
# 2009/1/1

View File

@ -1,9 +1,13 @@
# Tests for parentheses and brackets in account names
# 1. Parentheses in the middle of an account name are ignored.
hledger -f - print
<<<
2009-01-01 x
a 2
b (b) b -1
c
>>>
2009-01-01 x
a 2
@ -11,3 +15,19 @@ hledger -f - print
c
>>>=0
# 2. Nested parentheses are removed and the outer brackets are used as the type.
hledger -f- print
<<<
2023-01-01
[([(a)])] 1
[(b:bb)] 1
[b:[bbb]]
>>>
2023-01-01
[a] 1
[b:bb] 1
[b:[bbb]]
>>>=0