openhab-jrubyscripting 5.0.0.rc10 → 5.0.0.rc11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/openhab/core/actions/audio.rb +47 -0
- data/lib/openhab/core/actions/ephemeris.rb +39 -0
- data/lib/openhab/core/actions/exec.rb +51 -0
- data/lib/openhab/core/actions/http.rb +80 -0
- data/lib/openhab/core/actions/ping.rb +30 -0
- data/lib/openhab/core/actions/transformation.rb +32 -0
- data/lib/openhab/core/actions/voice.rb +36 -0
- data/lib/openhab/core/actions.rb +23 -120
- data/lib/openhab/core/{events → dto}/item_channel_link.rb +1 -4
- data/lib/openhab/core/{events → dto}/thing.rb +10 -12
- data/lib/openhab/core/dto.rb +11 -0
- data/lib/openhab/core/entity_lookup.rb +1 -1
- data/lib/openhab/core/events/abstract_event.rb +1 -0
- data/lib/openhab/core/events/abstract_item_registry_event.rb +36 -0
- data/lib/openhab/core/events/abstract_thing_registry_event.rb +40 -0
- data/lib/openhab/core/events/item_command_event.rb +1 -1
- data/lib/openhab/core/events/item_state_changed_event.rb +6 -6
- data/lib/openhab/core/events/item_state_event.rb +6 -6
- data/lib/openhab/core/events/thing_status_info_event.rb +8 -6
- data/lib/openhab/core/items/generic_item.rb +2 -1
- data/lib/openhab/core/items/persistence.rb +52 -18
- data/lib/openhab/core/items/player_item.rb +1 -1
- data/lib/openhab/core/items/proxy.rb +20 -14
- data/lib/openhab/core/items/registry.rb +2 -0
- data/lib/openhab/core/items.rb +3 -3
- data/lib/openhab/core/profile_factory.rb +3 -1
- data/lib/openhab/core/proxy.rb +125 -0
- data/lib/openhab/core/things/links/provider.rb +1 -1
- data/lib/openhab/core/things/proxy.rb +8 -0
- data/lib/openhab/core/types/date_time_type.rb +2 -1
- data/lib/openhab/core/types/decimal_type.rb +1 -1
- data/lib/openhab/core/types/un_def_type.rb +2 -2
- data/lib/openhab/core/value_cache.rb +1 -1
- data/lib/openhab/core_ext/ephemeris.rb +53 -0
- data/lib/openhab/core_ext/java/class.rb +1 -1
- data/lib/openhab/core_ext/java/duration.rb +25 -1
- data/lib/openhab/core_ext/java/local_date.rb +2 -0
- data/lib/openhab/core_ext/java/month_day.rb +2 -0
- data/lib/openhab/core_ext/java/zoned_date_time.rb +85 -0
- data/lib/openhab/core_ext/ruby/date.rb +2 -0
- data/lib/openhab/core_ext/ruby/date_time.rb +1 -0
- data/lib/openhab/core_ext/ruby/time.rb +1 -0
- data/lib/openhab/dsl/debouncer.rb +259 -0
- data/lib/openhab/dsl/items/builder.rb +4 -2
- data/lib/openhab/dsl/items/timed_command.rb +31 -13
- data/lib/openhab/dsl/rules/automation_rule.rb +28 -21
- data/lib/openhab/dsl/rules/builder.rb +357 -37
- data/lib/openhab/dsl/rules/guard.rb +12 -54
- data/lib/openhab/dsl/rules/name_inference.rb +11 -0
- data/lib/openhab/dsl/rules/property.rb +3 -4
- data/lib/openhab/dsl/rules/terse.rb +4 -1
- data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +5 -6
- data/lib/openhab/dsl/rules/triggers/cron/cron.rb +1 -0
- data/lib/openhab/dsl/rules/triggers/cron/cron_handler.rb +19 -31
- data/lib/openhab/dsl/rules/triggers/watch/watch.rb +1 -0
- data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +22 -30
- data/lib/openhab/dsl/things/builder.rb +1 -1
- data/lib/openhab/dsl/thread_local.rb +1 -0
- data/lib/openhab/dsl/version.rb +1 -1
- data/lib/openhab/dsl.rb +224 -3
- data/lib/openhab/rspec/hooks.rb +5 -2
- data/lib/openhab/rspec/karaf.rb +7 -0
- data/lib/openhab/rspec/mocks/instance_method_stasher.rb +22 -0
- data/lib/openhab/rspec/mocks/space.rb +23 -0
- data/lib/openhab/rspec/openhab/core/actions.rb +16 -4
- data/lib/openhab/rspec/openhab/core/items/proxy.rb +1 -13
- data/lib/openhab/rspec/suspend_rules.rb +1 -14
- data/lib/openhab/yard/base_helper.rb +19 -0
- data/lib/openhab/yard/code_objects/group_object.rb +9 -3
- data/lib/openhab/yard/coderay.rb +17 -0
- data/lib/openhab/yard/handlers/jruby/base.rb +10 -1
- data/lib/openhab/yard/handlers/jruby/java_import_handler.rb +3 -0
- data/lib/openhab/yard/html_helper.rb +49 -15
- data/lib/openhab/yard/markdown_helper.rb +135 -0
- data/lib/openhab/yard.rb +6 -0
- metadata +36 -4
data/lib/openhab/dsl.rb
CHANGED
@@ -37,6 +37,13 @@ module OpenHAB
|
|
37
37
|
public_class_method(*mod.private_instance_methods)
|
38
38
|
end
|
39
39
|
|
40
|
+
class << self
|
41
|
+
# @!visibility private
|
42
|
+
attr_reader :debouncers
|
43
|
+
end
|
44
|
+
|
45
|
+
@debouncers = java.util.concurrent.ConcurrentHashMap.new
|
46
|
+
|
40
47
|
module_function
|
41
48
|
|
42
49
|
# @!group Rule Creation
|
@@ -53,6 +60,8 @@ module OpenHAB
|
|
53
60
|
|
54
61
|
# @!group Rule Support
|
55
62
|
|
63
|
+
# rubocop:disable Layout/LineLength
|
64
|
+
|
56
65
|
#
|
57
66
|
# Defines a new profile that can be applied to item channel links.
|
58
67
|
#
|
@@ -79,8 +88,8 @@ module OpenHAB
|
|
79
88
|
# @see org.openhab.thing.Profile
|
80
89
|
# @see org.openhab.thing.StateProfile
|
81
90
|
#
|
82
|
-
# @example
|
83
|
-
# profile(:veto_closing_shades) do |event, item:, command
|
91
|
+
# @example Vetoing a command
|
92
|
+
# profile(:veto_closing_shades) do |event, item:, command:|
|
84
93
|
# next false if command&.down?
|
85
94
|
#
|
86
95
|
# true
|
@@ -94,9 +103,37 @@ module OpenHAB
|
|
94
103
|
# # can also be referenced from an `.items` file:
|
95
104
|
# # Rollershutter MyShade { channel="thing:rollershutter"[profile="ruby:veto_closing_shades"] }
|
96
105
|
#
|
106
|
+
# @example Overriding units from a binding
|
107
|
+
# profile(:set_uom) do |event, configuration:, state:, command:|
|
108
|
+
# unless configuration["unit"]
|
109
|
+
# logger.warn("Unit configuration not provided for set_uom profile")
|
110
|
+
# next true
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# case event
|
114
|
+
# when :state_from_handler
|
115
|
+
# next true unless state.is_a?(DecimalType) || state.is_a?(QuantityType) # what is it then?!
|
116
|
+
#
|
117
|
+
# state = state.to_d if state.is_a?(QuantityType) # ignore the units if QuantityType was given
|
118
|
+
# callback.send_update(state | configuration["unit"])
|
119
|
+
# false
|
120
|
+
# when :command_from_item
|
121
|
+
# # strip the unit from the command, as the binding likely can't handle it
|
122
|
+
# next true unless command.is_a?(QuantityType)
|
123
|
+
#
|
124
|
+
# callback.send_command(DecimalType.new(command.to_d))
|
125
|
+
# false
|
126
|
+
# else
|
127
|
+
# true # pass other events through as normal
|
128
|
+
# end
|
129
|
+
# end
|
130
|
+
# # can also be referenced from an `.items` file:
|
131
|
+
# # Number:Temperature MyTempWithNonUnitValueFromBinding "I prefer Celsius [%d °C]" { channel="something_that_returns_F"[profile="ruby:set_uom", unit="°F"] }
|
132
|
+
#
|
97
133
|
def profile(id, &block)
|
98
134
|
raise ArgumentError, "Block is required" unless block
|
99
135
|
|
136
|
+
id = id.to_s
|
100
137
|
uid = org.openhab.core.thing.profiles.ProfileTypeUID.new("ruby", id)
|
101
138
|
|
102
139
|
ThreadLocal.thread_local(openhab_rule_type: "profile", openhab_rule_uid: id) do
|
@@ -104,6 +141,8 @@ module OpenHAB
|
|
104
141
|
end
|
105
142
|
end
|
106
143
|
|
144
|
+
# rubocop:enable Layout/LineLength
|
145
|
+
|
107
146
|
# @!group Object Access
|
108
147
|
|
109
148
|
#
|
@@ -335,6 +374,133 @@ module OpenHAB
|
|
335
374
|
Range.new(start, finish, range.exclude_end?)
|
336
375
|
end
|
337
376
|
|
377
|
+
#
|
378
|
+
# Limits the frequency of calls to the given block within a given amount of time.
|
379
|
+
#
|
380
|
+
# It can be useful to throttle certain actions even when a rule is triggered too often.
|
381
|
+
# This can be used to debounce triggers in a UI rule.
|
382
|
+
#
|
383
|
+
# @param (see Debouncer#initialize)
|
384
|
+
# @param [Object] id ID to associate with this debouncer.
|
385
|
+
# @param [Block] block The block to be debounced.
|
386
|
+
#
|
387
|
+
# @return [void]
|
388
|
+
#
|
389
|
+
# @example Run at most once per second even when being called more frequently
|
390
|
+
# (1..100).each do
|
391
|
+
# debounce for: 1.second do
|
392
|
+
# logger.info "This will not be logged more frequently than every 1 second"
|
393
|
+
# end
|
394
|
+
# sleep 0.1
|
395
|
+
# end
|
396
|
+
#
|
397
|
+
# @see Debouncer Debouncer class
|
398
|
+
# @see Rules::BuilderDSL#debounce debounce rule guard
|
399
|
+
#
|
400
|
+
# @!visibility private
|
401
|
+
def debounce(for:, leading: false, idle_time: nil, id: nil, &block)
|
402
|
+
interval = binding.local_variable_get(:for)
|
403
|
+
id ||= block.source_location
|
404
|
+
DSL.debouncers.compute(id) do |_key, debouncer|
|
405
|
+
debouncer ||= Debouncer.new(for: interval, leading: leading, idle_time: idle_time)
|
406
|
+
debouncer.call(&block)
|
407
|
+
debouncer
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
#
|
412
|
+
# Waits until calls to this method have stopped firing for a period of time
|
413
|
+
# before executing the block.
|
414
|
+
#
|
415
|
+
# This method acts as a guard for the given block to ensure that it doesn't get executed
|
416
|
+
# too frequently. The debounce_for method can be called as frequently as possible.
|
417
|
+
# The given block, however, will only be executed once the `debounce_time` has passed
|
418
|
+
# since the last call to debounce_for.
|
419
|
+
#
|
420
|
+
# This method can be used from within a UI rule as well as from a file-based rule.
|
421
|
+
#
|
422
|
+
# @param (see Rules::BuilderDSL#debounce_for)
|
423
|
+
# @param [Object] id ID to associate with this call.
|
424
|
+
# @param [Block] block The block to be debounced.
|
425
|
+
#
|
426
|
+
# @return [void]
|
427
|
+
#
|
428
|
+
# @example Run a block of code only after an item has stopped changing
|
429
|
+
# # This can be placed inside a UI rule with an Item Change trigger for
|
430
|
+
# # a Door contact sensor.
|
431
|
+
# # If the door state has stopped changing state for 10 minutes,
|
432
|
+
# # execute the block.
|
433
|
+
# debounce_for(10.minutes) do
|
434
|
+
# if DoorState.open?
|
435
|
+
# Voice.say("The door has been left open!")
|
436
|
+
# end
|
437
|
+
# end
|
438
|
+
#
|
439
|
+
# @see Rules::BuilderDSL#debounce_for Rule builder's debounce_for for a detailed description
|
440
|
+
#
|
441
|
+
def debounce_for(debounce_time, id: nil, &block)
|
442
|
+
idle_time = debounce_time.is_a?(Range) ? debounce_time.begin : debounce_time
|
443
|
+
debounce(for: debounce_time, idle_time: idle_time, id: id, &block)
|
444
|
+
end
|
445
|
+
|
446
|
+
#
|
447
|
+
# Rate-limits block executions by delaying calls and only executing the last
|
448
|
+
# call within the given duration.
|
449
|
+
#
|
450
|
+
# When throttle_for is called, it will hold from executing the block and start
|
451
|
+
# a fixed timer for the given duration. Should more calls occur during
|
452
|
+
# this time, keep holding and once the wait time is over, execute the block.
|
453
|
+
#
|
454
|
+
# {throttle_for} will execute the block after it had waited for the given duration,
|
455
|
+
# regardless of how frequently `throttle_for` was called.
|
456
|
+
# In contrast, {debounce_for} will wait until there is a minimum interval
|
457
|
+
# between two triggers.
|
458
|
+
#
|
459
|
+
# {throttle_for} is ideal in situations where regular status updates need to be made
|
460
|
+
# for frequently changing values. It is also useful when a rule responds to triggers
|
461
|
+
# from multiple related items that are updated at around the same time. Instead of
|
462
|
+
# executing the rule multiple times, {throttle_for} will wait for a pre-set amount
|
463
|
+
# of time since the first group of triggers occurred before executing the rule.
|
464
|
+
#
|
465
|
+
# @param (see Rules::BuilderDSL#throttle_for)
|
466
|
+
# @param [Object] id ID to associate with this call.
|
467
|
+
# @param [Block] block The block to be throttled.
|
468
|
+
#
|
469
|
+
# @return [void]
|
470
|
+
#
|
471
|
+
# @see Rules::BuilderDSL#debounce_for Rule builder's debounce_for for a detailed description
|
472
|
+
# @see Rules::BuilderDSL#throttle_for
|
473
|
+
#
|
474
|
+
def throttle_for(duration, id: nil, &block)
|
475
|
+
debounce(for: duration, id: id, &block)
|
476
|
+
end
|
477
|
+
|
478
|
+
#
|
479
|
+
# Limit how often the given block executes to the specified interval.
|
480
|
+
#
|
481
|
+
# {only_every} will execute the given block but prevents further executions
|
482
|
+
# until the given interval has passed. In contrast, {throttle_for} will not
|
483
|
+
# execute the block immediately, and will wait until the end of the interval.
|
484
|
+
#
|
485
|
+
# @param (see Rules::BuilderDSL#only_every)
|
486
|
+
# @param [Object] id ID to associate with this call.
|
487
|
+
# @param [Block] block The block to be throttled.
|
488
|
+
#
|
489
|
+
# @return [void]
|
490
|
+
#
|
491
|
+
# @example Prevent door bell from ringing repeatedly
|
492
|
+
# # This can be called from a UI rule.
|
493
|
+
# # For file based rule, use the `only_every` rule guard
|
494
|
+
# only_every(30.seconds) do { Audio.play_sound("doorbell.mp3") }
|
495
|
+
#
|
496
|
+
# @see Rules::BuilderDSL#debounce_for Rule builder's debounce_for for a detailed description
|
497
|
+
# @see Rules::BuilderDSL#only_every
|
498
|
+
#
|
499
|
+
def only_every(interval, id: nil, &block)
|
500
|
+
interval = 1.send(interval) if %i[second minute hour day].include?(interval)
|
501
|
+
debounce(for: interval, leading: true, id: id, &block)
|
502
|
+
end
|
503
|
+
|
338
504
|
#
|
339
505
|
# Store states of supplied items
|
340
506
|
#
|
@@ -624,7 +790,7 @@ module OpenHAB
|
|
624
790
|
#
|
625
791
|
# @overload provider!(things: nil, items: nil, metadata: nil, links: nil, **metadata_items)
|
626
792
|
#
|
627
|
-
# @param [Core::Provider, org.openhab.core.registry.
|
793
|
+
# @param [Core::Provider, org.openhab.core.common.registry.ManagedProvider, :persistent, :transient, Proc] providers
|
628
794
|
# An explicit provider to use. If it's a {Core::Provider}, the type will be inferred automatically.
|
629
795
|
# Otherwise it's applied to all types.
|
630
796
|
# @param [Hash] providers_by_type
|
@@ -703,6 +869,61 @@ module OpenHAB
|
|
703
869
|
old_providers
|
704
870
|
end
|
705
871
|
|
872
|
+
#
|
873
|
+
# @see CoreExt::Ephemeris
|
874
|
+
#
|
875
|
+
# @overload holiday_file(file)
|
876
|
+
#
|
877
|
+
# Sets a thread local variable to use a specific holiday file
|
878
|
+
# for {CoreExt::Ephemeris ephemeris calls} inside the block.
|
879
|
+
#
|
880
|
+
# @param [String, nil] file Path to a file defining holidays;
|
881
|
+
# `nil` to reset to default.
|
882
|
+
# @yield [] Block executed in context of the supplied holiday file
|
883
|
+
# @return [Object] The return value from the block.
|
884
|
+
#
|
885
|
+
# @example Set a specific holiday configuration file temporarily
|
886
|
+
# holiday_file("/home/cody/holidays.xml") do
|
887
|
+
# Time.now.next_holiday
|
888
|
+
# end
|
889
|
+
#
|
890
|
+
# @see holiday_file!
|
891
|
+
#
|
892
|
+
# @overload holiday_file
|
893
|
+
#
|
894
|
+
# Returns the current thread local value for the holiday file.
|
895
|
+
#
|
896
|
+
# @return [String, nil] the current holiday file
|
897
|
+
#
|
898
|
+
def holiday_file(*args)
|
899
|
+
raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 0..1)" if args.length > 1
|
900
|
+
|
901
|
+
old = Thread.current[:openhab_holiday_file]
|
902
|
+
return old if args.empty?
|
903
|
+
|
904
|
+
holiday_file!(args.first)
|
905
|
+
yield
|
906
|
+
ensure
|
907
|
+
holiday_file!(old)
|
908
|
+
end
|
909
|
+
|
910
|
+
#
|
911
|
+
# Sets a thread local variable to set the default holiday file.
|
912
|
+
#
|
913
|
+
# @see https://github.com/svendiedrichsen/jollyday/tree/master/src/main/resources/holidays Example data files from the source
|
914
|
+
#
|
915
|
+
# @example
|
916
|
+
# holiday_file!("/home/cody/holidays.xml")
|
917
|
+
# Time.now.next_holiday
|
918
|
+
#
|
919
|
+
# @param [String, nil] file Path to a file defining holidays;
|
920
|
+
# `nil` to reset to default.
|
921
|
+
# @return [Symbol, nil] the new holiday file
|
922
|
+
#
|
923
|
+
def holiday_file!(file = nil)
|
924
|
+
Thread.current[:openhab_holiday_file] = file
|
925
|
+
end
|
926
|
+
|
706
927
|
# @!visibility private
|
707
928
|
def try_parse_time_like(string)
|
708
929
|
return string unless string.is_a?(String)
|
data/lib/openhab/rspec/hooks.rb
CHANGED
@@ -32,6 +32,11 @@ module OpenHAB
|
|
32
32
|
config.include ExampleGroup
|
33
33
|
|
34
34
|
config.before(:suite) do
|
35
|
+
if config.mock_framework.framework_name == :rspec
|
36
|
+
require_relative "mocks/instance_method_stasher"
|
37
|
+
require_relative "mocks/space"
|
38
|
+
end
|
39
|
+
|
35
40
|
Helpers.autorequires unless Configuration.private_confdir
|
36
41
|
Helpers.send(:set_up_autoupdates)
|
37
42
|
Helpers.load_transforms
|
@@ -86,8 +91,6 @@ module OpenHAB
|
|
86
91
|
end
|
87
92
|
|
88
93
|
config.after do
|
89
|
-
Core::Items::Proxy.reset_cache
|
90
|
-
Core::Things::Proxy.reset_cache
|
91
94
|
@profile_factory.unregister
|
92
95
|
timers.cancel_all
|
93
96
|
# timers and rules have already been canceled, so we can safely just
|
data/lib/openhab/rspec/karaf.rb
CHANGED
@@ -280,6 +280,13 @@ module OpenHAB
|
|
280
280
|
props = cfg.properties || java.util.Hashtable.new
|
281
281
|
props.put("default", "default")
|
282
282
|
cfg.update(props)
|
283
|
+
|
284
|
+
# configure ephemeris with basic values
|
285
|
+
cfg = ca.get_configuration("org.openhab.ephemeris", nil)
|
286
|
+
props = cfg.properties || java.util.Hashtable.new
|
287
|
+
props.put("country", "us")
|
288
|
+
props.put("dayset-weekend", %w[SATURDAY SUNDAY])
|
289
|
+
cfg.update(props)
|
283
290
|
end
|
284
291
|
wait_for_service("org.openhab.core.automation.RuleManager") do |re|
|
285
292
|
require_relative "mocks/synchronous_executor"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OpenHAB
|
4
|
+
module RSpec
|
5
|
+
module Mocks
|
6
|
+
module InstanceMethodStasher
|
7
|
+
::RSpec::Mocks::InstanceMethodStasher.prepend(self)
|
8
|
+
|
9
|
+
# Disable "singleton on non-persistent Java type"
|
10
|
+
# it doesn't matter during specs
|
11
|
+
def initialize(*)
|
12
|
+
original_verbose = $VERBOSE
|
13
|
+
$VERBOSE = nil
|
14
|
+
|
15
|
+
super
|
16
|
+
ensure
|
17
|
+
$VERBOSE = original_verbose
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OpenHAB
|
4
|
+
module RSpec
|
5
|
+
module Mocks
|
6
|
+
module Space
|
7
|
+
::RSpec::Mocks::Space.prepend(self)
|
8
|
+
|
9
|
+
#
|
10
|
+
# When setting expectations on {Items::Proxy proxies}, set them against the item
|
11
|
+
# themselves, so that it will catch calls against `self` from within the instance.
|
12
|
+
#
|
13
|
+
def proxy_for(object)
|
14
|
+
return super unless ::RSpec.current_example&.example_group&.consistent_proxies?
|
15
|
+
|
16
|
+
object = object.__getobj__ if object.is_a?(Core::Items::Proxy)
|
17
|
+
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -12,12 +12,24 @@ module OpenHAB
|
|
12
12
|
logger.debug("notify: #{msg}")
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
class Voice
|
16
|
+
class << self
|
17
|
+
def say(text, voice: nil, sink: nil, volume: nil)
|
18
|
+
logger.debug("say: #{text}")
|
19
|
+
end
|
20
|
+
end
|
17
21
|
end
|
18
22
|
|
19
|
-
|
20
|
-
|
23
|
+
class Audio
|
24
|
+
class << self
|
25
|
+
def play_sound(filename, sink: nil, volume: nil)
|
26
|
+
logger.debug("play_sound: #{filename}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def play_stream(url, sink: nil)
|
30
|
+
logger.debug("play_stream: #{url}")
|
31
|
+
end
|
32
|
+
end
|
21
33
|
end
|
22
34
|
|
23
35
|
# rubocop:enable Lint/UnusedMethodArgument
|
@@ -4,21 +4,9 @@ module OpenHAB
|
|
4
4
|
module Core
|
5
5
|
module Items
|
6
6
|
class Proxy
|
7
|
-
@proxies = {}
|
8
|
-
|
9
7
|
class << self
|
10
|
-
# ensure each item only has a single proxy, so that
|
11
|
-
# expect(item).to receive(:method) works
|
12
|
-
def new(item)
|
13
|
-
return super unless defined?(::RSpec) && ::RSpec.current_example&.example_group&.consistent_proxies?
|
14
|
-
|
15
|
-
@proxies.fetch(item.name) do
|
16
|
-
@proxies[item.name] = super
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
8
|
def reset_cache
|
21
|
-
@proxies
|
9
|
+
@proxies.clear
|
22
10
|
end
|
23
11
|
end
|
24
12
|
end
|
@@ -12,20 +12,7 @@ module OpenHAB
|
|
12
12
|
logger.trace("Skipping execution of #{uid} because rules are suspended.")
|
13
13
|
return
|
14
14
|
end
|
15
|
-
|
16
|
-
# super
|
17
|
-
::OpenHAB::DSL::ThreadLocal.thread_local(**@thread_locals) do
|
18
|
-
logger.trace { "Execute called with mod (#{mod&.to_string}) and inputs (#{inputs.inspect})" }
|
19
|
-
logger.trace { "Event details #{inputs["event"].inspect}" } if inputs&.key?("event")
|
20
|
-
trigger_conditions(inputs).process(mod: mod, inputs: inputs) do
|
21
|
-
event = extract_event(inputs)
|
22
|
-
process_queue(create_queue(event), mod, event)
|
23
|
-
end
|
24
|
-
rescue Exception => e
|
25
|
-
raise if defined?(::RSpec) && ::RSpec.current_example.example_group.propagate_exceptions?
|
26
|
-
|
27
|
-
@run_context.send(:logger).log_exception(e)
|
28
|
-
end
|
15
|
+
execute!(mod, inputs)
|
29
16
|
end
|
30
17
|
end
|
31
18
|
# private_constant :AutomationRule
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OpenHAB
|
4
|
+
module YARD
|
5
|
+
# @!visibility private
|
6
|
+
module BaseHelper
|
7
|
+
def link_object(obj, title = nil, *)
|
8
|
+
::YARD::Handlers::JRuby::Base.infer_java_class(obj) if obj.is_a?(String)
|
9
|
+
obj = ::YARD::Registry.resolve(object, obj, true, true) if obj.is_a?(String)
|
10
|
+
if obj.is_a?(::YARD::CodeObjects::Java::Base) && (see = obj.docstring.tag(:see))
|
11
|
+
# link to the first see tag
|
12
|
+
return linkify(see.name, title&.to_s || see.text)
|
13
|
+
end
|
14
|
+
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -4,13 +4,19 @@ module OpenHAB
|
|
4
4
|
module YARD
|
5
5
|
module CodeObjects
|
6
6
|
class GroupObject < ::YARD::CodeObjects::Base
|
7
|
+
attr_reader :full_name
|
8
|
+
|
9
|
+
def initialize(namespace, name)
|
10
|
+
@full_name = name
|
11
|
+
name = name.delete(%(.?"')).tr(" ", "-")
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
7
15
|
def path
|
8
16
|
"group#{sep}#{super}"
|
9
17
|
end
|
10
18
|
|
11
|
-
|
12
|
-
name
|
13
|
-
end
|
19
|
+
alias_method :to_s, :full_name
|
14
20
|
end
|
15
21
|
end
|
16
22
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "coderay"
|
4
|
+
|
5
|
+
module OpenHAB
|
6
|
+
module YARD
|
7
|
+
module CodeRay
|
8
|
+
module HtmlHelper
|
9
|
+
::CodeRay::Scanners.list.each do |scanner|
|
10
|
+
define_method("html_syntax_highlight_#{scanner}") do |source|
|
11
|
+
::CodeRay.scan(source, scanner).html
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -7,9 +7,18 @@ module YARD
|
|
7
7
|
class << self
|
8
8
|
def infer_java_class(klass, inferred_type = nil, comments = nil, statement = nil)
|
9
9
|
components = klass.split(".")
|
10
|
+
components.pop if components.last == "freeze"
|
11
|
+
|
10
12
|
class_first_char = components.last[0]
|
11
13
|
is_field = components.last == components.last.upcase
|
12
|
-
|
14
|
+
container_first_char = components[-2]&.[](0)
|
15
|
+
is_method = container_first_char &&
|
16
|
+
class_first_char != class_first_char.upcase &&
|
17
|
+
container_first_char == container_first_char.upcase
|
18
|
+
is_package = !is_method && !is_field && class_first_char != class_first_char.upcase
|
19
|
+
|
20
|
+
# methods aren't supported right now
|
21
|
+
return if is_method
|
13
22
|
|
14
23
|
javadocs = YARD::Config.options.dig(:jruby, "javadocs") || {}
|
15
24
|
|
@@ -14,6 +14,9 @@ module YARD
|
|
14
14
|
obj = infer_java_class(klass)
|
15
15
|
next unless obj
|
16
16
|
|
17
|
+
# don't overwrite an already-extant object with the same name
|
18
|
+
next if ::YARD::Registry.at("#{namespace.path}::#{obj.simple_name}")
|
19
|
+
|
17
20
|
# then we create a new constant in the current namespace
|
18
21
|
register CodeObjects::ConstantObject.new(namespace, obj.simple_name) { |o|
|
19
22
|
o.source = statement
|
@@ -1,17 +1,62 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "nokogiri"
|
4
|
+
|
3
5
|
module OpenHAB
|
4
6
|
module YARD
|
5
7
|
# @!visibility private
|
6
8
|
module HtmlHelper
|
9
|
+
def base_url
|
10
|
+
if serializer.is_a?(::YARD::Server::DocServerSerializer)
|
11
|
+
abs_url(base_path(router.docs_prefix), "")
|
12
|
+
else
|
13
|
+
u = url_for("")
|
14
|
+
u = "#{u}/" if !u.empty? && u[-1] != "/"
|
15
|
+
u
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def url_for_search_index
|
20
|
+
if serializer.is_a?(::YARD::Server::DocServerSerializer)
|
21
|
+
url_for_list("index")
|
22
|
+
else
|
23
|
+
url_for("index.json")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
7
27
|
def html_markup_markdown(text)
|
8
|
-
result = super
|
28
|
+
result = super(text)
|
9
29
|
|
30
|
+
html = Nokogiri::HTML5.fragment(result)
|
10
31
|
# re-link files in docs/*.md. They're written so they work on github without any
|
11
32
|
# processing
|
12
|
-
|
13
|
-
|
14
|
-
|
33
|
+
unless serializer.is_a?(::YARD::Server::DocServerSerializer)
|
34
|
+
html.css("a[href!='']").each do |link|
|
35
|
+
uri = URI.parse(link["href"])
|
36
|
+
next unless uri.relative? && File.extname(uri.path) == ".md"
|
37
|
+
|
38
|
+
basename = File.basename(uri.path, ".md")
|
39
|
+
uri.path = "file.#{basename}.html"
|
40
|
+
link["href"] = uri.to_s
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# wtf commonmarker, you don't generate anchors?!
|
45
|
+
html.css("h1, h2, h3, h4, h5, h6").each do |header|
|
46
|
+
next if header["id"]
|
47
|
+
|
48
|
+
id = header.text.strip.downcase.delete(%(.?"')).tr(" ", "-")
|
49
|
+
header["id"] = id
|
50
|
+
header.prepend_child(%(<a href="##{id}" class="header-anchor">#</a>))
|
51
|
+
end
|
52
|
+
|
53
|
+
html.to_s
|
54
|
+
end
|
55
|
+
|
56
|
+
def link_url(url, title = nil, params = {})
|
57
|
+
params.merge!(@link_attrs) if defined?(@link_attrs) && @link_attrs
|
58
|
+
params[:class] = params.delete(:classes).join(" ") if params[:classes]
|
59
|
+
super
|
15
60
|
end
|
16
61
|
|
17
62
|
# have to completely replace this method. only change is the regex splitting
|
@@ -28,17 +73,6 @@ module OpenHAB
|
|
28
73
|
list.empty? ? "" : (brackets ? "(#{list.join(", ")})" : list.join(", "))
|
29
74
|
end
|
30
75
|
# rubocop:enable Style/NestedTernaryOperator, Style/StringConcatenation, Style/TernaryParentheses
|
31
|
-
|
32
|
-
def link_object(obj, title = nil, *)
|
33
|
-
::YARD::Handlers::JRuby::Base.infer_java_class(obj) if obj.is_a?(String)
|
34
|
-
obj = ::YARD::Registry.resolve(object, obj, true, true) if obj.is_a?(String)
|
35
|
-
if obj.is_a?(::YARD::CodeObjects::Java::Base) && (see = obj.docstring.tag(:see))
|
36
|
-
# link to the first see tag
|
37
|
-
return linkify(see.name, title&.to_s || see.text)
|
38
|
-
end
|
39
|
-
|
40
|
-
super
|
41
|
-
end
|
42
76
|
end
|
43
77
|
end
|
44
78
|
end
|