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