Update 2024-01-27 11:21 OpenBSD/amd64-x13
This commit is contained in:
parent
63bfa3234f
commit
cab3f26ede
339
.vim/pack/plugins/start/vim-ledger/COPYING
Normal file
339
.vim/pack/plugins/start/vim-ledger/COPYING
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
128
.vim/pack/plugins/start/vim-ledger/README.mkd
Normal file
128
.vim/pack/plugins/start/vim-ledger/README.mkd
Normal file
@ -0,0 +1,128 @@
|
||||
vim-ledger
|
||||
==========
|
||||
|
||||
This is the ledger filetype for Vim.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Copy each file to the corresponding directory in your `~/.vim` directory or
|
||||
install using [Pathogen](https://github.com/tpope/vim-pathogen).
|
||||
|
||||
You can also use a modeline like this in every ledger file:
|
||||
|
||||
vim:filetype=ledger
|
||||
|
||||
Tips and useful commands
|
||||
------------------------
|
||||
|
||||
* Try account-completion (as explained below)
|
||||
|
||||
* `:call ledger#transaction_date_set(line('.'), 'auxiliary')`
|
||||
|
||||
will set today's date as the auxiliary date of the current transaction. You
|
||||
can use also `primary` or `unshift` in place of `auxiliary`. When you pass
|
||||
"unshift" the old primary date will be set as the auxiliary date and today's
|
||||
date will be set as the new primary date.
|
||||
To use a different date pass a date measured in seconds since 1st Jan 1970
|
||||
as the third argument.
|
||||
|
||||
* `:call ledger#transaction_state_set(line('.'), '*')`
|
||||
|
||||
sets the state of the current transaction to '*'. You can use this in custom
|
||||
mappings.
|
||||
|
||||
* `:call ledger#transaction_state_toggle(line('.'), ' *?!')`
|
||||
|
||||
will toggle through the provided transaction states. You can map this to
|
||||
double-clicking for example:
|
||||
|
||||
noremap <silent><buffer> <2-LeftMouse>\
|
||||
:call ledger#transaction_state_toggle(line('.'), ' *?!')<CR>
|
||||
|
||||
* Align commodities at the decimal point. See `help ledger-tips`.
|
||||
|
||||
* `:call ledger#entry()`
|
||||
|
||||
will replace the text on the current line with a new transaction based
|
||||
on the replaced text.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Include the following let-statements somewhere in your `.vimrc` to modify the
|
||||
behaviour of the ledger filetype.
|
||||
|
||||
* Number of columns that will be used to display the foldtext. Set this when
|
||||
you think that the amount is too far off to the right.
|
||||
|
||||
let g:ledger_maxwidth = 80
|
||||
|
||||
* String that will be used to fill the space between account name and amount in
|
||||
the foldtext. Set this to get some kind of lines or visual aid.
|
||||
|
||||
let g:ledger_fillstring = ' -'
|
||||
|
||||
* If you want the account completion to be sorted by level of detail/depth
|
||||
instead of alphabetical, include the following line:
|
||||
|
||||
let g:ledger_detailed_first = 1
|
||||
|
||||
* By default vim will fold ledger transactions, leaving surrounding blank lines
|
||||
unfolded. You can use `g:ledger_fold_blanks` to hide blank lines following a
|
||||
transaction.
|
||||
|
||||
let g:ledger_fold_blanks = 0
|
||||
|
||||
A value of 0 will disable folding of blank lines, 1 will allow folding of a
|
||||
single blank line between transactions; any larger value will enable folding
|
||||
undconditionally.
|
||||
|
||||
Note that only lines containing no trailing spaces are considered for
|
||||
folding. You can take advantage of this to disable this feature on a
|
||||
case-by-case basis.
|
||||
|
||||
Completion
|
||||
----------
|
||||
|
||||
Omni completion is currently implemented for account names only.
|
||||
|
||||
### Accounts
|
||||
|
||||
Account names are matched by the start of every sub-level. When you
|
||||
insert an account name like this:
|
||||
|
||||
Asse<C-X><C-O>
|
||||
|
||||
You will get a list of top-level accounts that start like this.
|
||||
|
||||
Go ahead and try something like:
|
||||
|
||||
As:Ban:Che<C-X><C-O>
|
||||
|
||||
When you have an account like this, 'Assets:Bank:Checking' should show up.
|
||||
|
||||
When you want to complete on a virtual transaction, it's currently best
|
||||
to keep the cursor in front of the closing bracket. Of course you can
|
||||
insert the closing bracket after calling the completion, too.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Copyright 2019 Caleb Maclennan
|
||||
Copyright 2009–2017 Johann Klähn
|
||||
Copyright 2009 Stefan Karrmann
|
||||
Copyright 2005 Wolfgang Oertl
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation, either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <https://www.gnu.org/licenses/>.
|
733
.vim/pack/plugins/start/vim-ledger/autoload/ledger.vim
Normal file
733
.vim/pack/plugins/start/vim-ledger/autoload/ledger.vim
Normal file
@ -0,0 +1,733 @@
|
||||
" vim:ts=2:sw=2:sts=2:foldmethod=marker
|
||||
function! ledger#transaction_state_toggle(lnum, ...)
|
||||
if a:0 == 1
|
||||
let chars = a:1
|
||||
else
|
||||
let chars = ' *'
|
||||
endif
|
||||
let trans = s:transaction.from_lnum(a:lnum)
|
||||
if empty(trans) || has_key(trans, 'expr')
|
||||
return
|
||||
endif
|
||||
|
||||
let old = has_key(trans, 'state') ? trans['state'] : ' '
|
||||
let i = stridx(chars, old) + 1
|
||||
let new = chars[i >= len(chars) ? 0 : i]
|
||||
|
||||
call trans.set_state(new)
|
||||
|
||||
call setline(trans['head'], trans.format_head())
|
||||
endf
|
||||
|
||||
function! ledger#transaction_state_set(lnum, char)
|
||||
" modifies or sets the state of the transaction at the cursor,
|
||||
" removing the state altogether if a:char is empty
|
||||
let trans = s:transaction.from_lnum(a:lnum)
|
||||
if empty(trans) || has_key(trans, 'expr')
|
||||
return
|
||||
endif
|
||||
|
||||
call trans.set_state(a:char)
|
||||
|
||||
call setline(trans['head'], trans.format_head())
|
||||
endf
|
||||
|
||||
function! ledger#transaction_date_set(lnum, type, ...) "{{{1
|
||||
let time = a:0 == 1 ? a:1 : localtime()
|
||||
let trans = s:transaction.from_lnum(a:lnum)
|
||||
if empty(trans) || has_key(trans, 'expr')
|
||||
return
|
||||
endif
|
||||
|
||||
let formatted = strftime(g:ledger_date_format, time)
|
||||
if has_key(trans, 'date') && ! empty(trans['date'])
|
||||
let date = split(trans['date'], '=')
|
||||
else
|
||||
let date = [formatted]
|
||||
endif
|
||||
|
||||
if a:type =~? 'effective\|actual'
|
||||
echoerr "actual/effective arguments were replaced by primary/auxiliary"
|
||||
return
|
||||
endif
|
||||
|
||||
if a:type ==? 'primary'
|
||||
let date[0] = formatted
|
||||
elseif a:type ==? 'auxiliary'
|
||||
if time < 0
|
||||
" remove auxiliary date
|
||||
let date = [date[0]]
|
||||
else
|
||||
" set auxiliary date
|
||||
if len(date) >= 2
|
||||
let date[1] = formatted
|
||||
else
|
||||
call add(date, formatted)
|
||||
endif
|
||||
endif
|
||||
elseif a:type ==? 'unshift'
|
||||
let date = [formatted, date[0]]
|
||||
endif
|
||||
|
||||
let trans['date'] = join(date[0:1], '=')
|
||||
|
||||
call setline(trans['head'], trans.format_head())
|
||||
endf "}}}
|
||||
|
||||
" == get transactions ==
|
||||
|
||||
function! ledger#transaction_from_lnum(lnum)
|
||||
return s:transaction.from_lnum(a:lnum)
|
||||
endf
|
||||
|
||||
function! ledger#transactions(...)
|
||||
if a:0 == 2
|
||||
let lnum = a:1
|
||||
let end = a:2
|
||||
elseif a:0 == 0
|
||||
let lnum = 1
|
||||
let end = line('$')
|
||||
else
|
||||
throw "wrong number of arguments for get_transactions()"
|
||||
return []
|
||||
endif
|
||||
|
||||
" safe view / position
|
||||
let view = winsaveview()
|
||||
let fe = &foldenable
|
||||
set nofoldenable
|
||||
|
||||
let transactions = []
|
||||
call cursor(lnum, 0)
|
||||
while lnum && lnum < end
|
||||
let trans = s:transaction.from_lnum(lnum)
|
||||
if ! empty(trans)
|
||||
call add(transactions, trans)
|
||||
call cursor(trans['tail'], 0)
|
||||
endif
|
||||
let lnum = search('^[~=[:digit:]]', 'cW')
|
||||
endw
|
||||
|
||||
" restore view / position
|
||||
let &foldenable = fe
|
||||
call winrestview(view)
|
||||
|
||||
return transactions
|
||||
endf
|
||||
|
||||
" == transaction object implementation ==
|
||||
|
||||
let s:transaction = {} "{{{1
|
||||
function! s:transaction.new() dict
|
||||
return copy(s:transaction)
|
||||
endf
|
||||
|
||||
function! s:transaction.from_lnum(lnum) dict "{{{2
|
||||
let [head, tail] = s:get_transaction_extents(a:lnum)
|
||||
if ! head
|
||||
return {}
|
||||
endif
|
||||
|
||||
let trans = copy(s:transaction)
|
||||
let trans['head'] = head
|
||||
let trans['tail'] = tail
|
||||
|
||||
" split off eventual comments at the end of line
|
||||
let line = split(getline(head), '\ze\s*\%(\t\| \);', 1)
|
||||
if len(line) > 1
|
||||
let trans['appendix'] = join(line[1:], '')
|
||||
endif
|
||||
|
||||
" parse rest of line
|
||||
" FIXME (minor): will not preserve spacing (see 'join(parts)')
|
||||
let parts = split(line[0], '\s\+')
|
||||
if parts[0] ==# '~'
|
||||
let trans['expr'] = join(parts[1:])
|
||||
return trans
|
||||
elseif parts[0] ==# '='
|
||||
let trans['auto'] = join(parts[1:])
|
||||
return trans
|
||||
elseif parts[0] !~ '^\d'
|
||||
" this case is avoided in s:get_transaction_extents(),
|
||||
" but we'll check anyway.
|
||||
return {}
|
||||
endif
|
||||
|
||||
for part in parts
|
||||
if ! has_key(trans, 'date') && part =~ '^\d'
|
||||
let trans['date'] = part
|
||||
elseif ! has_key(trans, 'code') && part =~ '^([^)]*)$'
|
||||
let trans['code'] = part[1:-2]
|
||||
elseif ! has_key(trans, 'state') && part =~ '^[[:punct:]]$'
|
||||
" the first character by itself is assumed to be the state of the transaction.
|
||||
let trans['state'] = part
|
||||
else
|
||||
" everything after date/code or state belongs to the description
|
||||
break
|
||||
endif
|
||||
call remove(parts, 0)
|
||||
endfor
|
||||
|
||||
let trans['description'] = join(parts)
|
||||
return trans
|
||||
endf "}}}
|
||||
|
||||
function! s:transaction.set_state(char) dict "{{{2
|
||||
if has_key(self, 'state') && a:char =~ '^\s*$'
|
||||
call remove(self, 'state')
|
||||
else
|
||||
let self['state'] = a:char
|
||||
endif
|
||||
endf "}}}
|
||||
|
||||
function! s:transaction.parse_body(...) dict "{{{2
|
||||
if a:0 == 2
|
||||
let head = a:1
|
||||
let tail = a:2
|
||||
elseif a:0 == 0
|
||||
let head = self['head']
|
||||
let tail = self['tail']
|
||||
else
|
||||
throw "wrong number of arguments for parse_body()"
|
||||
return []
|
||||
endif
|
||||
|
||||
if ! head || tail <= head
|
||||
return []
|
||||
endif
|
||||
|
||||
let lnum = head
|
||||
let tags = {}
|
||||
let postings = []
|
||||
while lnum <= tail
|
||||
let line = split(getline(lnum), '\s*\%(\t\| \);', 1)
|
||||
|
||||
if line[0] =~ '^\s\+[^[:blank:];]'
|
||||
" posting
|
||||
let [state, rest] = matchlist(line[0], '^\s\+\([*!]\?\)\s*\(.*\)$')[1:2]
|
||||
if rest =~ '\t\| '
|
||||
let [account, amount] = matchlist(rest, '^\(.\{-}\)\%(\t\| \)\s*\(.\{-}\)\s*$')[1:2]
|
||||
else
|
||||
let amount = ''
|
||||
let account = matchstr(rest, '^\s*\zs.\{-}\ze\s*$')
|
||||
endif
|
||||
call add(postings, {'account': account, 'amount': amount, 'state': state})
|
||||
end
|
||||
|
||||
" where are tags to be stored?
|
||||
if empty(postings)
|
||||
" they belong to the transaction
|
||||
let tag_container = tags
|
||||
else
|
||||
" they belong to last posting
|
||||
if ! has_key(postings[-1], 'tags')
|
||||
let postings[-1]['tags'] = {}
|
||||
endif
|
||||
let tag_container = postings[-1]['tags']
|
||||
endif
|
||||
|
||||
let comment = join(line[1:], ' ;')
|
||||
if comment =~ '^\s*:'
|
||||
" tags without values
|
||||
for t in s:findall(comment, ':\zs[^:[:blank:]]\([^:]*[^:[:blank:]]\)\?\ze:')
|
||||
let tag_container[t] = ''
|
||||
endfor
|
||||
elseif comment =~ '^\s*[^:[:blank:]][^:]\+:'
|
||||
" tag with value
|
||||
let key = matchstr(comment, '^\s*\zs[^:]\+\ze:')
|
||||
if ! empty(key)
|
||||
let val = matchstr(comment, ':\s*\zs.*\ze\s*$')
|
||||
let tag_container[key] = val
|
||||
endif
|
||||
endif
|
||||
let lnum += 1
|
||||
endw
|
||||
return [tags, postings]
|
||||
endf "}}}
|
||||
|
||||
function! s:transaction.format_head() dict "{{{2
|
||||
if has_key(self, 'expr')
|
||||
return '~ '.self['expr']
|
||||
elseif has_key(self, 'auto')
|
||||
return '= '.self['auto']
|
||||
endif
|
||||
|
||||
let parts = []
|
||||
if has_key(self, 'date') | call add(parts, self['date']) | endif
|
||||
if has_key(self, 'state') | call add(parts, self['state']) | endif
|
||||
if has_key(self, 'code') | call add(parts, '('.self['code'].')') | endif
|
||||
if has_key(self, 'description') | call add(parts, self['description']) | endif
|
||||
|
||||
let line = join(parts)
|
||||
if has_key(self, 'appendix') | let line .= self['appendix'] | endif
|
||||
|
||||
return line
|
||||
endf "}}}
|
||||
"}}}
|
||||
|
||||
" == helper functions ==
|
||||
|
||||
" get a list of declared accounts in the buffer
|
||||
function! ledger#declared_accounts(...)
|
||||
if a:0 == 2
|
||||
let lnum = a:1
|
||||
let lend = a:2
|
||||
elseif a:0 == 0
|
||||
let lnum = 1
|
||||
let lend = line('$')
|
||||
else
|
||||
throw "wrong number of arguments for ledger#declared_accounts()"
|
||||
return []
|
||||
endif
|
||||
|
||||
" save view / position
|
||||
let view = winsaveview()
|
||||
let fe = &foldenable
|
||||
set nofoldenable
|
||||
|
||||
let accounts = []
|
||||
call cursor(lnum, 0)
|
||||
while 1
|
||||
let lnum = search('^account\s', 'cW', lend)
|
||||
if !lnum || lnum > lend
|
||||
break
|
||||
endif
|
||||
|
||||
" remove comments at the end and "account" at the front
|
||||
let line = split(getline(lnum), '\s\+;')[0]
|
||||
let line = matchlist(line, 'account\s\+\(.\+\)')[1]
|
||||
|
||||
if len(line) > 1
|
||||
call add(accounts, line)
|
||||
endif
|
||||
|
||||
call cursor(lnum+1,0)
|
||||
endw
|
||||
|
||||
" restore view / position
|
||||
let &foldenable = fe
|
||||
call winrestview(view)
|
||||
|
||||
return accounts
|
||||
endf
|
||||
|
||||
function! s:get_transaction_extents(lnum)
|
||||
if ! (indent(a:lnum) || getline(a:lnum) =~ '^[~=[:digit:]]')
|
||||
" only do something if lnum is in a transaction
|
||||
return [0, 0]
|
||||
endif
|
||||
|
||||
" safe view / position
|
||||
let view = winsaveview()
|
||||
let fe = &foldenable
|
||||
set nofoldenable
|
||||
|
||||
call cursor(a:lnum, 0)
|
||||
let head = search('^[~=[:digit:]]', 'bcnW')
|
||||
let tail = search('^[^;[:blank:]]\S\+', 'nW')
|
||||
let tail = tail > head ? tail - 1 : line('$')
|
||||
|
||||
" restore view / position
|
||||
let &foldenable = fe
|
||||
call winrestview(view)
|
||||
|
||||
return head ? [head, tail] : [0, 0]
|
||||
endf
|
||||
|
||||
function! ledger#find_in_tree(tree, levels)
|
||||
if empty(a:levels)
|
||||
return []
|
||||
endif
|
||||
let results = []
|
||||
let currentlvl = a:levels[0]
|
||||
let nextlvls = a:levels[1:]
|
||||
let branches = ledger#filter_items(keys(a:tree), currentlvl)
|
||||
for branch in branches
|
||||
let exact = empty(nextlvls)
|
||||
call add(results, [branch, exact])
|
||||
if ! empty(nextlvls)
|
||||
for [result, exact] in ledger#find_in_tree(a:tree[branch], nextlvls)
|
||||
call add(results, [branch.':'.result, exact])
|
||||
endfor
|
||||
endif
|
||||
endfor
|
||||
return results
|
||||
endf
|
||||
|
||||
function! ledger#filter_items(list, keyword)
|
||||
" return only those items that start with a specified keyword
|
||||
return filter(copy(a:list), 'v:val =~ ''^\V'.substitute(a:keyword, '\\', '\\\\', 'g').'''')
|
||||
endf
|
||||
|
||||
function! s:findall(text, rx)
|
||||
" returns all the matches in a string,
|
||||
" there will be overlapping matches according to :help match()
|
||||
let matches = []
|
||||
|
||||
while 1
|
||||
let m = matchstr(a:text, a:rx, 0, len(matches)+1)
|
||||
if empty(m)
|
||||
break
|
||||
endif
|
||||
|
||||
call add(matches, m)
|
||||
endw
|
||||
|
||||
return matches
|
||||
endf
|
||||
|
||||
" Move the cursor to the specified column, filling the line with spaces if necessary.
|
||||
" Ensure that at least min_spaces are added, and go to the end of the line if
|
||||
" the line is already too long
|
||||
function! s:goto_col(pos, min_spaces)
|
||||
exec "normal!" "$"
|
||||
let diff = max([a:min_spaces, a:pos - virtcol('.')])
|
||||
if diff > 0 | exec "normal!" diff . "a " | endif
|
||||
endf
|
||||
|
||||
" Return character position of decimal separator (multibyte safe)
|
||||
function! s:decimalpos(expr)
|
||||
let pos = match(a:expr, '\V' . g:ledger_decimal_sep)
|
||||
if pos > 0
|
||||
let pos = strchars(a:expr[:pos]) - 1
|
||||
endif
|
||||
return pos
|
||||
endf
|
||||
|
||||
" Align the amount expression after an account name at the decimal point.
|
||||
"
|
||||
" This function moves the amount expression of a posting so that the decimal
|
||||
" separator is aligned at the column specified by g:ledger_align_at.
|
||||
"
|
||||
" For example, after selecting:
|
||||
"
|
||||
" 2015/05/09 Some Payee
|
||||
" Expenses:Other $120,23 ; Tags here
|
||||
" Expenses:Something $-4,99
|
||||
" Expenses:More ($12,34 + $16,32)
|
||||
"
|
||||
" :'<,'>call ledger#align_commodity() produces:
|
||||
"
|
||||
" 2015/05/09 Some Payee
|
||||
" Expenses:Other $120,23 ; Tags here
|
||||
" Expenses:Something $-4,99
|
||||
" Expenses:More ($12,34 + $16,32)
|
||||
"
|
||||
function! ledger#align_commodity()
|
||||
" Extract the part of the line after the account name (excluding spaces):
|
||||
let rhs = matchstr(getline('.'), '\m^\s\+[^;[:space:]].\{-}\(\t\| \)\s*\zs.*$')
|
||||
if rhs != ''
|
||||
" Remove everything after the account name (including spaces):
|
||||
.s/\m^\s\+[^[:space:]].\{-}\zs\(\t\| \).*$//
|
||||
let pos = -1
|
||||
if g:ledger_decimal_sep != ''
|
||||
" Find the position of the first decimal separator:
|
||||
let pos = s:decimalpos(rhs)
|
||||
endif
|
||||
if pos < 0
|
||||
" Find the position after the first digits
|
||||
let pos = matchend(rhs, '\m\d[^[:space:]]*')
|
||||
endif
|
||||
" Go to the column that allows us to align the decimal separator at g:ledger_align_at:
|
||||
if pos > 0
|
||||
call s:goto_col(g:ledger_align_at - pos - 1, 2)
|
||||
else
|
||||
call s:goto_col(g:ledger_align_at - strdisplaywidth(rhs) - 2, 2)
|
||||
endif " Append the part of the line that was previously removed:
|
||||
exe 'normal! a' . rhs
|
||||
endif
|
||||
endf!
|
||||
|
||||
" Align the amount under the cursor and append/prepend the default currency.
|
||||
function! ledger#align_amount_at_cursor()
|
||||
" Select and cut text:
|
||||
normal! viWd
|
||||
" Find the position of the decimal separator
|
||||
let pos = s:decimalpos(@") " Returns zero when the separator is the empty string
|
||||
if pos <= 0
|
||||
let pos = len(@")
|
||||
endif
|
||||
" Paste text at the correct column and append/prepend default commodity:
|
||||
if g:ledger_commodity_before
|
||||
call s:goto_col(g:ledger_align_at - pos - len(g:ledger_default_commodity) - len(g:ledger_commodity_sep) - 1, 2)
|
||||
exe 'normal! a' . g:ledger_default_commodity . g:ledger_commodity_sep
|
||||
normal! p
|
||||
else
|
||||
call s:goto_col(g:ledger_align_at - pos - 1, 2)
|
||||
exe 'normal! pa' . g:ledger_commodity_sep . g:ledger_default_commodity
|
||||
endif
|
||||
endf!
|
||||
|
||||
" Report generation {{{1
|
||||
|
||||
" Helper functions and variables {{{2
|
||||
" Position of report windows
|
||||
let s:winpos_map = {
|
||||
\ "T": "to new", "t": "abo new", "B": "bo new", "b": "bel new",
|
||||
\ "L": "to vnew", "l": "abo vnew", "R": "bo vnew", "r": "bel vnew"
|
||||
\ }
|
||||
|
||||
function! s:error_message(msg)
|
||||
redraw " See h:echo-redraw
|
||||
echohl ErrorMsg
|
||||
echo "\r"
|
||||
echomsg a:msg
|
||||
echohl NONE
|
||||
endf
|
||||
|
||||
function! s:warning_message(msg)
|
||||
redraw " See h:echo-redraw
|
||||
echohl WarningMsg
|
||||
echo "\r"
|
||||
echomsg a:msg
|
||||
echohl NONE
|
||||
endf
|
||||
|
||||
" Open the quickfix/location window when it is not empty,
|
||||
" closes it if it is empty.
|
||||
"
|
||||
" Optional parameters:
|
||||
" a:1 Quickfix window title.
|
||||
" a:2 Message to show when the window is empty.
|
||||
"
|
||||
" Returns 0 if the quickfix window is empty, 1 otherwise.
|
||||
function! s:quickfix_toggle(...)
|
||||
if g:ledger_use_location_list
|
||||
let l:list = 'l'
|
||||
let l:open = (len(getloclist(winnr())) > 0)
|
||||
else
|
||||
let l:list = 'c'
|
||||
let l:open = (len(getqflist()) > 0)
|
||||
endif
|
||||
|
||||
if l:open
|
||||
execute (g:ledger_qf_vertical ? 'vert' : 'botright') l:list.'open' g:ledger_qf_size
|
||||
" Set local mappings to quit the quickfix window or lose focus.
|
||||
nnoremap <silent> <buffer> <tab> <c-w><c-w>
|
||||
execute 'nnoremap <silent> <buffer> q :' l:list.'close<CR>'
|
||||
" Note that the following settings do not persist (e.g., when you close and re-open the quickfix window).
|
||||
" See: https://superuser.com/questions/356912/how-do-i-change-the-quickix-title-status-bar-in-vim
|
||||
if g:ledger_qf_hide_file
|
||||
setl conceallevel=2
|
||||
setl concealcursor=nc
|
||||
syntax match qfFile /^[^|]*/ transparent conceal
|
||||
endif
|
||||
if a:0 > 0
|
||||
let w:quickfix_title = a:1
|
||||
endif
|
||||
return 1
|
||||
endif
|
||||
|
||||
execute l:list.'close'
|
||||
call s:warning_message((a:0 > 1) ? a:2 : 'No results')
|
||||
return 0
|
||||
endf
|
||||
|
||||
" Populate a quickfix/location window with data. The argument must be a String
|
||||
" or a List.
|
||||
function! s:quickfix_populate(data)
|
||||
" Note that cexpr/lexpr always uses the global value of errorformat
|
||||
let l:efm = &errorformat " Save global errorformat
|
||||
set errorformat=%EWhile\ parsing\ file\ \"%f\"\\,\ line\ %l:,%ZError:\ %m,%-C%.%#
|
||||
set errorformat+=%tarning:\ \"%f\"\\,\ line\ %l:\ %m
|
||||
" Format to parse command-line errors:
|
||||
set errorformat+=Error:\ %m
|
||||
" Format to parse reports:
|
||||
set errorformat+=%f:%l\ %m
|
||||
set errorformat+=%-G%.%#
|
||||
execute (g:ledger_use_location_list ? 'l' : 'c').'getexpr' 'a:data'
|
||||
let &errorformat = l:efm " Restore global errorformat
|
||||
return
|
||||
endf
|
||||
|
||||
" Build a ledger command to process the given file.
|
||||
function! s:ledger_cmd(file, args)
|
||||
return join([g:ledger_bin, g:ledger_extra_options, '-f', shellescape(expand(a:file)), a:args])
|
||||
endf
|
||||
" }}}
|
||||
|
||||
function! ledger#autocomplete_and_align()
|
||||
if pumvisible()
|
||||
return "\<c-n>"
|
||||
endif
|
||||
" Align an amount only if there is a digit immediately before the cursor and
|
||||
" such digit is preceded by at least one space (the latter condition is
|
||||
" necessary to avoid situations where a date starting at the first column is
|
||||
" confused with a commodity to be aligned).
|
||||
if match(getline('.'), '\s.*\d\%'.col('.').'c') > -1
|
||||
norm h
|
||||
call ledger#align_amount_at_cursor()
|
||||
return "\<c-o>A"
|
||||
endif
|
||||
return "\<c-x>\<c-o>"
|
||||
endf
|
||||
|
||||
" Use current line as input to ledger entry and replace with output. If there
|
||||
" are errors, they are echoed instead.
|
||||
func! ledger#entry()
|
||||
let l:output = systemlist(s:ledger_cmd(g:ledger_main, join(["entry", getline('.')])))
|
||||
" Filter out warnings
|
||||
let l:output = filter(l:output, "v:val !~? '^Warning: '")
|
||||
" Errors may occur
|
||||
if v:shell_error
|
||||
echomsg join(l:output)
|
||||
return
|
||||
endif
|
||||
" Append output so we insert instead of overwrite, then delete line
|
||||
call append('.', l:output)
|
||||
normal! "_dd
|
||||
endfunc
|
||||
|
||||
" Run an arbitrary ledger command and show the output in a new buffer. If
|
||||
" there are errors, no new buffer is opened: the errors are displayed in a
|
||||
" quickfix window instead.
|
||||
"
|
||||
" Parameters:
|
||||
" file The file to be processed.
|
||||
" args A string of Ledger command-line arguments.
|
||||
"
|
||||
" Returns:
|
||||
" Ledger's output as a String.
|
||||
function! ledger#report(file, args)
|
||||
let l:output = systemlist(s:ledger_cmd(a:file, a:args))
|
||||
if v:shell_error " If there are errors, show them in a quickfix/location list.
|
||||
call s:quickfix_populate(l:output)
|
||||
call s:quickfix_toggle('Errors', 'Unable to parse errors')
|
||||
endif
|
||||
return l:output
|
||||
endf
|
||||
|
||||
" Open the output of a Ledger's command in a new buffer.
|
||||
"
|
||||
" Parameters:
|
||||
" report A String containing the output of a Ledger's command.
|
||||
"
|
||||
" Returns:
|
||||
" 1 if a new buffer is created; 0 otherwise.
|
||||
function! ledger#output(report)
|
||||
if empty(a:report)
|
||||
call s:warning_message('No results')
|
||||
return 0
|
||||
endif
|
||||
" Open a new buffer to show Ledger's output.
|
||||
execute get(s:winpos_map, g:ledger_winpos, "bo new")
|
||||
setlocal buftype=nofile bufhidden=wipe modifiable nobuflisted noswapfile nowrap
|
||||
call append(0, a:report)
|
||||
setlocal nomodifiable
|
||||
" Set local mappings to quit window or lose focus.
|
||||
nnoremap <silent> <buffer> <tab> <c-w><c-p>
|
||||
nnoremap <silent> <buffer> q <c-w><c-p>@=winnr("#")<cr><c-w>c
|
||||
" Add some coloring to the report
|
||||
syntax match LedgerNumber /-\@1<!\d\+\([,.]\d\+\)*/
|
||||
syntax match LedgerNegativeNumber /-\d\+\([,.]\d\+\)*/
|
||||
syntax match LedgerImproperPerc /\d\d\d\+%/
|
||||
return 1
|
||||
endf
|
||||
|
||||
" Show an arbitrary register report in a quickfix list.
|
||||
"
|
||||
" Parameters:
|
||||
" file The file to be processed
|
||||
" args A string of Ledger command-line arguments.
|
||||
function! ledger#register(file, args)
|
||||
let l:cmd = s:ledger_cmd(a:file, join([
|
||||
\ "register",
|
||||
\ "--format='" . g:ledger_qf_register_format . "'",
|
||||
\ "--prepend-format='%(filename):%(beg_line) '",
|
||||
\ a:args
|
||||
\ ]))
|
||||
call s:quickfix_populate(systemlist(l:cmd))
|
||||
call s:quickfix_toggle('Register report')
|
||||
endf
|
||||
|
||||
" Reconcile the given account.
|
||||
" This function accepts a file path as a third optional argument.
|
||||
" The default is to use the value of g:ledger_main.
|
||||
"
|
||||
" Parameters:
|
||||
" file The file to be processed
|
||||
" account An account name (String)
|
||||
" target_amount The target amount (Float)
|
||||
function! ledger#reconcile(file, account, target_amount)
|
||||
let l:cmd = s:ledger_cmd(a:file, join([
|
||||
\ "register",
|
||||
\ "--uncleared",
|
||||
\ "--format='" . g:ledger_qf_reconcile_format . "'",
|
||||
\ "--prepend-format='%(filename):%(beg_line) %(pending ? \"P\" : \"U\") '",
|
||||
\ a:account
|
||||
\ ]))
|
||||
let l:file = expand(a:file) " Needed for #show_balance() later
|
||||
call s:quickfix_populate(systemlist(l:cmd))
|
||||
if s:quickfix_toggle("Reconcile " . a:account, "Nothing to reconcile")
|
||||
let g:ledger_target_amount = a:target_amount
|
||||
" Show updated account balance upon saving, as long as the quickfix window is open
|
||||
augroup reconcile
|
||||
autocmd!
|
||||
execute "autocmd BufWritePost *.ldg,*.ledger call ledger#show_balance('" . l:file . "','" . a:account . "')"
|
||||
autocmd BufWipeout <buffer> call <sid>finish_reconciling()
|
||||
augroup END
|
||||
" Add refresh shortcut
|
||||
execute "nnoremap <silent> <buffer> <c-l> :<c-u>call ledger#reconcile('"
|
||||
\ . l:file . "','" . a:account . "'," . string(a:target_amount) . ")<cr>"
|
||||
call ledger#show_balance(l:file, a:account)
|
||||
endif
|
||||
endf
|
||||
|
||||
function! s:finish_reconciling()
|
||||
unlet g:ledger_target_amount
|
||||
augroup reconcile
|
||||
autocmd!
|
||||
augroup END
|
||||
augroup! reconcile
|
||||
endf
|
||||
|
||||
" Show the pending/cleared balance of an account.
|
||||
" This function has an optional parameter:
|
||||
"
|
||||
" a:1 An account name
|
||||
"
|
||||
" If no account if given, the account in the current line is used.
|
||||
function! ledger#show_balance(file, ...)
|
||||
let l:account = a:0 > 0 && !empty(a:1) ? a:1 : matchstr(getline('.'), '\m\( \|\t\)\zs\S.\{-}\ze\( \|\t\|$\)')
|
||||
if empty(l:account)
|
||||
call s:error_message('No account found')
|
||||
return
|
||||
endif
|
||||
let l:cmd = s:ledger_cmd(a:file, join([
|
||||
\ "cleared",
|
||||
\ l:account,
|
||||
\ "--empty",
|
||||
\ "--collapse",
|
||||
\ "--format='%(scrub(get_at(display_total, 0)))|%(scrub(get_at(display_total, 1)))|%(quantity(scrub(get_at(display_total, 1))))'",
|
||||
\ (empty(g:ledger_default_commodity) ? '' : "-X " . shellescape(g:ledger_default_commodity))
|
||||
\ ]))
|
||||
let l:output = systemlist(l:cmd)
|
||||
" Errors may occur, for example, when the account has multiple commodities
|
||||
" and g:ledger_default_commodity is empty.
|
||||
if v:shell_error
|
||||
call s:quickfix_populate(l:output)
|
||||
call s:quickfix_toggle('Errors', 'Unable to parse errors')
|
||||
return
|
||||
endif
|
||||
let l:amounts = split(l:output[-1], '|')
|
||||
redraw " Necessary in some cases to overwrite previous messages. See :h echo-redraw
|
||||
if len(l:amounts) < 3
|
||||
call s:error_message("Could not determine balance. Did you use a valid account?")
|
||||
return
|
||||
endif
|
||||
echo g:ledger_pending_string
|
||||
echohl LedgerPending
|
||||
echon l:amounts[0]
|
||||
echohl NONE
|
||||
echon ' ' g:ledger_cleared_string
|
||||
echohl LedgerCleared
|
||||
echon l:amounts[1]
|
||||
echohl NONE
|
||||
if exists('g:ledger_target_amount')
|
||||
echon ' ' g:ledger_target_string
|
||||
echohl LedgerTarget
|
||||
echon printf('%.2f', (g:ledger_target_amount - str2float(l:amounts[2])))
|
||||
echohl NONE
|
||||
endif
|
||||
endf
|
||||
" }}}
|
29
.vim/pack/plugins/start/vim-ledger/compiler/ledger.vim
Normal file
29
.vim/pack/plugins/start/vim-ledger/compiler/ledger.vim
Normal file
@ -0,0 +1,29 @@
|
||||
" Vim Compiler File
|
||||
" Compiler: ledger
|
||||
" by Johann Klähn; Use according to the terms of the GPL>=2.
|
||||
" vim:ts=2:sw=2:sts=2:foldmethod=marker
|
||||
|
||||
if exists("current_compiler")
|
||||
finish
|
||||
endif
|
||||
let current_compiler = "ledger"
|
||||
|
||||
if exists(":CompilerSet") != 2
|
||||
command -nargs=* CompilerSet setlocal <args>
|
||||
endif
|
||||
|
||||
" default value will be set in ftplugin
|
||||
if ! exists("g:ledger_bin") || empty(g:ledger_bin) || ! executable(g:ledger_bin)
|
||||
finish
|
||||
endif
|
||||
|
||||
" Capture Ledger errors (%-C ignores all lines between "While parsing..." and "Error:..."):
|
||||
CompilerSet errorformat=%EWhile\ parsing\ file\ \"%f\"\\,\ line\ %l:,%ZError:\ %m,%-C%.%#
|
||||
" Capture Ledger warnings:
|
||||
CompilerSet errorformat+=%tarning:\ \"%f\"\\,\ line\ %l:\ %m
|
||||
" Skip all other lines:
|
||||
CompilerSet errorformat+=%-G%.%#
|
||||
|
||||
" Check file syntax
|
||||
exe 'CompilerSet makeprg='.substitute(g:ledger_bin, ' ', '\\ ', 'g').'\ '.substitute(g:ledger_extra_options, ' ', '\\ ', 'g').'\ source\ %:S'
|
||||
|
423
.vim/pack/plugins/start/vim-ledger/doc/ledger.txt
Normal file
423
.vim/pack/plugins/start/vim-ledger/doc/ledger.txt
Normal file
@ -0,0 +1,423 @@
|
||||
*ledger.txt* Plugin for the ledger filetype.
|
||||
|
||||
|
||||
*ledger* *ledger-plugin*
|
||||
|
||||
Contents:
|
||||
|
||||
Commands............|ledger-invoking|
|
||||
Source................|ledger-source|
|
||||
Usage..................|ledger-usage|
|
||||
Tips....................|ledger-tips|
|
||||
Reports..............|ledger-reports|
|
||||
Settings............|ledger-settings|
|
||||
Completion........|ledger-completion|
|
||||
License..............|ledger-license|
|
||||
|
||||
|
||||
==============================================================================
|
||||
USAGE *ledger-usage*
|
||||
|
||||
Copy each file to the corresponding directory in your ~/.vim directory or
|
||||
install using Pathogen.
|
||||
|
||||
You can also use a modeline like this in every ledger file:
|
||||
|
||||
vim:filetype=ledger
|
||||
|
||||
==============================================================================
|
||||
TIPS *ledger-tips*
|
||||
|
||||
Tips and useful commands
|
||||
|
||||
* vim-ledger can do syntax-sensitive folding when you set `foldmethod=syntax`
|
||||
in the |modeline| of your ledger file. This way transactions can shrink down
|
||||
to just one line.
|
||||
|
||||
* Try account-completion (as explained below). If you use YouCompleteMe, you
|
||||
should disable it for Ledger files. Put this in your .vimrc:
|
||||
|
||||
if exists('g:ycm_filetype_blacklist')
|
||||
call extend(g:ycm_filetype_blacklist, { 'ledger': 1 })
|
||||
endif
|
||||
|
||||
* You may use `:make` for syntax checking. It may be convenient to define a
|
||||
mapping for the following command:
|
||||
|
||||
:silent make | redraw! | cwindow
|
||||
|
||||
It is recommended to set the value of `g:ledger_extra_options` (see below)
|
||||
as follows:
|
||||
|
||||
let g:ledger_extra_options = '--pedantic --explicit --check-payees'
|
||||
|
||||
to catch most potential problems in your source file.
|
||||
|
||||
* Remap vim paragraph motion to move by transaction.
|
||||
|
||||
In vim, the "{" and "}" keystrokes move the cursor up and down by whole
|
||||
paragraphs. They can be redefined in ledger files to move by transaction
|
||||
instead. Add these lines to .vimrc:
|
||||
|
||||
au FileType ledger noremap { ?^\d<CR>
|
||||
au FileType ledger noremap } /^\d<CR>
|
||||
|
||||
The default definitions already work in ledger files that separate
|
||||
transactions with blank lines.
|
||||
|
||||
* `:call ledger#transaction_date_set('.'), "auxiliary")`
|
||||
|
||||
will set today's date as the auxiliary date of the current transaction. You
|
||||
can use also "primary" or "unshift" in place of "auxiliary". When you pass
|
||||
"unshift" the old primary date will be set as the auxiliary date and today's
|
||||
date will be set as the new primary date.
|
||||
To use a different date pass a date measured in seconds since 1st Jan 1970
|
||||
as the third argument.
|
||||
|
||||
* `:call ledger#transaction_state_set(line('.'), '*')`
|
||||
|
||||
sets the state of the current transaction to '*'. You can use this in custom
|
||||
mappings.
|
||||
|
||||
* `:call ledger#transaction_state_toggle(line('.'), ' *?!')`
|
||||
|
||||
will toggle through the provided transaction states. You can map this to
|
||||
double-clicking for example:
|
||||
|
||||
noremap <silent><buffer> <2-LeftMouse>\
|
||||
:call ledger#transaction_state_toggle(line('.'), ' *?!')<CR>
|
||||
|
||||
* `:LedgerAlign`
|
||||
|
||||
moves the amount expression of a posting so that the decimal separator is
|
||||
aligned at the column specified by g:ledger_align_at. If an amount has no
|
||||
decimal point, the imaginary decimal point to the right of the least
|
||||
significant digit will align. The command acts on a range, with the default
|
||||
being the current line.
|
||||
|
||||
The decimal separator can be set using `g:ledger_decimal_sep`. The default
|
||||
value of `g:ledger_decimal_sep` is `'.'`.
|
||||
|
||||
See below for the recommended mappings.
|
||||
|
||||
* `:call ledger#align_amount_at_cursor()`
|
||||
|
||||
aligns the amount under the cursor and append/prepend the default currency.
|
||||
The default currency can be set using `g:ledger_default_commodity`. Whether
|
||||
the commodity should be inserted before the amount or appended to it can be
|
||||
configured with the boolean flag `g:ledger_commodity_before` (the default
|
||||
value is 1). A separator between the commodity and the amount may be set
|
||||
using `g:ledger_commodity_sep`.
|
||||
|
||||
See below for the recommended mappings.
|
||||
|
||||
* `:call ledger#autocomplete_and_align()`
|
||||
|
||||
when the cursor is on a number or immediately after it, invokes
|
||||
`ledger#align_amount_at_cursor()` to align it and add the default currency;
|
||||
otherwise, performs autocompletion. If you define the following mappings in
|
||||
your `.vimrc` then you may perform both autocompletion and alignment using
|
||||
the <Tab> key:
|
||||
|
||||
au FileType ledger inoremap <silent> <Tab> \
|
||||
<C-r>=ledger#autocomplete_and_align()<CR>
|
||||
au FileType ledger vnoremap <silent> <Tab> :LedgerAlign<CR>
|
||||
|
||||
Alternatively, you may create a file `.vim/after/ftplugin/ledger.vim`
|
||||
containing the following definitions:
|
||||
|
||||
inoremap <silent> <buffer> <Tab> \
|
||||
<C-r>=ledger#autocomplete_and_align()<CR>
|
||||
vnoremap <silent> <buffer> <Tab> :LedgerAlign<CR>
|
||||
|
||||
Now, you may type `asset:check<Tab><Space>123.45<Tab>`, and have the
|
||||
account name autocompleted and `$123.45` properly aligned (assuming your
|
||||
default commodity is set to `'$'`). Or you may press <Tab> in Visual mode
|
||||
to align a number of transactions at once.
|
||||
|
||||
* `:call ledger#entry()`
|
||||
|
||||
enters a new transaction based on the text in the current line.
|
||||
The text in the current line is replaced by the new transaction.
|
||||
This is a front end to `ledger entry`.
|
||||
|
||||
==============================================================================
|
||||
REPORTS *ledger-reports*
|
||||
|
||||
* `:Ledger`
|
||||
|
||||
Executes an arbitrary Ledger command and sends the output to a new buffer.
|
||||
For example:
|
||||
|
||||
:Ledger bal ^assets ^liab
|
||||
|
||||
Errors are displayed in a quickfix window. The command offers account and
|
||||
payee autocompletion (by pressing <Tab>): every name starting with `@` is
|
||||
autocompleted as a payee; any other name is autocompleted as an account.
|
||||
|
||||
In a report buffer or in the quickfix window, you may press <Tab> to switch
|
||||
back to your source file, and you may press `q` to dismiss the current window.
|
||||
|
||||
There are three highlight groups that are used to color the report:
|
||||
|
||||
* `LedgerNumber`
|
||||
|
||||
This is used to color nonnegative numbers.
|
||||
|
||||
* `LedgerNegativeNumber`
|
||||
|
||||
This is used to color negative numbers.
|
||||
|
||||
* `LedgerImproperPerc`
|
||||
|
||||
This is used to color improper percentages.
|
||||
|
||||
* `:Balance`
|
||||
|
||||
Show the pending and cleared balance of a given account below the status
|
||||
line. For example:
|
||||
|
||||
:Balance checking:savings
|
||||
|
||||
The command offers payee and account autocompletion (see `:Ledger`). The
|
||||
account argument is optional: if no argument is given, the first account
|
||||
name found in the current line is used.
|
||||
|
||||
Two highlight groups can be used to customize the colors of the line:
|
||||
|
||||
* `LedgerCleared`
|
||||
|
||||
This is used to color the cleared balance.
|
||||
|
||||
* `LedgerPending`
|
||||
|
||||
This is used to color the pending balance.
|
||||
|
||||
* `:Register`
|
||||
|
||||
Opens an arbitrary register report in the quickfix window. For example:
|
||||
|
||||
:Register groceries -p 'this month'
|
||||
|
||||
The command offers account and payee autocompletion (see |:Ledger|). You
|
||||
may use the standard quickfix commands to jump from an entry in the register
|
||||
report to the corresponding location in the source file. If you use GUI Vim
|
||||
or if your terminal has support for the mouse (e.g., iTerm2, or even
|
||||
Terminal.app in OS X 10.11 or later), you may also double-click on a line
|
||||
number in the quickfix window to jump to the corresponding posting.
|
||||
|
||||
It is strongly recommended that you add mappings for common quickfix
|
||||
commands like `:cprev` and `:cnext`, or that you use T. Pope's Unimpaired
|
||||
plugin.
|
||||
|
||||
* :`Reconcile`
|
||||
|
||||
Reconcile an account. For example:
|
||||
|
||||
:Reconcile checking
|
||||
|
||||
After you press Enter, you will be asked to enter a target amount (use
|
||||
Vim's syntax for numbers, not your ledger's format). For example, for a
|
||||
checking account, the target amount may be the balance of your latest bank
|
||||
statement. The list of uncleared postings appears in the quickfix window.
|
||||
The current balance of the account, together with the difference between the
|
||||
target amount and the cleared balance, is shown at the bottom of the screen.
|
||||
You may use standard quickfix commands to navigate through the postings. You
|
||||
may use |ledger#transaction_state_set()| to update a transaction's state.
|
||||
Every time you save your file, the balance and the difference from the
|
||||
target amount are updated at the bottom of the screen. The goal, of course,
|
||||
is to get such difference to zero. You may press `<C-l>` to refresh the
|
||||
Reconcile buffer. To finish reconciling an account, simply close the
|
||||
quickfix window.
|
||||
|
||||
There is a highlight group to customize the color of the difference from
|
||||
target:
|
||||
|
||||
* `LedgerTarget`
|
||||
|
||||
This is used to color the difference between the target amount and the
|
||||
cleared balance.
|
||||
|
||||
==============================================================================
|
||||
SETTINGS *ledger-settings*
|
||||
|
||||
Configuration
|
||||
|
||||
Include the following let-statements somewhere in your `.vimrc` to modify the
|
||||
behaviour of the ledger filetype.
|
||||
|
||||
* Path to the `ledger` executable:
|
||||
|
||||
let g:ledger_bin = 'ledger'
|
||||
|
||||
* Additional default options for the `ledger` executable:
|
||||
|
||||
let g:ledger_extra_options = ''
|
||||
|
||||
* Number of columns that will be used to display the foldtext. Set this when
|
||||
you think that the amount is too far off to the right.
|
||||
|
||||
let g:ledger_maxwidth = 80
|
||||
|
||||
* String that will be used to fill the space between account name and amount in
|
||||
the foldtext. Set this to get some kind of lines or visual aid.
|
||||
|
||||
let g:ledger_fillstring = ' -'
|
||||
|
||||
* If you want the account completion to be sorted by level of detail/depth
|
||||
instead of alphabetical, include the following line:
|
||||
|
||||
let g:ledger_detailed_first = 1
|
||||
|
||||
* By default vim will fold ledger transactions, leaving surrounding blank lines
|
||||
unfolded. You can use 'g:ledger_fold_blanks' to hide blank lines following a
|
||||
transaction.
|
||||
|
||||
let g:ledger_fold_blanks = 0
|
||||
|
||||
A value of 0 will disable folding of blank lines, 1 will allow folding of a
|
||||
single blank line between transactions; any larger value will enable folding
|
||||
unconditionally.
|
||||
|
||||
Note that only lines containing no trailing spaces are considered for
|
||||
folding. You can take advantage of this to disable this feature on a
|
||||
case-by-case basis.
|
||||
|
||||
* Decimal separator:
|
||||
|
||||
let g:ledger_decimal_sep = '.'
|
||||
|
||||
* Specify at which column decimal separators should be aligned:
|
||||
|
||||
let g:ledger_align_at = 60
|
||||
|
||||
* Default commodity used by `ledger#align_amount_at_cursor()`:
|
||||
|
||||
let g:ledger_default_commodity = ''
|
||||
|
||||
* Flag that tells whether the commodity should be prepended or appended to the
|
||||
amount:
|
||||
|
||||
let g:ledger_commodity_before = 1
|
||||
|
||||
* String to be put between the commodity and the amount:
|
||||
|
||||
let g:ledger_commodity_sep = ''
|
||||
|
||||
* Flag that enable the spelling of the amount:
|
||||
|
||||
let g:ledger_commodity_spell = 1
|
||||
|
||||
* Format of transaction date:
|
||||
|
||||
let g:ledger_date_format = '%Y/%m/%d'
|
||||
|
||||
* The file to be used to generate reports:
|
||||
|
||||
let g:ledger_main = '%'
|
||||
|
||||
The default is to use the current file.
|
||||
|
||||
* Position of a report buffer:
|
||||
|
||||
let g:ledger_winpos = 'B'
|
||||
|
||||
Use `b` for bottom, `t` for top, `l` for left, `r` for right. Use uppercase letters
|
||||
if you want the window to always occupy the full width or height.
|
||||
|
||||
* Format of quickfix register reports (see |:Register|):
|
||||
|
||||
let g:ledger_qf_register_format = \
|
||||
'%(date) %-50(payee) %-30(account) %15(amount) %15(total)\n'
|
||||
|
||||
The format is specified using the standard Ledger syntax for --format.
|
||||
|
||||
* Format of the reconcile quickfix window (see |:Reconcile|):
|
||||
|
||||
let g:ledger_qf_reconcile_format = \
|
||||
'%(date) %-4(code) %-50(payee) %-30(account) %15(amount)\n'
|
||||
|
||||
The format is specified using the standard Ledger syntax for --format.
|
||||
|
||||
* Flag that tells whether a location list or a quickfix list should be used:
|
||||
|
||||
let g:ledger_use_location_list = 0
|
||||
|
||||
The default is to use the quickfix window. Set to 1 to use a location list.
|
||||
|
||||
* Position of the quickfix/location list:
|
||||
|
||||
let g:ledger_qf_vertical = 0
|
||||
|
||||
Set to 1 to open the quickfix window in a vertical split.
|
||||
|
||||
* Size of the quickfix window:
|
||||
|
||||
let g:ledger_qf_size = 10
|
||||
|
||||
This is the number of lines of a horizontal quickfix window, or the number
|
||||
of columns of a vertical quickfix window.
|
||||
|
||||
* Flag to show or hide filenames in the quickfix window:
|
||||
|
||||
let g:ledger_qf_hide_file = 1
|
||||
|
||||
Filenames in the quickfix window are hidden by default. Set this to 1 is
|
||||
you want filenames to be visible.
|
||||
|
||||
* Text of the output of the |:Balance| command:
|
||||
|
||||
let g:ledger_cleared_string = 'Cleared: '
|
||||
let g:ledger_pending_string = 'Cleared or pending: '
|
||||
let g:ledger_target_string = 'Difference from target: '
|
||||
|
||||
==============================================================================
|
||||
COMPLETION *ledger-completion*
|
||||
|
||||
Omni completion is currently implemented for account names only.
|
||||
|
||||
### Accounts
|
||||
|
||||
Account names are matched by the start of every sub-level. When you
|
||||
insert an account name like this:
|
||||
|
||||
Asse<C-X><C-O>
|
||||
|
||||
You will get a list of top-level accounts that start like this.
|
||||
|
||||
Go ahead and try something like:
|
||||
|
||||
As:Ban:Che<C-X><C-O>
|
||||
|
||||
When you have an account like this, 'Assets:Bank:Checking' should show up.
|
||||
|
||||
When you want to complete on a virtual transaction, it's currently best
|
||||
to keep the cursor in front of the closing bracket. Of course you can
|
||||
insert the closing bracket after calling the completion, too.
|
||||
|
||||
==============================================================================
|
||||
LICENSE *ledger-license*
|
||||
|
||||
https://github.com/ledger/vim-ledger
|
||||
|
||||
Copyright 2019 Caleb Maclennan
|
||||
Copyright 2009–2017 Johann Klähn
|
||||
Copyright 2009 Stefan Karrmann
|
||||
Copyright 2005 Wolfgang Oertl
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation, either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
vim:ts=8 sw=8 noexpandtab tw=78 ft=help:
|
||||
|
1
.vim/pack/plugins/start/vim-ledger/ftdetect/ledger.vim
Normal file
1
.vim/pack/plugins/start/vim-ledger/ftdetect/ledger.vim
Normal file
@ -0,0 +1 @@
|
||||
autocmd BufNewFile,BufRead *.ldg,*.ledger,*.journal setlocal filetype=ledger
|
449
.vim/pack/plugins/start/vim-ledger/ftplugin/ledger.vim
Normal file
449
.vim/pack/plugins/start/vim-ledger/ftplugin/ledger.vim
Normal file
@ -0,0 +1,449 @@
|
||||
" Vim filetype plugin file
|
||||
" filetype: ledger
|
||||
" by Johann Klähn; Use according to the terms of the GPL>=2.
|
||||
" vim:ts=2:sw=2:sts=2:foldmethod=marker
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
endif
|
||||
|
||||
let b:did_ftplugin = 1
|
||||
|
||||
let b:undo_ftplugin = "setlocal ".
|
||||
\ "foldtext< ".
|
||||
\ "include< comments< commentstring< omnifunc< formatprg<"
|
||||
|
||||
if !exists('current_compiler')
|
||||
compiler ledger
|
||||
endif
|
||||
|
||||
setl foldtext=LedgerFoldText()
|
||||
setl include=^!\\?include
|
||||
setl comments=b:;
|
||||
setl commentstring=;%s
|
||||
setl omnifunc=LedgerComplete
|
||||
|
||||
" set location of ledger binary for checking and auto-formatting
|
||||
if ! exists("g:ledger_bin") || empty(g:ledger_bin) || ! executable(g:ledger_bin)
|
||||
if executable('ledger')
|
||||
let g:ledger_bin = 'ledger'
|
||||
else
|
||||
unlet! g:ledger_bin
|
||||
echohl WarningMsg
|
||||
echomsg "ledger command not found. Set g:ledger_bin or extend $PATH ".
|
||||
\ "to enable error checking and auto-formatting."
|
||||
echohl None
|
||||
endif
|
||||
endif
|
||||
|
||||
if exists("g:ledger_bin")
|
||||
exe 'setl formatprg='.substitute(g:ledger_bin, ' ', '\\ ', 'g').'\ -f\ -\ print'
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_extra_options')
|
||||
let g:ledger_extra_options = ''
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_date_format')
|
||||
let g:ledger_date_format = '%Y/%m/%d'
|
||||
endif
|
||||
|
||||
" You can set a maximal number of columns the fold text (excluding amount)
|
||||
" will use by overriding g:ledger_maxwidth in your .vimrc.
|
||||
" When maxwidth is zero, the amount will be displayed at the far right side
|
||||
" of the screen.
|
||||
if !exists('g:ledger_maxwidth')
|
||||
let g:ledger_maxwidth = 0
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_fillstring')
|
||||
let g:ledger_fillstring = ' '
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_decimal_sep')
|
||||
let g:ledger_decimal_sep = '.'
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_align_at')
|
||||
let g:ledger_align_at = 60
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_default_commodity')
|
||||
let g:ledger_default_commodity = ''
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_commodity_before')
|
||||
let g:ledger_commodity_before = 1
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_commodity_sep')
|
||||
let g:ledger_commodity_sep = ''
|
||||
endif
|
||||
|
||||
" If enabled this will list the most detailed matches at the top {{{
|
||||
" of the completion list.
|
||||
" For example when you have some accounts like this:
|
||||
" A:Ba:Bu
|
||||
" A:Bu:Bu
|
||||
" and you complete on A:B:B normal behaviour may be the following
|
||||
" A:B:B
|
||||
" A:Bu:Bu
|
||||
" A:Bu
|
||||
" A:Ba:Bu
|
||||
" A:Ba
|
||||
" A
|
||||
" with this option turned on it will be
|
||||
" A:B:B
|
||||
" A:Bu:Bu
|
||||
" A:Ba:Bu
|
||||
" A:Bu
|
||||
" A:Ba
|
||||
" A
|
||||
" }}}
|
||||
if !exists('g:ledger_detailed_first')
|
||||
let g:ledger_detailed_first = 1
|
||||
endif
|
||||
|
||||
" only display exact matches (no parent accounts etc.)
|
||||
if !exists('g:ledger_exact_only')
|
||||
let g:ledger_exact_only = 0
|
||||
endif
|
||||
|
||||
" display original text / account name as completion
|
||||
if !exists('g:ledger_include_original')
|
||||
let g:ledger_include_original = 0
|
||||
endif
|
||||
|
||||
" Settings for Ledger reports {{{
|
||||
if !exists('g:ledger_main')
|
||||
let g:ledger_main = '%'
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_winpos')
|
||||
let g:ledger_winpos = 'B' " Window position (see s:winpos_map)
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_use_location_list')
|
||||
let g:ledger_use_location_list = 0 " Use quickfix list by default
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_cleared_string')
|
||||
let g:ledger_cleared_string = 'Cleared: '
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_pending_string')
|
||||
let g:ledger_pending_string = 'Cleared or pending: '
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_target_string')
|
||||
let g:ledger_target_string = 'Difference from target: '
|
||||
endif
|
||||
" }}}
|
||||
|
||||
" Settings for the quickfix window {{{
|
||||
if !exists('g:ledger_qf_register_format')
|
||||
let g:ledger_qf_register_format = '%(date) %-50(payee) %-30(account) %15(amount) %15(total)\n'
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_qf_reconcile_format')
|
||||
let g:ledger_qf_reconcile_format = '%(date) %-4(code) %-50(payee) %-30(account) %15(amount)\n'
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_qf_size')
|
||||
let g:ledger_qf_size = 10 " Size of the quickfix window
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_qf_vertical')
|
||||
let g:ledger_qf_vertical = 0
|
||||
endif
|
||||
|
||||
if !exists('g:ledger_qf_hide_file')
|
||||
let g:ledger_qf_hide_file = 1
|
||||
endif
|
||||
" }}}
|
||||
|
||||
" Highlight groups for Ledger reports {{{
|
||||
hi link LedgerNumber Number
|
||||
hi link LedgerNegativeNumber Special
|
||||
hi link LedgerCleared Constant
|
||||
hi link LedgerPending Todo
|
||||
hi link LedgerTarget Statement
|
||||
hi link LedgerImproperPerc Special
|
||||
" }}}
|
||||
|
||||
let s:rx_amount = '\('.
|
||||
\ '\%([0-9]\+\)'.
|
||||
\ '\%([,.][0-9]\+\)*'.
|
||||
\ '\|'.
|
||||
\ '[,.][0-9]\+'.
|
||||
\ '\)'.
|
||||
\ '\s*\%([[:alpha:]¢$€£]\+\s*\)\?'.
|
||||
\ '\%(\s*;.*\)\?$'
|
||||
|
||||
function! LedgerFoldText() "{{{1
|
||||
" find amount
|
||||
let amount = ""
|
||||
let lnum = v:foldstart + 1
|
||||
while lnum <= v:foldend
|
||||
let line = getline(lnum)
|
||||
|
||||
" Skip metadata/leading comment
|
||||
if line !~ '^\%(\s\+;\|\d\)'
|
||||
" No comment, look for amount...
|
||||
let groups = matchlist(line, s:rx_amount)
|
||||
if ! empty(groups)
|
||||
let amount = groups[1]
|
||||
break
|
||||
endif
|
||||
endif
|
||||
let lnum += 1
|
||||
endwhile
|
||||
|
||||
let fmt = '%s %s '
|
||||
" strip whitespace at beginning and end of line
|
||||
let foldtext = substitute(getline(v:foldstart),
|
||||
\ '\(^\s\+\|\s\+$\)', '', 'g')
|
||||
|
||||
" number of columns foldtext can use
|
||||
let columns = s:get_columns()
|
||||
if g:ledger_maxwidth
|
||||
let columns = min([columns, g:ledger_maxwidth])
|
||||
endif
|
||||
let columns -= s:multibyte_strlen(printf(fmt, '', amount))
|
||||
|
||||
" add spaces so the text is always long enough when we strip it
|
||||
" to a certain width (fake table)
|
||||
if strlen(g:ledger_fillstring)
|
||||
" add extra spaces so fillstring aligns
|
||||
let filen = s:multibyte_strlen(g:ledger_fillstring)
|
||||
let folen = s:multibyte_strlen(foldtext)
|
||||
let foldtext .= repeat(' ', filen - (folen%filen))
|
||||
|
||||
let foldtext .= repeat(g:ledger_fillstring,
|
||||
\ s:get_columns()/filen)
|
||||
else
|
||||
let foldtext .= repeat(' ', s:get_columns())
|
||||
endif
|
||||
|
||||
" we don't use slices[:5], because that messes up multibyte characters
|
||||
let foldtext = substitute(foldtext, '.\{'.columns.'}\zs.*$', '', '')
|
||||
|
||||
return printf(fmt, foldtext, amount)
|
||||
endfunction "}}}
|
||||
|
||||
function! LedgerComplete(findstart, base) "{{{1
|
||||
if a:findstart
|
||||
let lnum = line('.')
|
||||
let line = getline('.')
|
||||
let b:compl_context = ''
|
||||
if line =~ '^\s\+[^[:blank:];]' "{{{2 (account)
|
||||
" only allow completion when in or at end of account name
|
||||
if matchend(line, '^\s\+\%(\S \S\|\S\)\+') >= col('.') - 1
|
||||
" the start of the first non-blank character
|
||||
" (excluding virtual-transaction and 'cleared' marks)
|
||||
" is the beginning of the account name
|
||||
let b:compl_context = 'account'
|
||||
return matchend(line, '^\s\+[*!]\?\s*[\[(]\?')
|
||||
endif
|
||||
elseif line =~ '^\d' "{{{2 (description)
|
||||
let pre = matchend(line, '^\d\S\+\%(([^)]*)\|[*?!]\|\s\)\+')
|
||||
if pre < col('.') - 1
|
||||
let b:compl_context = 'description'
|
||||
return pre
|
||||
endif
|
||||
elseif line =~ '^$' "{{{2 (new line)
|
||||
let b:compl_context = 'new'
|
||||
endif "}}}
|
||||
return -1
|
||||
else
|
||||
if ! exists('b:compl_cache')
|
||||
let b:compl_cache = s:collect_completion_data()
|
||||
let b:compl_cache['#'] = changenr()
|
||||
endif
|
||||
let update_cache = 0
|
||||
|
||||
let results = []
|
||||
if b:compl_context == 'account' "{{{2 (account)
|
||||
let hierarchy = split(a:base, ':')
|
||||
if a:base =~ ':$'
|
||||
call add(hierarchy, '')
|
||||
endif
|
||||
|
||||
let results = ledger#find_in_tree(b:compl_cache.accounts, hierarchy)
|
||||
let exacts = filter(copy(results), 'v:val[1]')
|
||||
|
||||
if len(exacts) < 1
|
||||
" update cache if we have no exact matches
|
||||
let update_cache = 1
|
||||
endif
|
||||
|
||||
if g:ledger_exact_only
|
||||
let results = exacts
|
||||
endif
|
||||
|
||||
call map(results, 'v:val[0]')
|
||||
|
||||
if g:ledger_detailed_first
|
||||
let results = reverse(sort(results, 's:sort_accounts_by_depth'))
|
||||
else
|
||||
let results = sort(results)
|
||||
endif
|
||||
elseif b:compl_context == 'description' "{{{2 (description)
|
||||
let results = ledger#filter_items(b:compl_cache.descriptions, a:base)
|
||||
|
||||
if len(results) < 1
|
||||
let update_cache = 1
|
||||
endif
|
||||
elseif b:compl_context == 'new' "{{{2 (new line)
|
||||
return [strftime(g:ledger_date_format)]
|
||||
endif "}}}
|
||||
|
||||
|
||||
if g:ledger_include_original
|
||||
call insert(results, a:base)
|
||||
endif
|
||||
|
||||
" no completion (apart from a:base) found. update cache if file has changed
|
||||
if update_cache && b:compl_cache['#'] != changenr()
|
||||
unlet b:compl_cache
|
||||
return LedgerComplete(a:findstart, a:base)
|
||||
else
|
||||
unlet! b:compl_context
|
||||
return results
|
||||
endif
|
||||
endif
|
||||
endf "}}}
|
||||
|
||||
" Deprecated functions {{{1
|
||||
let s:deprecated = {
|
||||
\ 'LedgerToggleTransactionState': 'ledger#transaction_state_toggle',
|
||||
\ 'LedgerSetTransactionState': 'ledger#transaction_state_set',
|
||||
\ 'LedgerSetDate': 'ledger#transaction_date_set'
|
||||
\ }
|
||||
|
||||
for [s:old, s:new] in items(s:deprecated)
|
||||
let s:fun = "function! {s:old}(...)\nechohl WarningMsg\necho '" . s:old .
|
||||
\ " is deprecated. Use ".s:new." instead!'\nechohl None\n" .
|
||||
\ "call call('" . s:new . "', a:000)\nendf"
|
||||
exe s:fun
|
||||
endfor
|
||||
unlet s:old s:new s:fun
|
||||
" }}}1
|
||||
|
||||
function! s:collect_completion_data() "{{{1
|
||||
let transactions = ledger#transactions()
|
||||
let cache = {'descriptions': [], 'tags': {}, 'accounts': {}}
|
||||
let accounts = ledger#declared_accounts()
|
||||
for xact in transactions
|
||||
" collect descriptions
|
||||
if has_key(xact, 'description') && index(cache.descriptions, xact['description']) < 0
|
||||
call add(cache.descriptions, xact['description'])
|
||||
endif
|
||||
let [t, postings] = xact.parse_body()
|
||||
let tagdicts = [t]
|
||||
|
||||
" collect account names
|
||||
for posting in postings
|
||||
if has_key(posting, 'tags')
|
||||
call add(tagdicts, posting.tags)
|
||||
endif
|
||||
" remove virtual-transaction-marks
|
||||
let name = substitute(posting.account, '\%(^\s*[\[(]\?\|[\])]\?\s*$\)', '', 'g')
|
||||
if index(accounts, name) < 0
|
||||
call add(accounts, name)
|
||||
endif
|
||||
endfor
|
||||
|
||||
" collect tags
|
||||
for tags in tagdicts | for [tag, val] in items(tags)
|
||||
let values = get(cache.tags, tag, [])
|
||||
if index(values, val) < 0
|
||||
call add(values, val)
|
||||
endif
|
||||
let cache.tags[tag] = values
|
||||
endfor | endfor
|
||||
endfor
|
||||
|
||||
for account in accounts
|
||||
let last = cache.accounts
|
||||
for part in split(account, ':')
|
||||
let last[part] = get(last, part, {})
|
||||
let last = last[part]
|
||||
endfor
|
||||
endfor
|
||||
|
||||
return cache
|
||||
endf "}}}
|
||||
|
||||
" Helper functions {{{1
|
||||
|
||||
" return length of string with fix for multibyte characters
|
||||
function! s:multibyte_strlen(text) "{{{2
|
||||
return strlen(substitute(a:text, ".", "x", "g"))
|
||||
endfunction "}}}
|
||||
|
||||
" get # of visible/usable columns in current window
|
||||
function! s:get_columns() " {{{2
|
||||
" As long as vim doesn't provide a command natively,
|
||||
" we have to compute the available columns.
|
||||
" see :help todo.txt -> /Add argument to winwidth()/
|
||||
|
||||
let columns = (winwidth(0) == 0 ? 80 : winwidth(0)) - &foldcolumn
|
||||
if &number
|
||||
" line('w$') is the line number of the last line
|
||||
let columns -= max([len(line('w$'))+1, &numberwidth])
|
||||
endif
|
||||
|
||||
" are there any signs/is the sign column displayed?
|
||||
redir => signs
|
||||
silent execute 'sign place buffer='.string(bufnr("%"))
|
||||
redir END
|
||||
if signs =~# 'id='
|
||||
let columns -= 2
|
||||
endif
|
||||
|
||||
return columns
|
||||
endf "}}}
|
||||
|
||||
function! s:sort_accounts_by_depth(name1, name2) "{{{2
|
||||
let depth1 = s:count_expression(a:name1, ':')
|
||||
let depth2 = s:count_expression(a:name2, ':')
|
||||
return depth1 == depth2 ? 0 : depth1 > depth2 ? 1 : -1
|
||||
endf "}}}
|
||||
|
||||
function! s:count_expression(text, expression) "{{{2
|
||||
return len(split(a:text, a:expression, 1))-1
|
||||
endf "}}}
|
||||
|
||||
function! s:autocomplete_account_or_payee(argLead, cmdLine, cursorPos) "{{{2
|
||||
return (a:argLead =~ '^@') ?
|
||||
\ map(filter(systemlist(g:ledger_bin . ' -f ' . shellescape(expand(g:ledger_main)) . ' payees'),
|
||||
\ "v:val =~? '" . strpart(a:argLead, 1) . "' && v:val !~? '^Warning: '"), '"@" . escape(v:val, " ")')
|
||||
\ :
|
||||
\ map(filter(systemlist(g:ledger_bin . ' -f ' . shellescape(expand(g:ledger_main)) . ' accounts'),
|
||||
\ "v:val =~? '" . a:argLead . "' && v:val !~? '^Warning: '"), 'escape(v:val, " ")')
|
||||
endf "}}}
|
||||
|
||||
function! s:reconcile(file, account) "{{{2
|
||||
" call inputsave()
|
||||
let l:amount = input('Target amount' . (empty(g:ledger_default_commodity) ? ': ' : ' (' . g:ledger_default_commodity . '): '))
|
||||
" call inputrestore()
|
||||
call ledger#reconcile(a:file, a:account, str2float(l:amount))
|
||||
endf "}}}
|
||||
|
||||
" Commands {{{1
|
||||
command! -buffer -nargs=? -complete=customlist,s:autocomplete_account_or_payee
|
||||
\ Balance call ledger#show_balance(g:ledger_main, <q-args>)
|
||||
|
||||
command! -buffer -nargs=+ -complete=customlist,s:autocomplete_account_or_payee
|
||||
\ Ledger call ledger#output(ledger#report(g:ledger_main, <q-args>))
|
||||
|
||||
command! -buffer -range LedgerAlign <line1>,<line2>call ledger#align_commodity()
|
||||
|
||||
command! -buffer -nargs=1 -complete=customlist,s:autocomplete_account_or_payee
|
||||
\ Reconcile call <sid>reconcile(g:ledger_main, <q-args>)
|
||||
|
||||
command! -buffer -complete=customlist,s:autocomplete_account_or_payee -nargs=*
|
||||
\ Register call ledger#register(g:ledger_main, <q-args>)
|
||||
" }}}
|
||||
|
46
.vim/pack/plugins/start/vim-ledger/indent/ledger.vim
Normal file
46
.vim/pack/plugins/start/vim-ledger/indent/ledger.vim
Normal file
@ -0,0 +1,46 @@
|
||||
" Vim filetype indent file
|
||||
" filetype: ledger
|
||||
" by Johann Klähn; Use according to the terms of the GPL>=2.
|
||||
" vim:ts=2:sw=2:sts=2:foldmethod=marker
|
||||
|
||||
if exists("b:did_indent")
|
||||
finish
|
||||
endif
|
||||
let b:did_indent = 1
|
||||
|
||||
setl autoindent
|
||||
setl indentexpr=GetLedgerIndent()
|
||||
|
||||
if exists("*GetLedgerIndent")
|
||||
finish
|
||||
endif
|
||||
|
||||
function GetLedgerIndent(...)
|
||||
" You can pass in a line number when calling this function manually.
|
||||
let lnum = a:0 > 0 ? a:1 : v:lnum
|
||||
" If this line is empty look at (the indentation of) the last line.
|
||||
" Note that inside of a transaction no blank lines are allowed.
|
||||
let line = getline(lnum)
|
||||
let prev = getline(lnum - 1)
|
||||
|
||||
if line =~ '^\s\+\S'
|
||||
" Lines that already are indented (→postings, sub-directives) keep their indentation.
|
||||
return &sw
|
||||
elseif line =~ '^\s*$'
|
||||
" Current line is empty, try to guess its type based on the previous line.
|
||||
if prev =~ '^\([[:digit:]~=]\|\s\+\S\)'
|
||||
" This is very likely a posting or a sub-directive.
|
||||
" While lines following the start of a transaction are automatically
|
||||
" indented you will have to indent the first line following a
|
||||
" pre-declaration manually. This makes it easier to type long lists of
|
||||
" 'account' pre-declarations without sub-directives, for example.
|
||||
return &sw
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
else
|
||||
" Everything else is not indented:
|
||||
" start of transactions, pre-declarations, apply/end-lines
|
||||
return 0
|
||||
endif
|
||||
endf
|
107
.vim/pack/plugins/start/vim-ledger/syntax/ledger.vim
Normal file
107
.vim/pack/plugins/start/vim-ledger/syntax/ledger.vim
Normal file
@ -0,0 +1,107 @@
|
||||
" Vim syntax file
|
||||
" filetype: ledger
|
||||
" by Johann Klähn; Use according to the terms of the GPL>=2.
|
||||
" by Stefan Karrmann; Use according to the terms of the GPL>=2.
|
||||
" by Wolfgang Oertl; Use according to the terms of the GPL>=2.
|
||||
" vim:ts=2:sw=2:sts=2:foldmethod=marker
|
||||
|
||||
if version < 600
|
||||
syntax clear
|
||||
elseif exists("b:current_sytax")
|
||||
finish
|
||||
endif
|
||||
|
||||
" Force old regex engine (:help two-engines)
|
||||
let s:oe = v:version < 704 ? '' : '\%#=1'
|
||||
let s:lb1 = v:version < 704 ? '\@<=' : '\@1<='
|
||||
|
||||
let s:fb = get(g:, 'ledger_fold_blanks', 0)
|
||||
let s:skip = s:fb > 0 ? '\|^\n' : ''
|
||||
if s:fb == 1
|
||||
let s:skip .= '\n\@!'
|
||||
endif
|
||||
|
||||
let s:ledgerAmount_contains = ''
|
||||
if get(g:, 'ledger_commodity_spell', 0) == 0
|
||||
let s:ledgerAmount_contains .= '@NoSpell'
|
||||
endif
|
||||
|
||||
" for debugging
|
||||
syntax clear
|
||||
|
||||
" DATE[=EDATE] [*|!] [(CODE)] DESC <-- first line of transaction
|
||||
" ACCOUNT AMOUNT [; NOTE] <-- posting
|
||||
|
||||
exe 'syn region ledgerTransaction start=/^[[:digit:]~=]/ '.
|
||||
\ 'skip=/^\s'. s:skip . '/ end=/^/ fold keepend transparent '.
|
||||
\ 'contains=ledgerTransactionDate,ledgerMetadata,ledgerPosting,ledgerTransactionExpression'
|
||||
syn match ledgerTransactionDate /^\d\S\+/ contained
|
||||
syn match ledgerTransactionExpression /^[=~]\s\+\zs.*/ contained
|
||||
syn match ledgerPosting /^\s\+[^[:blank:];][^;]*\ze\%($\|;\)/
|
||||
\ contained transparent contains=ledgerAccount,ledgerAmount,ledgerMetadata
|
||||
" every space in an account name shall be surrounded by two non-spaces
|
||||
" every account name ends with a tab, two spaces or the end of the line
|
||||
exe 'syn match ledgerAccount '.
|
||||
\ '/'.s:oe.'^\s\+\zs\%(\S'.s:lb1.' \S\|\S\)\+\ze\%( \|\t\|\s*$\)/ contained'
|
||||
exe 'syn match ledgerAmount '.
|
||||
\ '/'.s:oe.'\S'.s:lb1.'\%( \|\t\)\s*\zs\%([^;[:space:]]\|\s\+[^;[:space:]]\)\+/ contains='.s:ledgerAmount_contains.' contained'
|
||||
|
||||
syn region ledgerPreDeclaration start=/^\(account\|payee\|commodity\|tag\)/ skip=/^\s/ end=/^/
|
||||
\ keepend transparent
|
||||
\ contains=ledgerPreDeclarationType,ledgerPreDeclarationName,ledgerPreDeclarationDirective
|
||||
syn match ledgerPreDeclarationType /^\(account\|payee\|commodity\|tag\)/ contained
|
||||
syn match ledgerPreDeclarationName /^\S\+\s\+\zs.*/ contained
|
||||
syn match ledgerPreDeclarationDirective /^\s\+\zs\S\+/ contained
|
||||
|
||||
syn match ledgerDirective
|
||||
\ /^\%(alias\|assert\|bucket\|capture\|check\|define\|expr\|fixed\|include\|year\)\s/
|
||||
syn match ledgerOneCharDirective /^\%(P\|A\|Y\|N\|D\|C\)\s/
|
||||
|
||||
syn region ledgerBlockComment start=/^comment/ end=/^end comment/
|
||||
syn region ledgerBlockTest start=/^test/ end=/^end test/
|
||||
syn match ledgerComment /^[;|*#].*$/
|
||||
" comments at eol must be preceded by at least 2 spaces / 1 tab
|
||||
syn region ledgerMetadata start=/\%( \|\t\|^\s\+\);/ skip=/^\s\+;/ end=/^/
|
||||
\ keepend contained contains=ledgerTags,ledgerValueTag,ledgerTypedTag
|
||||
exe 'syn match ledgerTags '.
|
||||
\ '/'.s:oe.'\%(\%(;\s*\|^tag\s\+\)\)\@<='.
|
||||
\ ':[^:[:space:]][^:]*\%(::\?[^:[:space:]][^:]*\)*:\s*$/ '.
|
||||
\ 'contained contains=ledgerTag'
|
||||
syn match ledgerTag /:\zs[^:]\+\ze:/ contained
|
||||
exe 'syn match ledgerValueTag '.
|
||||
\ '/'.s:oe.'\%(\%(;\|^tag\)[^:]\+\)\@<=[^:]\+:\ze.\+$/ contained'
|
||||
exe 'syn match ledgerTypedTag '.
|
||||
\ '/'.s:oe.'\%(\%(;\|^tag\)[^:]\+\)\@<=[^:]\+::\ze.\+$/ contained'
|
||||
|
||||
syn region ledgerApply
|
||||
\ matchgroup=ledgerStartApply start=/^apply\>/
|
||||
\ matchgroup=ledgerEndApply end=/^end\s\+apply\>/
|
||||
\ contains=ledgerApplyHead,ledgerApply,ledgerTransaction,ledgerComment
|
||||
exe 'syn match ledgerApplyHead '.
|
||||
\ '/'.s:oe.'\%(^apply\s\+\)\@<=\S.*$/ contained'
|
||||
|
||||
highlight default link ledgerComment Comment
|
||||
highlight default link ledgerBlockComment Comment
|
||||
highlight default link ledgerBlockTest Comment
|
||||
highlight default link ledgerTransactionDate Constant
|
||||
highlight default link ledgerTransactionExpression Statement
|
||||
highlight default link ledgerMetadata Tag
|
||||
highlight default link ledgerTypedTag Keyword
|
||||
highlight default link ledgerValueTag Type
|
||||
highlight default link ledgerTag Type
|
||||
highlight default link ledgerStartApply Tag
|
||||
highlight default link ledgerEndApply Tag
|
||||
highlight default link ledgerApplyHead Type
|
||||
highlight default link ledgerAccount Identifier
|
||||
highlight default link ledgerAmount Number
|
||||
highlight default link ledgerPreDeclarationType Type
|
||||
highlight default link ledgerPreDeclarationName Identifier
|
||||
highlight default link ledgerPreDeclarationDirective Type
|
||||
highlight default link ledgerDirective Type
|
||||
highlight default link ledgerOneCharDirective Type
|
||||
|
||||
" syncinc is easy: search for the first transaction.
|
||||
syn sync clear
|
||||
syn sync match ledgerSync grouphere ledgerTransaction "^[[:digit:]~=]"
|
||||
|
||||
let b:current_syntax = "ledger"
|
Loading…
Reference in New Issue
Block a user