command_kit 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +18 -3
  3. data/.rubocop.yml +141 -0
  4. data/ChangeLog.md +165 -0
  5. data/Gemfile +3 -0
  6. data/README.md +186 -118
  7. data/Rakefile +3 -2
  8. data/command_kit.gemspec +4 -4
  9. data/examples/command.rb +1 -1
  10. data/gemspec.yml +7 -0
  11. data/lib/command_kit/arguments/argument.rb +2 -2
  12. data/lib/command_kit/arguments.rb +36 -7
  13. data/lib/command_kit/colors.rb +702 -53
  14. data/lib/command_kit/command.rb +2 -3
  15. data/lib/command_kit/commands/auto_load.rb +8 -1
  16. data/lib/command_kit/commands/help.rb +3 -2
  17. data/lib/command_kit/commands/subcommand.rb +1 -1
  18. data/lib/command_kit/commands.rb +24 -9
  19. data/lib/command_kit/env/path.rb +1 -1
  20. data/lib/command_kit/file_utils.rb +46 -0
  21. data/lib/command_kit/help/man.rb +17 -33
  22. data/lib/command_kit/inflector.rb +47 -17
  23. data/lib/command_kit/interactive.rb +9 -0
  24. data/lib/command_kit/main.rb +7 -9
  25. data/lib/command_kit/man.rb +44 -0
  26. data/lib/command_kit/open_app.rb +69 -0
  27. data/lib/command_kit/options/option.rb +41 -27
  28. data/lib/command_kit/options/option_value.rb +3 -2
  29. data/lib/command_kit/options/parser.rb +17 -22
  30. data/lib/command_kit/options.rb +102 -14
  31. data/lib/command_kit/os/linux.rb +157 -0
  32. data/lib/command_kit/os.rb +159 -11
  33. data/lib/command_kit/package_manager.rb +200 -0
  34. data/lib/command_kit/pager.rb +46 -4
  35. data/lib/command_kit/printing/indent.rb +4 -4
  36. data/lib/command_kit/printing.rb +14 -3
  37. data/lib/command_kit/program_name.rb +9 -0
  38. data/lib/command_kit/sudo.rb +40 -0
  39. data/lib/command_kit/terminal.rb +5 -0
  40. data/lib/command_kit/version.rb +1 -1
  41. data/spec/arguments/argument_spec.rb +1 -1
  42. data/spec/arguments_spec.rb +84 -1
  43. data/spec/colors_spec.rb +357 -70
  44. data/spec/command_spec.rb +77 -6
  45. data/spec/commands/auto_load_spec.rb +33 -2
  46. data/spec/commands_spec.rb +101 -29
  47. data/spec/env/path_spec.rb +6 -0
  48. data/spec/exception_handler_spec.rb +1 -1
  49. data/spec/file_utils_spec.rb +59 -0
  50. data/spec/fixtures/template.erb +5 -0
  51. data/spec/help/man_spec.rb +54 -57
  52. data/spec/inflector_spec.rb +70 -8
  53. data/spec/man_spec.rb +46 -0
  54. data/spec/open_app_spec.rb +85 -0
  55. data/spec/options/option_spec.rb +38 -2
  56. data/spec/options/option_value_spec.rb +55 -0
  57. data/spec/options/parser_spec.rb +0 -10
  58. data/spec/options_spec.rb +328 -0
  59. data/spec/os/linux_spec.rb +164 -0
  60. data/spec/os_spec.rb +200 -13
  61. data/spec/package_manager_spec.rb +806 -0
  62. data/spec/pager_spec.rb +71 -6
  63. data/spec/printing/indent_spec.rb +7 -5
  64. data/spec/printing_spec.rb +23 -1
  65. data/spec/program_name_spec.rb +8 -0
  66. data/spec/sudo_spec.rb +51 -0
  67. data/spec/terminal_spec.rb +30 -0
  68. data/spec/usage_spec.rb +1 -1
  69. metadata +23 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acf8c9763694ffe7ac298e158863a3165c5d8f1a2209d1cac5b01e9c60d9dd85
4
- data.tar.gz: 98669568909de27878be028ae8b0251ddc6e8a4740af23037bd234d06778b2ce
3
+ metadata.gz: 306f055fa898d4d82c14ba8e79b397ae413280bb7144ce69e1787081620827e9
4
+ data.tar.gz: e79e640f7d4ae566401e7543d3ba98aa42b1e2396657734e29ab3cd3b383b41c
5
5
  SHA512:
6
- metadata.gz: b04269a04b5d474f2a17724e04fa015fe5c1eefdbba9f53cf06c49c727c369ae3ba9a77e336c09f69fc3e7c8b6e5f77fa98abe7912c022213489d5b04191f5bb
7
- data.tar.gz: 01c43327289df1e30970e618b2d133e26bc5e6cdd3d65cc6fad7cbc369e44085fd164cb0b93a241df6508e3019fbfed658f83191e958457ec6f7ecfed86b88b3
6
+ metadata.gz: ee4268377db8c2398b5157feda9fa106a0b156537c6085b71fcfd8c7710f898c3bc0ef5d4408d9c6cbcae932e4f4ee4dd49070003e6c5734da06da33fbbace9a
7
+ data.tar.gz: 03b6a48369bea030002f9432d0d8645d8c0f5cdefba81778922e73a54f267611419bdb63e5033e98b09aa1c6ae97af1e8c3b8135cb7ed4b807fce666c6c379b8
@@ -3,19 +3,20 @@ name: CI
3
3
  on: [ push, pull_request ]
4
4
 
5
5
  jobs:
6
+ # run tests
6
7
  tests:
7
8
  runs-on: ubuntu-latest
8
9
  strategy:
9
10
  fail-fast: false
10
11
  matrix:
11
12
  ruby:
12
- # - 2.4
13
- # - 2.5
14
- # - 2.6
15
13
  - 2.7
16
14
  - 3.0
15
+ - 3.1
17
16
  # TODO: uncomment when jruby supports ruby >= 2.7
18
17
  # - jruby
18
+ # TODO: uncomment when truffleruby supports splatting empty kwargs
19
+ # - truffleruby
19
20
  name: Ruby ${{ matrix.ruby }}
20
21
  steps:
21
22
  - uses: actions/checkout@v2
@@ -27,3 +28,17 @@ jobs:
27
28
  run: bundle install --jobs 4 --retry 3
28
29
  - name: Run tests
29
30
  run: bundle exec rake test
31
+
32
+ # rubocop linting
33
+ rubocop:
34
+ runs-on: ubuntu-latest
35
+ steps:
36
+ - uses: actions/checkout@v2
37
+ - name: Set up Ruby
38
+ uses: ruby/setup-ruby@v1
39
+ with:
40
+ ruby-version: 2.7
41
+ - name: Install dependencies
42
+ run: bundle install --jobs 4 --retry 3
43
+ - name: Run rubocop
44
+ run: bundle exec rubocop --parallel
data/.rubocop.yml ADDED
@@ -0,0 +1,141 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ SuggestExtensions: false
4
+ TargetRubyVersion: 2.7
5
+
6
+ #
7
+ # our rules
8
+ #
9
+
10
+ Layout/FirstArrayElementIndentation: { Exclude: ['spec/**/*'] }
11
+ Layout/LineLength: { Enabled: false }
12
+ Layout/SpaceAroundEqualsInParameterDefault: { EnforcedStyle: no_space }
13
+ Lint/ConstantDefinitionInBlock: { Exclude: ['spec/**/*'] }
14
+ Metrics: { Enabled: false }
15
+ Style/SymbolArray: { EnforcedStyle: brackets }
16
+ Style/IfInsideElse: { Enabled: false } # Offense count: 1
17
+ Style/PercentLiteralDelimiters:
18
+ Enabled: true
19
+ PreferredDelimiters:
20
+ default: '{}'
21
+ '%i': '[]'
22
+ '%I': '[]'
23
+ '%w': '[]'
24
+ '%W': '[]'
25
+
26
+ #
27
+ # rules that are in flux
28
+ #
29
+
30
+ # consider enabling these and autocorrecting?
31
+ # Layout/SpaceAfterComma
32
+ # Layout/SpaceAroundKeyword
33
+ # Layout/SpaceBeforeComma
34
+ # Layout/SpaceInsideHashLiteralBraces
35
+ # Layout/SpaceInsideParens
36
+ # Layout/TrailingWhitespace
37
+ # Lint/UnreachableLoop
38
+ # Lint/UnusedBlockArgument
39
+ # Style/ClassCheck
40
+ # Style/Documentation
41
+ # Style/ExpandPathArguments
42
+ # Style/GlobalStdStream
43
+ # Style/HashSyntax
44
+ # Style/KeywordParametersOrder
45
+ # Style/MethodCallWithoutArgsParentheses
46
+ # Style/MutableConstant
47
+ # Style/QuotedSymbols: { EnforcedStyle: double_quotes }
48
+ # Style/RedundantReturn
49
+ # Style/SafeNavigation
50
+ # Style/SpecialGlobalVars
51
+ # Style/StringLiterals: { EnforcedStyle: double_quotes }
52
+ # Style/WordArray
53
+
54
+ # these have been fixed
55
+ # Gemspec/DuplicatedAssignment: { Enabled: false } # Offense count: 1
56
+ # Layout/ElseAlignment: { Enabled: false } # Offense count: 1
57
+ # Layout/EndAlignment: { Enabled: false } # Offense count: 1
58
+ # Lint/DuplicateMethods: { Enabled: false } # Offense count: 1
59
+ # Lint/UselessAssignment: { Enabled: false } # Offense count: 1
60
+ # Style/Encoding: { Enabled: false } # Offense count: 2
61
+ # Style/RedundantBegin: { Enabled: false } # Offense count: 2
62
+ # Style/RedundantInterpolation: { Enabled: false } # Offense count: 1
63
+ # Style/TrailingCommaInArrayLiteral: { Enabled: false } # Offense count: 1
64
+
65
+ #
66
+ # This list was generated with:
67
+ # bundle exec rubocop --auto-gen-config --exclude-limit 1
68
+ #
69
+
70
+ # > 10 violations
71
+ Layout/AssignmentIndentation: { Enabled: false } # Offense count: 11
72
+ Layout/EmptyLinesAroundClassBody: { Enabled: false } # Offense count: 76
73
+ Layout/HashAlignment: { Enabled: false } # Offense count: 28
74
+ Layout/SpaceAfterComma: { Enabled: false } # Offense count: 141
75
+ Layout/SpaceInsideHashLiteralBraces: { Enabled: false } # Offense count: 57
76
+ Layout/TrailingWhitespace: { Enabled: false } # Offense count: 50
77
+ Naming/RescuedExceptionsVariableName: { Enabled: false } # Offense count: 11
78
+ Style/BlockDelimiters: { Enabled: false } # Offense count: 17
79
+ Style/ClassCheck: { Enabled: false } # Offense count: 10
80
+ Style/ClassEqualityComparison: { Enabled: false } # Offense count: 16
81
+ Style/FrozenStringLiteralComment: { Enabled: false } # Offense count: 77
82
+ Style/GlobalStdStream: { Enabled: false } # Offense count: 13
83
+ Style/GuardClause: { Enabled: false } # Offense count: 10
84
+ Style/IfUnlessModifier: { Enabled: false } # Offense count: 13
85
+ Style/MethodCallWithoutArgsParentheses: { Enabled: false } # Offense count: 10
86
+ Style/SpecialGlobalVars: { Enabled: false } # Offense count: 28
87
+ Style/StringLiterals: { Enabled: false } # Offense count: 774
88
+ Lint/ElseLayout: { Enabled: false } # Offense count: 22
89
+
90
+ # < 10 violations
91
+ Layout/EmptyLinesAroundModuleBody: { Enabled: false } # Offense count: 5
92
+ Layout/ExtraSpacing: { Enabled: false } # Offense count: 6
93
+ Layout/FirstHashElementIndentation: { Enabled: false } # Offense count: 4
94
+ Layout/ParameterAlignment: { Enabled: false } # Offense count: 9
95
+ Layout/SpaceAroundKeyword: { Enabled: false } # Offense count: 7
96
+ Layout/SpaceBeforeComma: { Enabled: false } # Offense count: 4
97
+ Layout/SpaceInsideParens: { Enabled: false } # Offense count: 4
98
+ Lint/EmptyClass: { Enabled: false } # Offense count: 3
99
+ Lint/SuppressedException: { Enabled: false } # Offense count: 4
100
+ Lint/UnusedMethodArgument: { Enabled: false } # Offense count: 5
101
+ Style/AccessorGrouping: { Enabled: false } # Offense count: 7
102
+ Style/Documentation: { Enabled: false } # Offense count: 3
103
+ Style/ExpandPathArguments: { Enabled: false } # Offense count: 8
104
+ Style/HashSyntax: { Exclude: ['Rakefile'] } # Offense count: 3
105
+ Style/KeywordParametersOrder: { Enabled: false } # Offense count: 8
106
+ Style/Lambda: { Enabled: false } # Offense count: 3
107
+ Style/MutableConstant: { Enabled: false } # Offense count: 4
108
+ Style/RaiseArgs: { Enabled: false } # Offense count: 4
109
+ Style/RedundantReturn: { Enabled: false } # Offense count: 7
110
+ Style/SafeNavigation: { Enabled: false } # Offense count: 5
111
+ Style/StringConcatenation: { Enabled: false } # Offense count: 8
112
+ Style/WordArray: { Enabled: false } # Offense count: 4
113
+
114
+ # 1 or 2 violations
115
+ Layout/ArgumentAlignment: { Enabled: false } # Offense count: 1
116
+ Layout/BlockAlignment: { Enabled: false } # Offense count: 1
117
+ Layout/IndentationWidth: { Enabled: false } # Offense count: 2
118
+ Layout/SpaceAroundOperators: { Enabled: false } # Offense count: 1
119
+ Layout/SpaceBeforeBlockBraces: { Enabled: false } # Offense count: 1
120
+ Lint/MissingSuper: { Enabled: false } # Offense count: 2
121
+ Lint/RescueException: { Enabled: false } # Offense count: 1
122
+ Lint/UnreachableLoop: { Enabled: false } # Offense count: 1
123
+ Lint/UnusedBlockArgument: { Enabled: false } # Offense count: 1
124
+ Naming/MethodParameterName: { Enabled: false } # Offense count: 1
125
+ Style/EmptyMethod: { Enabled: false } # Offense count: 2
126
+ Style/HashConversion: { Enabled: false } # Offense count: 1
127
+ Style/MultilineMemoization: { Enabled: false } # Offense count: 1
128
+ Style/NumericPredicate: { Enabled: false } # Offense count: 1
129
+ Style/OptionalArguments: { Enabled: false } # Offense count: 1
130
+ Style/ParenthesesAroundCondition: { Enabled: false } # Offense count: 1
131
+ Style/PreferredHashMethods: { Enabled: false } # Offense count: 1
132
+ Style/QuotedSymbols: { Enabled: false } # Offense count: 1
133
+ Style/RedundantException: { Enabled: false } # Offense count: 1
134
+ Style/RedundantRegexpEscape: { Enabled: false } # Offense count: 1
135
+ Style/RegexpLiteral: { Enabled: false } # Offense count: 1
136
+ Style/RescueStandardError: { Enabled: false } # Offense count: 1
137
+ Style/SoleNestedConditional: { Enabled: false } # Offense count: 1
138
+ Style/TrailingCommaInHashLiteral: { Enabled: false } # Offense count: 2
139
+
140
+ # rubocop cannot tell that rubygems_mfa_required is enabled in gemspec.yml
141
+ Gemspec/RequireMFA: { Enabled: false }
data/ChangeLog.md CHANGED
@@ -1,3 +1,167 @@
1
+ ### 0.3.0 / 2021-12-26
2
+
3
+ * Added {CommandKit::FileUtils}.
4
+
5
+ #### CommandKit::FileUtils
6
+
7
+ * Added {CommandKit::FileUtils#erb #erb}.
8
+
9
+ #### CommandKit::Colors
10
+
11
+ * Added {CommandKit::Colors::ANSI::RESET_FG RESET_FG}.
12
+ * Added {CommandKit::Colors::ANSI.bright_black bright_black}.
13
+ * Added {CommandKit::Colors::ANSI.gray gray}.
14
+ * Added {CommandKit::Colors::ANSI.bright_red bright_red}.
15
+ * Added {CommandKit::Colors::ANSI.bright_green bright_green}.
16
+ * Added {CommandKit::Colors::ANSI.bright_yellow bright_yellow}.
17
+ * Added {CommandKit::Colors::ANSI.bright_blue bright_blue}.
18
+ * Added {CommandKit::Colors::ANSI.bright_magenta bright_magenta}.
19
+ * Added {CommandKit::Colors::ANSI.bright_cyan bright_cyan}.
20
+ * Added {CommandKit::Colors::ANSI.bright_white bright_white}.
21
+ * Added {CommandKit::Colors::ANSI.on_bright_black on_bright_black}.
22
+ * Added {CommandKit::Colors::ANSI.on_gray on_gray}.
23
+ * Added {CommandKit::Colors::ANSI.on_bright_red on_bright_red}.
24
+ * Added {CommandKit::Colors::ANSI.on_bright_green on_bright_green}.
25
+ * Added {CommandKit::Colors::ANSI.on_bright_yellow on_bright_yellow}.
26
+ * Added {CommandKit::Colors::ANSI.on_bright_blue on_bright_blue}.
27
+ * Added {CommandKit::Colors::ANSI.on_bright_magenta on_bright_magenta}.
28
+ * Added {CommandKit::Colors::ANSI.on_bright_cyan on_bright_cyan}.
29
+ * Added {CommandKit::Colors::ANSI.on_bright_white on_bright_white}.
30
+
31
+ #### ComandKit::Options
32
+
33
+ * Allow grouping options into categories:
34
+
35
+ option :opt1, category: 'Foo Options',
36
+ desc: 'Option 1'
37
+
38
+ option :opt2, category: 'Foo Options',
39
+ desc: 'Option 1'
40
+
41
+ * Allow options to have multi-line descriptions:
42
+
43
+ option :opt1, short: '-o',
44
+ desc: [
45
+ 'line1',
46
+ 'line2',
47
+ '...'
48
+ ]
49
+
50
+ #### CommandKit::Arguments
51
+
52
+ * Allow arguments to have multi-line descriptions:
53
+
54
+ argument :arg1, desc: [
55
+ 'line1',
56
+ 'line2',
57
+ '...'
58
+ ]
59
+
60
+
61
+ #### CommandKit::ProgramName
62
+
63
+ * Added {CommandKit::ProgramName#command_name}.
64
+
65
+ ### 0.2.2 / 2021-12-26
66
+
67
+ #### CommandKit::Help::Man
68
+
69
+ * Raise a `NotImplementedError` exception in {CommandKit::Help::Man#help_man
70
+ #help_man} if {CommandKit::Help::Man::ClassMethods#man_dir .man_dir} was not
71
+ set.
72
+
73
+ ### 0.2.1 / 2021-11-16
74
+
75
+ * Ensure that all error messages end with a period.
76
+ * Documentation fixes.
77
+ * Opt-in to [rubygem.org MFA requirement](https://guides.rubygems.org/mfa-requirement-opt-in/).
78
+
79
+ #### CommandKit::Printing
80
+
81
+ * Auto-detect whether {CommandKit::CommandName#command_name #command_name} is
82
+ available, and if so, prepend the command name to all error messages.
83
+
84
+ #### CommandKit::Help::Man
85
+
86
+ * Expand the path given to
87
+ {CommandKit::Help::Man::ClassMethods#man_dir man_dir}.
88
+ * If {CommandKit::Help::Man::ClassMethods#man_dir man_dir} is not set, fallback
89
+ to regular `--help` output.
90
+
91
+ #### CommandKit::Arguments
92
+
93
+ * Include {CommandKit::Usage} and {CommandKit::Printing} into
94
+ {CommandKit::Arguments}.
95
+
96
+ #### CommandKit::Options
97
+
98
+ * Include {CommandKit::Arguments} into {CommandKit::Options}.
99
+ * Ensure that {CommandKit::Options::Parser#main} runs before
100
+ {CommandKit::Arguments#main}.
101
+ * Ensure that {CommandKit::Options#help} also calls
102
+ {CommandKit::Arguments#help_arguments}.
103
+ * Always prepopulate {CommandKit::Options#options #options} with option's
104
+ default values.
105
+ * Note: if an option has a default value but the option's value is not
106
+ required (ex: `value: {required: false, default: "foo"}`), and the option's
107
+ flag is given but no value is given (ex: `--option-flag --some-other-flag`),
108
+ the option's value in {CommandKit::Options#options #options} will be `nil`
109
+ _not_ the option's default value (`"foo"`). This helps indicate that the
110
+ option's flag was given but no value was given with it.
111
+
112
+ #### CommandKit::Options::OptionValue
113
+
114
+ * When a `Class` is passed to {CommandKit::Options::OptionValue.default_usage},
115
+ demodularize the class name before converting it to underscored/uppercase.
116
+
117
+ #### CommandKit::Command
118
+
119
+ * Fixed the inclusion order of {CommandKit::Options} and
120
+ {CommandKit::Arguments}.
121
+
122
+ #### CommandKit::Commands
123
+
124
+ * Define the `COMMAND` and `ARGS` arguments.
125
+ * Correctly duplicate the {CommandKit::Env#env env} (which can be either `ENV`
126
+ or a `Hash`) to work on ruby-3.1.0-preview1.
127
+ * Print command aliases that were set explicitly
128
+ (ex: `command_aliases['rm'] = 'remove'`) in {CommandKit::Commands#help}.
129
+ * Print help and exit with status `1` if no command is given. This matches the
130
+ behavior of the `git` command.
131
+
132
+ #### CommandKit::Commands::AutoLoad
133
+
134
+ * Ensure that any explicit command aliases are added to the command's
135
+ {CommandKit::Commands::ClassMethods#command_aliases command_aliases}.
136
+
137
+ ### 0.2.0 / 2021-08-31
138
+
139
+ * Added {CommandKit::Colors::ANSI#on_black}.
140
+ * Added {CommandKit::Colors::ANSI#on_red}.
141
+ * Added {CommandKit::Colors::ANSI#on_green}.
142
+ * Added {CommandKit::Colors::ANSI#on_yellow}.
143
+ * Added {CommandKit::Colors::ANSI#on_blue}.
144
+ * Added {CommandKit::Colors::ANSI#on_magenta}.
145
+ * Added {CommandKit::Colors::ANSI#on_cyan}.
146
+ * Added {CommandKit::Colors::ANSI#on_white}.
147
+ * Added {CommandKit::Man}.
148
+ * Added {CommandKit::OS#bsd?}.
149
+ * Added {CommandKit::OS#freebsd?}.
150
+ * Added {CommandKit::OS#netbsd?}.
151
+ * Added {CommandKit::OS#openbsd?}.
152
+ * Added {CommandKit::OS#os}.
153
+ * Added {CommandKit::OS#unix?}.
154
+ * Added {CommandKit::OS::Linux}.
155
+ * Added {CommandKit::OpenApp}.
156
+ * Added {CommandKit::PackageManager}.
157
+ * Added {CommandKit::Pager#pipe_to_pager}.
158
+ * Added {CommandKit::Sudo}.
159
+ * Added {CommandKit::Terminal#tty?}.
160
+ * Refactor {CommandKit::Inflector.camelize} and
161
+ {CommandKit::Inflector.underscore} to use StringScanner.
162
+ * Allow {CommandKit::OS#initialize} to accept an `os:` keyword to override the
163
+ detected OS.
164
+
1
165
  ### 0.1.0 / 2021-07-16
2
166
 
3
167
  * Initial release:
@@ -21,6 +185,7 @@
21
185
  * {CommandKit::Options}
22
186
  * {CommandKit::Options::Quiet}
23
187
  * {CommandKit::Options::Verbose}
188
+ * {CommandKit::OS}
24
189
  * {CommandKit::Pager}
25
190
  * {CommandKit::Printing}
26
191
  * {CommandKit::Printing::Indent}
data/Gemfile CHANGED
@@ -6,9 +6,12 @@ group :development do
6
6
  gem 'rake'
7
7
  gem 'rubygems-tasks', '~> 0.2'
8
8
 
9
+ gem 'rubocop', '~> 1.18'
10
+
9
11
  gem 'rspec', '~> 3.0'
10
12
  gem 'simplecov', '~> 0.20', require: false
11
13
 
12
14
  gem 'kramdown'
13
15
  gem 'yard', '~> 0.9'
16
+ gem 'yard-spellcheck', require: false
14
17
  end