guard 2.7.0 → 2.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/guard +7 -2
- data/lib/guard.rb +16 -5
- data/lib/guard.rb.orig +210 -0
- data/lib/guard/aruba_adapter.rb +59 -0
- data/lib/guard/cli.rb +1 -1
- data/lib/guard/commander.rb +3 -1
- data/lib/guard/commands/scope.rb +1 -1
- data/lib/guard/deprecated_methods.rb +16 -0
- data/lib/guard/deprecator.rb +15 -0
- data/lib/guard/dsl_describer.rb +0 -2
- data/lib/guard/guardfile/evaluator.rb +2 -2
- data/lib/guard/interactor.rb.orig +6 -1
- data/lib/guard/jobs/pry_wrapper.rb +1 -0
- data/lib/guard/jobs/stdin.rb.orig +46 -0
- data/lib/guard/notifiers/emacs.rb +3 -8
- data/lib/guard/notifiers/emacs.rb.orig +103 -0
- data/lib/guard/plugin_util.rb +5 -3
- data/lib/guard/runner.rb +34 -31
- data/lib/guard/setuper.rb +24 -11
- data/lib/guard/setuper.rb.orig +56 -20
- data/lib/guard/sheller.rb +47 -11
- data/lib/guard/sheller.rb.orig +107 -0
- data/lib/guard/tags +182 -107
- data/lib/guard/terminal.rb +11 -0
- data/lib/guard/terminal.rb.orig +0 -0
- data/lib/guard/ui.rb +21 -2
- data/lib/guard/ui.rb.orig +11 -1
- data/lib/guard/version.rb +1 -1
- data/lib/guard/version.rb.orig +1 -1
- data/lib/guard/watcher.rb.orig +119 -0
- metadata +10 -9
- data/lib/guard/cli.rb.orig +0 -215
- data/lib/guard/dsl_describer.rb.orig +0 -184
- data/lib/guard/guard.rb.orig +0 -42
- data/lib/guard/guardfile/evaluator.rb.orig +0 -275
- data/lib/guard/jobs/pry_wrapper.rb.orig +0 -293
- data/lib/guard/plugin_util.rb.orig +0 -178
- data/lib/guard/runner.rb.orig +0 -200
@@ -1,184 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require "formatador"
|
3
|
-
|
4
|
-
require "guard/guardfile/evaluator"
|
5
|
-
require "guard/ui"
|
6
|
-
|
7
|
-
module Guard
|
8
|
-
# The DslDescriber evaluates the Guardfile and creates an internal structure
|
9
|
-
# of it that is used in some inspection utility methods like the CLI commands
|
10
|
-
# `show` and `list`.
|
11
|
-
#
|
12
|
-
# @see Guard::Dsl
|
13
|
-
# @see Guard::CLI
|
14
|
-
#
|
15
|
-
class DslDescriber
|
16
|
-
attr_reader :options
|
17
|
-
|
18
|
-
# Initializes a new DslDescriber object.
|
19
|
-
#
|
20
|
-
# @option options [String] guardfile the path to a valid Guardfile
|
21
|
-
#
|
22
|
-
# @option options [String] guardfile_contents a string representing the
|
23
|
-
# content of a valid Guardfile
|
24
|
-
#
|
25
|
-
# @see Guard::Guardfile::Evaluator#initialize
|
26
|
-
#
|
27
|
-
def initialize(options = {})
|
28
|
-
@options = options
|
29
|
-
::Guard.reset_groups
|
30
|
-
::Guard.reset_plugins
|
31
|
-
::Guard.reset_scope
|
32
|
-
end
|
33
|
-
|
34
|
-
# List the Guard plugins that are available for use in your system and marks
|
35
|
-
# those that are currently used in your `Guardfile`.
|
36
|
-
#
|
37
|
-
# @see CLI#list
|
38
|
-
#
|
39
|
-
def list
|
40
|
-
_evaluate_guardfile
|
41
|
-
|
42
|
-
names = ::Guard::PluginUtil.plugin_names.sort.uniq
|
43
|
-
final_rows = names.inject([]) do |rows, name|
|
44
|
-
rows << {
|
45
|
-
Plugin: name.capitalize,
|
46
|
-
Guardfile: ::Guard.plugins(name) ? "✔" : "✘"
|
47
|
-
}
|
48
|
-
end
|
49
|
-
|
50
|
-
Formatador.display_compact_table(final_rows, [:Plugin, :Guardfile])
|
51
|
-
end
|
52
|
-
|
53
|
-
# Shows all Guard plugins and their options that are defined in
|
54
|
-
# the `Guardfile`.
|
55
|
-
#
|
56
|
-
# @see CLI#show
|
57
|
-
#
|
58
|
-
def show
|
59
|
-
_evaluate_guardfile
|
60
|
-
groups = ::Guard.groups
|
61
|
-
|
62
|
-
final_rows = groups.each_with_object([]) do |group, rows|
|
63
|
-
|
64
|
-
plugins = Array(::Guard.plugins(group: group.name))
|
65
|
-
|
66
|
-
plugins.each do |plugin|
|
67
|
-
options = plugin.options.inject({}) do |o, (k, v)|
|
68
|
-
o.tap { |option| option[k.to_s] = v }
|
69
|
-
end.sort
|
70
|
-
|
71
|
-
if options.empty?
|
72
|
-
rows << :split
|
73
|
-
rows << {
|
74
|
-
Group: group.title,
|
75
|
-
Plugin: plugin.title,
|
76
|
-
Option: "",
|
77
|
-
Value: ""
|
78
|
-
}
|
79
|
-
else
|
80
|
-
options.each_with_index do |(option, value), index|
|
81
|
-
if index == 0
|
82
|
-
rows << :split
|
83
|
-
rows << {
|
84
|
-
Group: group.title,
|
85
|
-
Plugin: plugin.title,
|
86
|
-
Option: option.to_s,
|
87
|
-
Value: value.inspect
|
88
|
-
}
|
89
|
-
else
|
90
|
-
rows << {
|
91
|
-
Group: "",
|
92
|
-
Plugin: "",
|
93
|
-
Option: option.to_s,
|
94
|
-
Value: value.inspect
|
95
|
-
}
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
rows
|
102
|
-
end
|
103
|
-
|
104
|
-
Formatador.display_compact_table(
|
105
|
-
final_rows.drop(1),
|
106
|
-
[:Group, :Plugin, :Option, :Value]
|
107
|
-
)
|
108
|
-
end
|
109
|
-
|
110
|
-
# Shows all notifiers and their options that are defined in
|
111
|
-
# the `Guardfile`.
|
112
|
-
#
|
113
|
-
# @see CLI#show
|
114
|
-
#
|
115
|
-
def notifiers
|
116
|
-
_evaluate_guardfile
|
117
|
-
|
118
|
-
merged_notifiers = ::Guard::Notifier::NOTIFIERS.inject(:merge)
|
119
|
-
final_rows = merged_notifiers.each_with_object([]) do |definition, rows|
|
120
|
-
|
121
|
-
name = definition[0]
|
122
|
-
clazz = definition[1]
|
123
|
-
available = clazz.available?(silent: true) ? "✔" : "✘"
|
124
|
-
notifier = ::Guard::Notifier.notifiers.detect { |n| n[:name] == name }
|
125
|
-
used = notifier ? "✔" : "✘"
|
126
|
-
|
127
|
-
options = _merge_options(clazz, notifier)
|
128
|
-
options.delete(:silent)
|
129
|
-
|
130
|
-
if options.empty?
|
131
|
-
rows << :split
|
132
|
-
_add_row(rows, name, available, used, "", "")
|
133
|
-
else
|
134
|
-
options.each_with_index do |(option, value), index|
|
135
|
-
if index == 0
|
136
|
-
rows << :split
|
137
|
-
_add_row(rows, name, available, used, option.to_s, value.inspect)
|
138
|
-
else
|
139
|
-
_add_row(rows, "", "", "", option.to_s, value.inspect)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
rows
|
145
|
-
end
|
146
|
-
|
147
|
-
Formatador.display_compact_table(
|
148
|
-
final_rows.drop(1),
|
149
|
-
[:Name, :Available, :Used, :Option, :Value]
|
150
|
-
)
|
151
|
-
end
|
152
|
-
|
153
|
-
private
|
154
|
-
|
155
|
-
# Evaluates the `Guardfile` by delegating to
|
156
|
-
# {Guard::Guardfile::Evaluator#evaluate_guardfile}.
|
157
|
-
#
|
158
|
-
def _evaluate_guardfile
|
159
|
-
::Guard.save_scope
|
160
|
-
::Guard::Guardfile::Evaluator.new(options).evaluate_guardfile
|
161
|
-
::Guard.restore_scope
|
162
|
-
end
|
163
|
-
|
164
|
-
def _merge_options(klass, notifier)
|
165
|
-
notify_options = notifier ? notifier[:options] : {}
|
166
|
-
|
167
|
-
if klass.const_defined?(:DEFAULTS)
|
168
|
-
klass.const_get(:DEFAULTS).merge(notify_options)
|
169
|
-
else
|
170
|
-
notify_options
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
def _add_row(rows, name, available, used, option, value)
|
175
|
-
rows << {
|
176
|
-
Name: name,
|
177
|
-
Available: available,
|
178
|
-
Used: used,
|
179
|
-
Option: option,
|
180
|
-
Value: value
|
181
|
-
}
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
data/lib/guard/guard.rb.orig
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
require "guard/plugin/base"
|
2
|
-
|
3
|
-
module Guard
|
4
|
-
# @deprecated Inheriting from `Guard::Guard` is deprecated, please inherit
|
5
|
-
# from {Plugin} instead. Please note that the constructor signature has
|
6
|
-
# changed from `Guard::Guard#initialize(watchers = [], options = {})` to
|
7
|
-
# `Guard::Plugin#initialize(options = {})`.
|
8
|
-
#
|
9
|
-
# @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
|
10
|
-
# upgrade for Guard 2.0
|
11
|
-
#
|
12
|
-
class Guard
|
13
|
-
include ::Guard::Plugin::Base
|
14
|
-
|
15
|
-
# @deprecated Inheriting from `Guard::Guard` is deprecated, please inherit
|
16
|
-
# from {Plugin} instead. Please note that the constructor signature
|
17
|
-
# has changed from `Guard::Guard#initialize(watchers = [], options = {})`
|
18
|
-
# to `Guard::Plugin#initialize(options = {})`.
|
19
|
-
#
|
20
|
-
# Initializes a Guard plugin. Don't do any work here,
|
21
|
-
# especially as Guard plugins get initialized even if they are not in an
|
22
|
-
# active group!
|
23
|
-
#
|
24
|
-
# @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
|
25
|
-
# upgrade for Guard 2.0
|
26
|
-
#
|
27
|
-
# @param [Array<Guard::Watcher>] watchers the Guard plugin file watchers
|
28
|
-
# @param [Hash] options the custom Guard plugin options
|
29
|
-
# @option options [Symbol] group the group this Guard plugin belongs to
|
30
|
-
# @option options [Boolean] any_return allow any object to be returned from
|
31
|
-
# a watcher
|
32
|
-
# @option options [Boolean] first_match stop after the first watcher that
|
33
|
-
# returns a valid result
|
34
|
-
#
|
35
|
-
def initialize(watchers = [], options = {})
|
36
|
-
UI.deprecation(Deprecator::GUARD_GUARD_DEPRECATION % title)
|
37
|
-
|
38
|
-
_set_instance_variables_from_options(options.merge(watchers: watchers))
|
39
|
-
_register_callbacks
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,275 +0,0 @@
|
|
1
|
-
require "guard/options"
|
2
|
-
require "guard/plugin"
|
3
|
-
|
4
|
-
module Guard
|
5
|
-
module Guardfile
|
6
|
-
# This class is responsible for evaluating the Guardfile. It delegates to
|
7
|
-
# Guard::Dsl for the actual objects generation from the Guardfile content.
|
8
|
-
#
|
9
|
-
# @see Guard::Dsl
|
10
|
-
#
|
11
|
-
class Evaluator
|
12
|
-
attr_reader :options, :guardfile_path
|
13
|
-
|
14
|
-
def guardfile_source
|
15
|
-
@source
|
16
|
-
end
|
17
|
-
|
18
|
-
# Initializes a new Guard::Guardfile::Evaluator object.
|
19
|
-
#
|
20
|
-
# @option opts [String] guardfile the path to a valid Guardfile
|
21
|
-
# @option opts [String] guardfile_contents a string representing the
|
22
|
-
# content of a valid Guardfile
|
23
|
-
#
|
24
|
-
def initialize(opts = {})
|
25
|
-
@source = nil
|
26
|
-
@guardfile_path = nil
|
27
|
-
|
28
|
-
valid_options = opts.select do |k, _|
|
29
|
-
[:guardfile, :guardfile_contents].include?(k.to_sym)
|
30
|
-
end
|
31
|
-
|
32
|
-
@options = ::Guard::Options.new(valid_options)
|
33
|
-
end
|
34
|
-
|
35
|
-
# Evaluates the DSL methods in the `Guardfile`.
|
36
|
-
#
|
37
|
-
# @example Programmatically evaluate a Guardfile
|
38
|
-
# Guard::Guardfile::Evaluator.new.evaluate_guardfile
|
39
|
-
#
|
40
|
-
# @example Programmatically evaluate a Guardfile with a custom Guardfile
|
41
|
-
# path
|
42
|
-
#
|
43
|
-
# options = { guardfile: '/Users/guardfile/MyAwesomeGuardfile' }
|
44
|
-
# Guard::Guardfile::Evaluator.new(options).evaluate_guardfile
|
45
|
-
#
|
46
|
-
# @example Programmatically evaluate a Guardfile with an inline Guardfile
|
47
|
-
#
|
48
|
-
# options = { guardfile_contents: 'guard :rspec' }
|
49
|
-
# Guard::Guardfile::Evaluator.new(options).evaluate_guardfile
|
50
|
-
#
|
51
|
-
def evaluate_guardfile
|
52
|
-
_fetch_guardfile_contents
|
53
|
-
::Guard.add_builtin_plugins
|
54
|
-
_instance_eval_guardfile(guardfile_contents)
|
55
|
-
end
|
56
|
-
|
57
|
-
# Re-evaluates the `Guardfile` to update
|
58
|
-
# the current Guard configuration.
|
59
|
-
#
|
60
|
-
def reevaluate_guardfile
|
61
|
-
# Don't re-evaluate inline Guardfile
|
62
|
-
return if @source == :inline
|
63
|
-
|
64
|
-
_before_reevaluate_guardfile
|
65
|
-
evaluate_guardfile
|
66
|
-
_after_reevaluate_guardfile
|
67
|
-
end
|
68
|
-
|
69
|
-
# Tests if the current `Guardfile` contains a specific Guard plugin.
|
70
|
-
#
|
71
|
-
# @example Programmatically test if a Guardfile contains a specific Guard
|
72
|
-
# plugin
|
73
|
-
#
|
74
|
-
# File.read('Guardfile')
|
75
|
-
# => "guard :rspec"
|
76
|
-
#
|
77
|
-
# Guard::Guardfile::Evaluator.new.guardfile_include?('rspec)
|
78
|
-
# => true
|
79
|
-
#
|
80
|
-
# @param [String] plugin_name the name of the Guard
|
81
|
-
# @return [Boolean] whether the Guard plugin has been declared
|
82
|
-
#
|
83
|
-
def guardfile_include?(plugin_name)
|
84
|
-
regexp = /^guard\s*\(?\s*['":]#{ plugin_name }['"]?/
|
85
|
-
_guardfile_contents_without_user_config.match(regexp)
|
86
|
-
end
|
87
|
-
|
88
|
-
# Gets the content of the `Guardfile` concatenated with the global
|
89
|
-
# user configuration file.
|
90
|
-
#
|
91
|
-
# @example Programmatically get the content of the current Guardfile
|
92
|
-
# Guard::Guardfile::Evaluator.new.guardfile_contents
|
93
|
-
# => "guard :rspec"
|
94
|
-
#
|
95
|
-
# @return [String] the Guardfile content
|
96
|
-
#
|
97
|
-
def guardfile_contents
|
98
|
-
config = File.read(_user_config_path) if File.exist?(_user_config_path)
|
99
|
-
[_guardfile_contents_without_user_config, config].compact.join("\n")
|
100
|
-
end
|
101
|
-
|
102
|
-
private
|
103
|
-
|
104
|
-
# Gets the content of the `Guardfile`.
|
105
|
-
#
|
106
|
-
# @return [String] the Guardfile content
|
107
|
-
#
|
108
|
-
def _guardfile_contents_without_user_config
|
109
|
-
@guardfile_contents || ""
|
110
|
-
end
|
111
|
-
|
112
|
-
# Evaluates the content of the `Guardfile`.
|
113
|
-
#
|
114
|
-
# @param [String] contents the content to evaluate.
|
115
|
-
#
|
116
|
-
def _instance_eval_guardfile(contents)
|
117
|
-
::Guard::Dsl.new.instance_eval(contents, @guardfile_path || "", 1)
|
118
|
-
rescue => ex
|
119
|
-
::Guard::UI.error "Invalid Guardfile, original error is:\n#{ $! }"
|
120
|
-
raise ex
|
121
|
-
end
|
122
|
-
|
123
|
-
# Gets the content to evaluate and stores it into @guardfile_contents.
|
124
|
-
#
|
125
|
-
def _fetch_guardfile_contents
|
126
|
-
_use_inline || _use_provided || _use_default
|
127
|
-
|
128
|
-
return if _guardfile_contents_usable?
|
129
|
-
::Guard::UI.error "No Guard plugins found in Guardfile,"\
|
130
|
-
" please add at least one."
|
131
|
-
end
|
132
|
-
|
133
|
-
# Use the provided inline Guardfile if provided.
|
134
|
-
#
|
135
|
-
def _use_inline
|
136
|
-
source_from_option = @source.nil? && options[:guardfile_contents]
|
137
|
-
inline = @source == :inline
|
138
|
-
|
139
|
-
return false unless (source_from_option) || inline
|
140
|
-
|
141
|
-
@source = :inline
|
142
|
-
@guardfile_contents = options[:guardfile_contents]
|
143
|
-
|
144
|
-
::Guard::UI.info "Using inline Guardfile."
|
145
|
-
true
|
146
|
-
end
|
147
|
-
|
148
|
-
# Try to use the provided Guardfile. Exits Guard if the Guardfile cannot
|
149
|
-
# be found.
|
150
|
-
#
|
151
|
-
def _use_provided
|
152
|
-
source_from_file = @source.nil? && options[:guardfile]
|
153
|
-
return false unless source_from_file || (@source == :custom)
|
154
|
-
|
155
|
-
@source = :custom
|
156
|
-
|
157
|
-
options[:guardfile] = File.expand_path(options[:guardfile])
|
158
|
-
if File.exist?(options[:guardfile])
|
159
|
-
_read_guardfile(options[:guardfile])
|
160
|
-
::Guard::UI.info "Using Guardfile at #{ options[:guardfile] }."
|
161
|
-
true
|
162
|
-
else
|
163
|
-
::Guard::UI.error "No Guardfile exists at #{ options[:guardfile] }."
|
164
|
-
exit 1
|
165
|
-
end
|
166
|
-
|
167
|
-
true
|
168
|
-
end
|
169
|
-
|
170
|
-
# Try to use one of the default Guardfiles (local or home Guardfile).
|
171
|
-
# Exits Guard if no Guardfile is found.
|
172
|
-
#
|
173
|
-
def _use_default
|
174
|
-
if guardfile_path = _find_default_guardfile
|
175
|
-
@source = :default
|
176
|
-
_read_guardfile(guardfile_path)
|
177
|
-
else
|
178
|
-
::Guard::UI.error \
|
179
|
-
"No Guardfile found, please create one with `guard init`."
|
180
|
-
exit 1
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
# Returns the first default Guardfile (either local or home Guardfile)
|
185
|
-
# or nil otherwise.
|
186
|
-
#
|
187
|
-
def _find_default_guardfile
|
188
|
-
[_local_guardfile_path, _home_guardfile_path].detect do |path|
|
189
|
-
File.exist?(path)
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
# Reads the current `Guardfile` content.
|
194
|
-
#
|
195
|
-
# @param [String] guardfile_path the path to the Guardfile
|
196
|
-
#
|
197
|
-
def _read_guardfile(guardfile_path)
|
198
|
-
@guardfile_path = guardfile_path
|
199
|
-
@guardfile_contents = File.read(guardfile_path)
|
200
|
-
rescue => ex
|
201
|
-
::Guard::UI.error "Error reading file #{ guardfile_path }:"
|
202
|
-
::Guard::UI.error ex.inspect
|
203
|
-
::Guard::UI.error ex.backtrace
|
204
|
-
exit 1
|
205
|
-
end
|
206
|
-
|
207
|
-
# Stops Guard and clear internal state
|
208
|
-
# before the Guardfile will be re-evaluated.
|
209
|
-
#
|
210
|
-
def _before_reevaluate_guardfile
|
211
|
-
::Guard.runner.run(:stop)
|
212
|
-
::Guard.reset_groups
|
213
|
-
::Guard.reset_plugins
|
214
|
-
::Guard.reset_scope
|
215
|
-
::Guard::Notifier.clear_notifiers
|
216
|
-
end
|
217
|
-
|
218
|
-
# Starts Guard and notification and show a message
|
219
|
-
# after the Guardfile has been re-evaluated.
|
220
|
-
#
|
221
|
-
def _after_reevaluate_guardfile
|
222
|
-
::Guard::Notifier.turn_on if ::Guard::Notifier.enabled?
|
223
|
-
|
224
|
-
if !::Guard.send(:_non_builtin_plugins?)
|
225
|
-
::Guard::Notifier.notify(
|
226
|
-
"No plugins found in Guardfile, please add at least one.",
|
227
|
-
title: "Guard re-evaluate",
|
228
|
-
image: :failed)
|
229
|
-
else
|
230
|
-
msg = "Guardfile has been re-evaluated."
|
231
|
-
::Guard::UI.info(msg)
|
232
|
-
::Guard::Notifier.notify(msg, title: "Guard re-evaluate")
|
233
|
-
|
234
|
-
::Guard.setup_scope
|
235
|
-
::Guard.runner.run(:start)
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
# Tests if the current `Guardfile` content is usable.
|
240
|
-
#
|
241
|
-
# @return [Boolean] if the Guardfile is usable
|
242
|
-
#
|
243
|
-
def _guardfile_contents_usable?
|
244
|
-
guardfile_contents && guardfile_contents =~ /guard/m
|
245
|
-
end
|
246
|
-
|
247
|
-
# The path to the `Guardfile` that is located at
|
248
|
-
# the directory, where Guard has been started from.
|
249
|
-
#
|
250
|
-
# @return [String] the path to the local Guardfile
|
251
|
-
#
|
252
|
-
def _local_guardfile_path
|
253
|
-
File.expand_path(File.join(Dir.pwd, "Guardfile"))
|
254
|
-
end
|
255
|
-
|
256
|
-
# The path to the `.Guardfile` that is located at
|
257
|
-
# the users home directory.
|
258
|
-
#
|
259
|
-
# @return [String] the path to `~/.Guardfile`
|
260
|
-
#
|
261
|
-
def _home_guardfile_path
|
262
|
-
File.expand_path(File.join("~", ".Guardfile"))
|
263
|
-
end
|
264
|
-
|
265
|
-
# The path to the user configuration `.guard.rb`
|
266
|
-
# that is located at the users home directory.
|
267
|
-
#
|
268
|
-
# @return [String] the path to `~/.guard.rb`
|
269
|
-
#
|
270
|
-
def _user_config_path
|
271
|
-
File.expand_path(File.join("~", ".guard.rb"))
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|