Class: Canopus::Provider::Registry
- Inherits:
-
Object
- Object
- Canopus::Provider::Registry
- Defined in:
- lib/canopus/provider.rb,
sig/provider.rbs
Constant Summary collapse
- MAX_PROVIDERS =
64- MAX_ITEMS =
10_000- MAX_STRING =
65_536- PROVIDER_TIMEOUT =
0.2
Instance Method Summary collapse
- #complete(buffer, offset, context) ⇒ Array[Completion]
-
#initialize ⇒ Registry
constructor
A new instance of Registry.
- #inline_completion(buffer, offset) ⇒ String?
- #register_completion(source, priority:) {|arg0, arg1, arg2| ... } ⇒ Symbol
- #register_inline_completion(source) {|arg0, arg1| ... } ⇒ Symbol
Constructor Details
#initialize ⇒ Registry
Returns a new instance of Registry.
14 15 16 |
# File 'lib/canopus/provider.rb', line 14 def initialize @completion, @inline, @sequence = {}, {}, 0 end |
Instance Method Details
#complete(buffer, offset, context) ⇒ Array[Completion]
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/canopus/provider.rb', line 29 def complete(buffer, offset, context) validate_position(buffer, offset) query = completion_query(context) ranked, jobs = [], [] @completion.to_a.each do |source, details| thread = Thread.new { resolve(details.last.call(buffer, offset, context)) } thread.report_on_exception = false jobs << [source, details, thread] end jobs.sort_by! { |_source, (priority, registration, _supplier), _thread| [-priority, registration] } deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + PROVIDER_TIMEOUT jobs.each do |source, (priority, registration, _supplier), thread| break if ranked.length == MAX_ITEMS begin remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC) unless !thread.alive? || remaining.positive? && thread.join(remaining) raise RuntimeError, "completion provider timed out" end supplied = thread.value raise TypeError, "completion supplier must return an array" unless supplied.is_a?(Array) raise ArgumentError, "completion provider returned too many items" if supplied.length > MAX_ITEMS supplied = supplied.first(MAX_ITEMS - ranked.length) ranked.concat(supplied.each_with_index.map do |item, index| completion = normalize_completion(item, source, buffer) score = Spica.score(query, completion.filter_text || completion.label) [completion, score, priority, registration, index] end) rescue StandardError => error provider_error(context, source, error) end end ranked.sort_by! { |completion, score, priority, registration, index| [-score, -priority, completion.sort_text || completion.label, registration, index] } ranked.uniq! { |completion, _score, _priority, _registration, _index| [completion.label, completion.insert_text] } ranked.map!(&:first) ranked.freeze ensure jobs&.each do |_source, _details, thread| thread.kill if thread.alive? begin thread.join rescue StandardError nil end end end |
#inline_completion(buffer, offset) ⇒ String?
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/canopus/provider.rb', line 87 def inline_completion(buffer, offset) validate_position(buffer, offset) deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + PROVIDER_TIMEOUT @inline.sort_by { |_source, (registration, _supplier)| registration }.each do |_source, (_registration, supplier)| remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC) break unless remaining.positive? thread = Thread.new { resolve(supplier.call(buffer, offset)) } thread.report_on_exception = false begin remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC) break unless !thread.alive? || remaining.positive? && thread.join(remaining) value = thread.value next if value.nil? return normalize_string(value, "inline completion") rescue StandardError next ensure thread.kill if thread.alive? begin thread.join rescue StandardError nil end end end nil end |
#register_completion(source, priority:) {|arg0, arg1, arg2| ... } ⇒ Symbol
18 19 20 21 22 23 24 25 26 27 |
# File 'lib/canopus/provider.rb', line 18 def register_completion(source, priority:, &supplier) source = normalize_source(source) raise ArgumentError, "completion priority must be finite" unless priority.is_a?(Numeric) && priority.real? && priority.finite? raise ArgumentError, "completion supplier required" unless supplier raise ArgumentError, "too many completion providers" if !@completion.key?(source) && @completion.length >= MAX_PROVIDERS @sequence += 1 @completion[source] = [priority, @sequence, supplier] source end |
#register_inline_completion(source) {|arg0, arg1| ... } ⇒ Symbol
77 78 79 80 81 82 83 84 85 |
# File 'lib/canopus/provider.rb', line 77 def register_inline_completion(source, &supplier) source = normalize_source(source) raise ArgumentError, "inline completion supplier required" unless supplier raise ArgumentError, "too many inline completion providers" if !@inline.key?(source) && @inline.length >= MAX_PROVIDERS @sequence += 1 @inline[source] = [@sequence, supplier] source end |