Class: RVGP::Pta
- Inherits:
-
Object
- Object
- RVGP::Pta
- Defined in:
- lib/rvgp/pta.rb,
lib/rvgp/pta/ledger.rb,
lib/rvgp/pta/hledger.rb
Overview
A base class, which offers functionality to plain text accounting adapters. At the moment, that means either ‘ledger’, or ‘hledger’. This class contains abstractions and code shared by the HLedger and Ledger classes.
In addition, this class contains the AvailabilityHelper, which can be included by any class, in order to offer shorthand access to this entire suite of functions.
Defined Under Namespace
Modules: AvailabilityHelper Classes: AssertionError, BalanceAccount, HLedger, Ledger, RegisterPosting, RegisterTransaction
Class Method Summary collapse
-
.hledger ⇒ RVGP::Pta::HLedger
Return a new instance of RVGP::Pta::HLedger.
-
.ledger ⇒ RVGP::Pta::Ledger
Return a new instance of RVGP::Pta::Ledger.
-
.pta ⇒ RVGP::Pta::Ledger, RVGP::Pta::HLedger
Depending on what’s installed and configured, a pta adapter is returned.
-
.pta_adapter=(driver) ⇒ void
Override the default adapter, used by Pta.pta.
Instance Method Summary collapse
-
#adapter_name ⇒ Symbol
The name of this adapter, either :ledger or :hledger.
-
#args_and_opts(*args) ⇒ Array<Object>
Given a splatted array, groups and returns arguments into an array of commands, and a hash of options.
-
#bin_path ⇒ String
The path to this adapter’s binary.
-
#command(*args) ⇒ String
Returns the output of arguments to a pta adapter.
-
#hledger? ⇒ TrueClass, FalseClass
Indicates whether or not this is a hledger pta adapter.
-
#ledger? ⇒ TrueClass, FalseClass
Indicates whether or not this is a ledger pta adapter.
-
#present? ⇒ TrueClass, FalseClass
Determines whether this adapter is found in the expected path, and is executable.
-
#stats(*args) ⇒ Hash<String, <String,Array<String>>>
Returns the output of the ‘stats’ command, parsed into key/value pairs.
Class Method Details
.hledger ⇒ RVGP::Pta::HLedger
Return a new instance of RVGP::Pta::HLedger
278 279 280 |
# File 'lib/rvgp/pta.rb', line 278 def hledger HLedger.new end |
.ledger ⇒ RVGP::Pta::Ledger
Return a new instance of RVGP::Pta::Ledger
272 273 274 |
# File 'lib/rvgp/pta.rb', line 272 def ledger Ledger.new end |
.pta ⇒ RVGP::Pta::Ledger, RVGP::Pta::HLedger
Depending on what’s installed and configured, a pta adapter is returned. The rules that govern what adapter is choosen, works like this:
-
If pta_adapter= has been set, then, this adapter will be returned.
-
If ledger is installed on the system, then ledger is returned
-
If hledger is installed on the system, then hledger is returned
If no pta adapters are available, an error is raised.
289 290 291 292 293 294 295 296 297 298 299 |
# File 'lib/rvgp/pta.rb', line 289 def pta @pta ||= if @pta_adapter send @pta_adapter elsif ledger.present? ledger elsif hledger.present? hledger else raise StandardError, 'No pta adapter specified, or detected, on system' end end |
.pta_adapter=(driver) ⇒ void
This method returns an undefined value.
Override the default adapter, used by pta. This can be set to one of: nil, :hledger, or :ledger.
305 306 307 308 |
# File 'lib/rvgp/pta.rb', line 305 def pta_adapter=(driver) @pta = nil @pta_adapter = driver.to_sym end |
Instance Method Details
#adapter_name ⇒ Symbol
The name of this adapter, either :ledger or :hledger
253 254 255 |
# File 'lib/rvgp/pta.rb', line 253 def adapter_name self.class.name.split(':').last.downcase.to_sym end |
#args_and_opts(*args) ⇒ Array<Object>
Given a splatted array, groups and returns arguments into an array of commands, and a hash of options. Options, are expected to be provided as a Hash, as the last element of the splat.
Most of the public methods in a Pta adapter, have largely-undefined arguments. This is because these methods mostly just pass their method arguments, straight to ledger and hledger for handling. Therefore, the ‘best’ place to find documentation on what arguments are supported, is the man page for hledger/ledger. The reason most of the methods exist (#balance, #register, etc), in a pta adapter, are to control how the output of the command is parsed.
Here are some examples of how arguments are sent straight to a pta command:
-
ledger.balance(‘Personal:Expenses’, file: ‘/tmp/test.journal’) becomes: /usr/bin/ledger xml Personal:Expenses –file /tmp/test.journal
-
pta.register(‘Income’, monthly: true) becomes: /usr/bin/ledger xml Income –sort date –monthly
That being said - there are some options that don’t get passed directly to the pta command. Most of these options are documented below.
This method also supports the following options, for additional handling:
-
:hledger_args - If this is a ledger adapter, this option is removed. Otherwise, the values of this Array will be returned in the first element of the return array.
-
:hledger_opts - If this is a ledger adapter, this option is removed. Otherwise, the values of this Hash will be merged with the second element of the return array.
-
:ledger_args - If this is an hledger adapter, this option is removed. Otherwise, the values of this Array will be returned in the first element of the return array.
-
:ledger_opts - If this is an hledger adapter, this option is removed. Otherwise, the values of this Hash will be merged with the second element of the return array.
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/rvgp/pta.rb', line 218 def args_and_opts(*args) opts = args.last.is_a?(Hash) ? args.pop : {} if ledger? opts.delete :hledger_opts opts.delete :hledger_args args += opts.delete(:ledger_args) if opts.key? :ledger_args opts.merge! opts.delete(:ledger_opts) if opts.key? :ledger_opts elsif hledger? opts.delete :ledger_opts opts.delete :ledger_args args += opts.delete(:hledger_args) if opts.key? :hledger_args opts.merge! opts.delete(:hledger_opts) if opts.key? :hledger_opts end [args, opts] end |
#bin_path ⇒ String
The path to this adapter’s binary
246 247 248 249 |
# File 'lib/rvgp/pta.rb', line 246 def bin_path # Maybe we should support more than just /usr/bin... self.class::BIN_PATH end |
#command(*args) ⇒ String
Returns the output of arguments to a pta adapter.
NOTE: If the RVGP_LOG_COMMANDS environment variable is set. (say, to “1”) this command will output diagnostic information to the console. This information will include the fully expanded command being run, alongside its execution time.
While args and options are largely fed straight to the pta command, for processing, we support the following options, which, are removed from the arguments, and handled in this method.
-
:from_s (String)- If a string is provided here, it’s fed to the STDIN of the pta adapter. And “-f -” is added to the program’s arguments. This instructs the command to treat STDIN as a journal.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/rvgp/pta.rb', line 147 def command(*args) opts = args.pop if args.last.is_a? Hash open3_opts = {} if opts args += opts.map do |k, v| if k.to_sym == :from_s open3_opts[:stdin_data] = v %w[-f -] else [format('--%s', k.to_s), v == true ? nil : v] unless v == false end end.flatten.compact end is_logging = ENV.key?('RVGP_LOG_COMMANDS') && !ENV['RVGP_LOG_COMMANDS'].empty? cmd = ([bin_path] + args.collect { |a| Shellwords.escape a }).join(' ') time_start = Time.now if is_logging output, error, status = Open3.capture3 cmd, open3_opts time_end = Time.now if is_logging # Maybe We should send this to a RVGP.logger.trace... if is_logging pretty_cmd = ([bin_path] + args).join(' ') puts format('(%.2<time>f elapsed) %<cmd>s', time: time_end - time_start, cmd: pretty_cmd) end unless status.success? raise StandardError, format('%<adapter_name>s exited non-zero (%<exitstatus>d): %<msg>s', adapter_name: adapter_name, exitstatus: status.exitstatus, msg: error) end output end |
#hledger? ⇒ TrueClass, FalseClass
Indicates whether or not this is a hledger pta adapter
265 266 267 |
# File 'lib/rvgp/pta.rb', line 265 def hledger? adapter_name == :hledger end |
#ledger? ⇒ TrueClass, FalseClass
Indicates whether or not this is a ledger pta adapter
259 260 261 |
# File 'lib/rvgp/pta.rb', line 259 def ledger? adapter_name == :ledger end |
#present? ⇒ TrueClass, FalseClass
Determines whether this adapter is found in the expected path, and is executable
240 241 242 |
# File 'lib/rvgp/pta.rb', line 240 def present? File.executable? bin_path end |
#stats(*args) ⇒ Hash<String, <String,Array<String>>>
Returns the output of the ‘stats’ command, parsed into key/value pairs.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/rvgp/pta.rb', line 115 def stats(*args) # Somehow, it turned out that both hledger and ledger were similar enough, that I could abstract # this here.... args, opts = args_and_opts(*args) # TODO: This should get its own error class... raise StandardError, "Unexpected argument(s) : #{args.inspect}" unless args.empty? command('stats', opts).scan(/^\n? *(?:([^:]+?)|(?:([^:]+?) *: *(.*?))) *$/).each_with_object([]) do |match, sum| if match[0] sum.last[1] = [sum.last[1]] unless sum.last[1].is_a?(Array) sum.last[1] << match[0] else sum << [match[1], match[2].empty? ? [] : match[2]] end sum end.to_h end |