tty-exit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 90291ac39f6262d62023d9466a8f79edca9b001072c68cb60799ea45d462bf02
4
+ data.tar.gz: f9c7422bedb2eef073fe21636842a8e60914497fb2800ad1d14819a8da29b600
5
+ SHA512:
6
+ metadata.gz: bbfc7bd556613417a2ee20411033040ad438cfde2bec149435d46e7541b81aa9e5ee31d4dc3045b5410c4e5fb86db0baa1cd359de933e95a1c97631a8550c64f
7
+ data.tar.gz: 11a3cc9803ca5b1ac3eac8f2eaf5e3e4648e87c20eaac5854855e0e4fb0dd7961cccda02bfcb3ef49ec96d96b97ad7777a64ef1055948afa344bcd78ed7d755a
@@ -0,0 +1,7 @@
1
+ # Change log
2
+
3
+ ## [v0.1.0] - 2020-01-xx
4
+
5
+ * Initial implementation and release
6
+
7
+ [v0.1.0]: https://github.com/piotrmurach/tty-exit/compare/v0.1.0
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Piotr Murach
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,297 @@
1
+ <div align="center">
2
+ <a href="https://piotrmurach.github.io/tty" target="_blank"><img width="130" src="https://cdn.rawgit.com/piotrmurach/tty/master/images/tty.png" alt="tty logo" /></a>
3
+ </div>
4
+
5
+ # TTY::Exit [![Gitter](https://badges.gitter.im/Join%20Chat.svg)][gitter]
6
+
7
+ [![Gem Version](https://badge.fury.io/rb/tty-exit.svg)][gem]
8
+ [![Build Status](https://secure.travis-ci.org/piotrmurach/tty-exit.svg?branch=master)][travis]
9
+ [![Build status](https://ci.appveyor.com/api/projects/status/rtm3po27ouarfrhf?svg=true)][appveyor]
10
+ [![Code Climate](https://codeclimate.com/github/piotrmurach/tty-exit/badges/gpa.svg)][codeclimate]
11
+ [![Coverage Status](https://coveralls.io/repos/github/piotrmurach/tty-exit/badge.svg)][coverage]
12
+ [![Inline docs](http://inch-ci.org/github/piotrmurach/tty-exit.svg?branch=master)][inchpages]
13
+
14
+ [gitter]: https://gitter.im/piotrmurach/tty
15
+ [gem]: http://badge.fury.io/rb/tty-exit
16
+ [travis]: http://travis-ci.org/piotrmurach/tty-exit
17
+ [appveyor]: https://ci.appveyor.com/project/piotrmurach/tty-exit
18
+ [codeclimate]: https://codeclimate.com/github/piotrmurach/tty-exit
19
+ [coverage]: https://coveralls.io/github/piotrmurach/tty-exit
20
+ [inchpages]: http://inch-ci.org/github/piotrmurach/tty-exit
21
+
22
+ > Terminal exit codes for humans and machines.
23
+
24
+ The goal of this library is to provide human friendly and standard way to use exit status codes in command line applications. Instead of saying `exit(64)`, you can say `exit_with(:usage_error)`. Both indicate a failure to the parent process but the `:usage_error` is so much nicer! Wouldn't you agree? That's why `tty-exit` gathers a list of all the most common exit codes as used by POSIX-compliant tools on different Unix systems for you to use.
25
+
26
+ The exit statuses range from 0 to 255 (inclusive). Any other exit status than 0 indicates a failure of some kind. The exit codes in the range 64-78 are adapted from the OpenBSD [sysexits.h](https://man.openbsd.org/sysexits.3). The codes between 125 and 128 are reserved for shell statuses as defined in [Advanced Bash Scripting Guide, Appendix E](http://tldp.org/LDP/abs/html/exitcodes.html). The codes in the 129-154 range correspond with the fatal signals as defined in [signal](https://man.openbsd.org/signal.3).
27
+
28
+ **TTY::Exit** provides independent terminal exit codes component for [TTY](https://github.com/piotrmurach/tty) toolkit.
29
+
30
+ ## Installation
31
+
32
+ Add this line to your application's Gemfile:
33
+
34
+ ```ruby
35
+ gem 'tty-exit'
36
+ ```
37
+
38
+ And then execute:
39
+
40
+ $ bundle install
41
+
42
+ Or install it yourself as:
43
+
44
+ $ gem install tty-exit
45
+
46
+ ## Contents
47
+
48
+ * [1. Usage](#1-usage)
49
+ * [2. API](#2-api)
50
+ * [2.1 exit_code](#21-exit_code)
51
+ * [2.2 exit_message](#22-exit_message)
52
+ * [2.3 exit_with](#23-exit_with)
53
+ * [2.4 register_exit](#24-register_exit)
54
+ * [2.5 exit_reserved?](#25-exit_reserved)
55
+ * [2.6 exit_valid?](#26-exit_valid)
56
+ * [2.7 exit_success?](#27-exit_success)
57
+ * [2.8 exit_codes](#28-exit_codes)
58
+ * [2.9 exit_messages](#29-exit_messages)
59
+
60
+ ## 1. Usage
61
+
62
+ To exit from any program use `exit_with` method. Instead of a number, you can use a readable name for the exit status:
63
+
64
+ ```ruby
65
+ TTY::Exit.exit_with(:usage_error)
66
+ ```
67
+
68
+ The above will exit program immediately with an exit code indicating a failure:
69
+
70
+ ```ruby
71
+ puts $?.exitstatus
72
+ # => 64
73
+ ```
74
+
75
+ All the reserved exit statuses have a matching exit message. To display a default message, as a second argument to `exit_with` you can pass `:default` value:
76
+
77
+ ```ruby
78
+ TTY::Exit.exit_with(:usage_error, :default)
79
+ ```
80
+
81
+ That will produce the following user friendly message:
82
+
83
+ ```ruby
84
+ # => "ERROR(64): Command line usage error"
85
+ ```
86
+
87
+ The preferred way is to include **TTY::Exit** module in your code:
88
+
89
+ ```ruby
90
+ class Command
91
+ include TTY::Exit
92
+
93
+ def execute
94
+ exit_with(:config_error, :default)
95
+ end
96
+ end
97
+ ```
98
+
99
+ This will print an error message and return appropriate exit status:
100
+
101
+ ```ruby
102
+ cmd = Command.new
103
+ cmd.execute
104
+ # => "ERROR(78): Configuration Error"
105
+ puts $?.exitstatus
106
+ # => 78
107
+ ```
108
+
109
+ To see the full list of reserved exit codes go to [2.8 exit_codes](#28-exit-codes) section.
110
+
111
+ ## 2. API
112
+
113
+ ### 2.1 exit_code
114
+
115
+ There are many built-in exit codes that can be referenced using a name.
116
+
117
+ For example to return an exit code denoting success, you can use `:ok` or `:success`:
118
+
119
+ ```ruby
120
+ TTY::Exit.exit_code(:ok) # => 0
121
+ TTY::Exit.exit_code(:success) # => 0
122
+ ```
123
+
124
+ Any other exit status than 0 indicates a failure of some kind. For example, when a command cannot be found use `:not_found`:
125
+
126
+ ```ruby
127
+ TTY::Exit.exit_code(:not_found)
128
+ # => 127
129
+ ```
130
+
131
+ You can also use an exit code directly:
132
+
133
+ ```ruby
134
+ TTY::Exit.exit_code(127)
135
+ # => 127
136
+ ```
137
+
138
+ ### 2.2 exit_message
139
+
140
+ One of the downsides of exit codes is that they are not very communicative to the user. Why not have both? An exit code and a user friendly message. That's what `exit_message` is for. All the reserved exit codes have corresponding user friendly messages.
141
+
142
+ For example, when returning exit code `64` for usage error:
143
+
144
+ ```ruby
145
+ TTY::Exit.exit_message(:usage_error)
146
+ TTY::Exit.exit_message(64)
147
+ ```
148
+
149
+ Will return:
150
+
151
+ ```ruby
152
+ # => "ERROR(64): Command line usage error"
153
+ ```
154
+
155
+ The default messages are used by the `exit_with` method and can be overwritten by a custom one.
156
+
157
+ ### 2.3 exit_with
158
+
159
+ To exit program with an exit code use `exit_with`. This method accepts a name or a code for the exit status.
160
+
161
+ ```ruby
162
+ TTY::Exit.exit_with(:usage_error)
163
+ TTY::Exit.exit_with(64)
164
+ ```
165
+
166
+ Both will produce the same outcome.
167
+
168
+ As a second argument you can specify a user friendly message to be printed to `stderr` before exit. To use predefined messages use `:default` as a value:
169
+
170
+ ```ruby
171
+ TTY::Exit.exit_with(:usage_error, :default)
172
+ # => "ERROR(64): Command line usage error"
173
+ ```
174
+
175
+ Optionally, you can provide a custom message to display to the user.
176
+
177
+ ```ruby
178
+ TTY::Exit.exit_with(:usge_error, "Wrong arguments")
179
+ # => "Wrong arguments"
180
+ ```
181
+
182
+ Finally, you can redirect output to a different stream using `:io` option. By default, message is printed to `stderr`:
183
+
184
+ ```ruby
185
+ TTY::Exit.exit_with(:usage_error, io: $stdout)
186
+ ```
187
+
188
+ Since `TTY::Exit` is a module, you can include it in your code to get access to all the methods:
189
+
190
+ ```ruby
191
+ class Command
192
+ include TTY::Exit
193
+
194
+ def execute
195
+ exit_with(:usage_error, :default)
196
+ end
197
+ end
198
+ ```
199
+
200
+ ### 2.4 register_exit
201
+
202
+ If the provided exit codes don't match your needs, you can add your own using the `register_exit` method.
203
+
204
+ For example, to register a custom exit with `:too_long` name and the status `7` that will notify user and programs about too many arguments do:
205
+
206
+ ```ruby
207
+ class Command
208
+ include TTY::Exit
209
+
210
+ register_exit(:too_long, 7, "Argument list too long")
211
+
212
+ def execute
213
+ exit_with(:too_long, :default)
214
+ end
215
+ end
216
+ ```
217
+
218
+ Then when the command gets run:
219
+
220
+ ```ruby
221
+ cmd = Command.new
222
+ cmd.execute
223
+ # =>
224
+ # ERROR(7): Argument list too long
225
+ ```
226
+
227
+ ### 2.5 exit_reserved?
228
+
229
+ To check if an exit code is already reserved by Unix system use `exit_reserved?`. This is useful in situations where you want to add it your command line application custom exit codes. The check accepts only integer numbers in range 0 to 255 inclusive:
230
+
231
+ ```ruby
232
+ TTY::Exit.exit_reserved?(126) # => true
233
+ TTY::Exit.exit_reserved?(100) # => false
234
+ ```
235
+
236
+ ### 2.6 exit_valid?
237
+
238
+ The exit statuses range from 0 to 255 (inclusive). The `exit_valid?` method helps you check if an exit status is within the range or not.
239
+
240
+ ```ruby
241
+ TTY::Exit.exit_valid?(11) # => true
242
+ TTY::Exit.exit_valid?(522) # => false
243
+ ```
244
+
245
+ ### 2.7 exit_success?
246
+
247
+ Any other exit status than 0 indicates a failure of some kind. The `exit_success?` is a more descriptive way to determine if a program succeeded or not.
248
+
249
+ ```ruby
250
+ TTY::Exit.exit_success?(0) # => true
251
+ TTY::Exit.exit_success?(7) # => false
252
+ ```
253
+
254
+ ### 2.8 exit_codes
255
+
256
+ You can access all the predefined exit codes and their names with `exit_codes` method:
257
+
258
+ ```ruby
259
+ TTY::Exit.exit_codes
260
+ # =>
261
+ # "{:ok=>0, :success=>0, :error=>1, :shell_misuse=>2, :usage_error=>64, :data_error=>65, ... }"
262
+ ```
263
+
264
+ ### 2.9 exit_messages
265
+
266
+ To see what default messages are for the predefined exit codes use `exit_messages`:
267
+
268
+ ```ruby
269
+ TTY::Exit.exit_messages
270
+ # =>
271
+ # "{0=>"Successful termination", 1=>"An error occurred", 2=>"Misuse of shell builtins", 64=>"Command line usage error", ... }"
272
+ ```
273
+
274
+ The exit statuses range from 0 to 255 (inclusive). Any other exit status than 0 indicates a failure of some kind. The exit codes in the range 64-78 are adapted from the OpenBSD [sysexits.h](https://man.openbsd.org/sysexits.3). The codes between 125 and 128 are reserved for shell statuses as defined in [Advanced Bash Scripting Guide, Appendix E](http://tldp.org/LDP/abs/html/exitcodes.html). The codes in the 129-154 range correspond with the fatal signals as defined in [signal](https://man.openbsd.org/signal.3).
275
+
276
+
277
+ ## Development
278
+
279
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
280
+
281
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
282
+
283
+ ## Contributing
284
+
285
+ Bug reports and pull requests are welcome on GitHub at https://github.com/piotrmurach/tty-exit. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/piotrmurach/tty-exit/blob/master/CODE_OF_CONDUCT.md).
286
+
287
+ ## License
288
+
289
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
290
+
291
+ ## Code of Conduct
292
+
293
+ Everyone interacting in the TTY::Exit project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/piotrmurach/tty-exit/blob/master/CODE_OF_CONDUCT.md).
294
+
295
+ ## Copyright
296
+
297
+ Copyright (c) 2020 Piotr Murach. See LICENSE for further details.
@@ -0,0 +1 @@
1
+ require_relative "tty/exit"
@@ -0,0 +1,225 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "exit/code"
4
+ require_relative "exit/registry"
5
+ require_relative "exit/version"
6
+
7
+ module TTY
8
+ # Terminal exit codes for humans and machines
9
+ module Exit
10
+ extend self
11
+
12
+ Error = Class.new(StandardError)
13
+
14
+ # @api private
15
+ def self.included(base)
16
+ base.instance_eval do
17
+ def register_exit(*args)
18
+ Registry.register_exit(*args)
19
+ end
20
+ end
21
+ end
22
+
23
+ NAME_TO_EXIT_CODE = {
24
+ ok: Code::SUCCESS,
25
+ success: Code::SUCCESS,
26
+ error: Code::ERROR,
27
+ shell_misuse: Code::SHELL_MISUSE,
28
+
29
+ usage_error: Code::USAGE_ERROR,
30
+ data_err: Code::DATA_ERROR,
31
+ data_error: Code::DATA_ERROR,
32
+ no_input: Code::NO_INPUT,
33
+ no_user: Code::NO_USER,
34
+ no_host: Code::NO_HOST,
35
+ service_unavailable: Code::SERVICE_UNAVAILABLE,
36
+ software_error: Code::SOFTWARE_ERROR,
37
+ system_error: Code::SYSTEM_ERROR,
38
+ system_file_missing: Code::SYSTEM_FILE_MISSING,
39
+ cant_create: Code::CANT_CREATE,
40
+ io_error: Code::IO_ERROR,
41
+ io_err: Code::IO_ERROR,
42
+ temp_fail: Code::TEMP_FAIL,
43
+ protocol: Code::PROTOCOL,
44
+ no_perm: Code::NO_PERM,
45
+ no_permission: Code::NO_PERM,
46
+ config_error: Code::CONFIG_ERROR,
47
+ configuration_error: Code::CONFIG_ERROR,
48
+
49
+ cannot_execute: Code::CANNOT_EXECUTE,
50
+ not_found: Code::COMMAND_NOT_FOUND,
51
+ command_not_found: Code::COMMAND_NOT_FOUND,
52
+ invalid_argument: Code::INVALID_ARGUMENT,
53
+
54
+ hangup: Code::HANGUP,
55
+ interrupt: Code::INTERRUPT,
56
+ quit: Code::QUIT,
57
+ illegal_instruction: Code::ILLEGAL_INSTRUCTION,
58
+ trace_trap: Code::TRACE_TRAP,
59
+ abort: Code::ABORT,
60
+ kill: Code::KILL,
61
+ bus_error: Code::BUS_ERROR,
62
+ memory_error: Code::MEMORY_ERROR,
63
+ segmentation_fault: Code::MEMORY_ERROR,
64
+ pipe: Code::PIPE,
65
+ alarm: Code::ALARM,
66
+ user1: Code::USER1,
67
+ user2: Code::USER2
68
+ }.freeze
69
+ private_constant :NAME_TO_EXIT_CODE
70
+
71
+ CODE_TO_EXIT_MESSAGE = {
72
+ Code::SUCCESS => "Successful termination",
73
+ Code::ERROR => "An error occurred",
74
+ Code::SHELL_MISUSE => "Misuse of shell builtins",
75
+
76
+ Code::USAGE_ERROR => "Command line usage error",
77
+ Code::DATA_ERROR => "Data format error",
78
+ Code::NO_INPUT => "Cannot open input",
79
+ Code::NO_USER => "User name unknown",
80
+ Code::NO_HOST => "Host name unknown",
81
+ Code::SERVICE_UNAVAILABLE => "Service unavailable",
82
+ Code::SOFTWARE_ERROR => "Internal software error",
83
+ Code::SYSTEM_ERROR => "System error (e.g. can't fork)",
84
+ Code::SYSTEM_FILE_MISSING => "Critical OS file missing",
85
+ Code::CANT_CREATE => "Can't create user output file",
86
+ Code::IO_ERROR => "Input/output error",
87
+ Code::TEMP_FAIL => "Temp failure, user is invited to retry",
88
+ Code::PROTOCOL => "Remote error in protocol",
89
+ Code::NO_PERM => "Permission denied",
90
+ Code::CONFIG_ERROR => "Configuration error",
91
+
92
+ Code::CANNOT_EXECUTE => "Command invoked cannot execute",
93
+ Code::COMMAND_NOT_FOUND => "Command not found",
94
+ Code::INVALID_ARGUMENT => "Invalid argument",
95
+
96
+ Code::HANGUP => "Hangup detected on controlling terminal or death of controlling process.",
97
+ Code::INTERRUPT => "Interrupted by Control-C",
98
+ Code::QUIT => "Quit program",
99
+ Code::ILLEGAL_INSTRUCTION => "Illegal instruction",
100
+ Code::TRACE_TRAP => "Trace/breakpoint trap",
101
+ Code::ABORT => "Abort program",
102
+ Code::KILL => "Kill program",
103
+ Code::BUS_ERROR => "Access to an undefined portion of a memory object",
104
+ Code::MEMORY_ERROR => "An invalid virtual memory reference or segmentation fault",
105
+ Code::PIPE => "Write on a pipe with no one to read it",
106
+ Code::ALARM => "Alarm clock",
107
+ Code::USER1 => "User-defined signal 1",
108
+ Code::USER2 => "User-defined signal 2"
109
+ }.freeze
110
+ private_constant :CODE_TO_EXIT_MESSAGE
111
+
112
+ # Check if an exit code is valid, that it's within the 0-255 (inclusive)
113
+ #
114
+ # @param [Integer] code
115
+ # the code to check
116
+ #
117
+ # @return [Boolean]
118
+ #
119
+ # @api public
120
+ def exit_valid?(code)
121
+ code >= 0 && code <= 255
122
+ end
123
+
124
+ # Check if an exit code is already defined by Unix system
125
+ #
126
+ # @param [Integer] code
127
+ # the code to check
128
+ #
129
+ # @return [Boolean]
130
+ #
131
+ # @api public
132
+ def exit_reserved?(code)
133
+ (code >= Code::SUCCESS && code <= Code::SHELL_MISUSE) ||
134
+ (code >= Code::USAGE_ERROR && code <= Code::CONFIG_ERROR) ||
135
+ (code >= Code::CANNOT_EXECUTE && code <= Code::USER2)
136
+ end
137
+
138
+ # Check if the exit status was successful.
139
+ #
140
+ # @param [Integer] code
141
+ #
142
+ # @api public
143
+ def exit_success?(code)
144
+ code == Code::SUCCESS
145
+ end
146
+
147
+ # A user friendly explanation of the exit code
148
+ #
149
+ # @example
150
+ # TTY::Exit.exit_message(:usage_error)
151
+ # # => "Command line usage error"
152
+ #
153
+ # @param [String,Integer] name_or_code
154
+ #
155
+ # @api public
156
+ def exit_message(name_or_code = :ok)
157
+ (Registry.exits[name_or_code] || {})[:message] ||
158
+ CODE_TO_EXIT_MESSAGE[exit_code(name_or_code)] || ""
159
+ end
160
+
161
+ # Provide a list of reserved status messages
162
+ #
163
+ # @api public
164
+ def exit_messages
165
+ CODE_TO_EXIT_MESSAGE
166
+ end
167
+
168
+ # Provide exit code for a name or status
169
+ #
170
+ # @example
171
+ # TTY::Exit.exit_code(:usage_error)
172
+ # # => 64
173
+ #
174
+ # @param [String,Integer] name_or_code
175
+ #
176
+ # @return [Integer]
177
+ # the exit code
178
+ #
179
+ # @api public
180
+ def exit_code(name_or_code = :ok)
181
+ case name_or_code
182
+ when String, Symbol
183
+ (Registry.exits[name_or_code.to_sym] || {})[:code] ||
184
+ NAME_TO_EXIT_CODE.fetch(name_or_code.to_sym) do
185
+ raise Error, "Name '#{name_or_code}' isn't recognized."
186
+ end
187
+ when Numeric
188
+ if exit_valid?(name_or_code.to_i)
189
+ name_or_code.to_i
190
+ else
191
+ raise Error, "Provided code outside of the range (0 - 255)"
192
+ end
193
+ else
194
+ raise Error, "Provide a name or a number as an exit code"
195
+ end
196
+ end
197
+
198
+ # Provide a list of reserved codes
199
+ #
200
+ # @api public
201
+ def exit_codes
202
+ NAME_TO_EXIT_CODE
203
+ end
204
+
205
+ # Exit this process with a given status code
206
+ #
207
+ # @param [String,Integer] name_or_code
208
+ # The name for an exit code or code itself
209
+ # @param [String] message
210
+ # The message to print to io stream
211
+ # @param [IO] io
212
+ # The io to print message to
213
+ #
214
+ # @return [nil]
215
+ #
216
+ # @api public
217
+ def exit_with(name_or_code = :ok, message = nil, io: $stderr)
218
+ if message == :default
219
+ message = "ERROR(#{exit_code(name_or_code)}): #{exit_message(name_or_code)}"
220
+ end
221
+ io.print(message) if message
222
+ ::Kernel.exit(exit_code(name_or_code))
223
+ end
224
+ end # Exit
225
+ end # TTY
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TTY
4
+ module Exit
5
+ # All reserved exit codes as constants
6
+ module Code
7
+ # No errors
8
+ SUCCESS = 0
9
+
10
+ # Catchall for general errors
11
+ ERROR = 1
12
+
13
+ # Missing keyword or command, or permission problem
14
+ # (and diff return code on a failed binary file comparison).
15
+ SHELL_MISUSE = 2
16
+
17
+ # The start base code to reduce possibility of clashing with other
18
+ # exit statuses that programs may already run.
19
+ BASE = 64
20
+
21
+ # The command was used incorrectly, e.g., with the wrong number
22
+ # of arguments, a bad flag, a bad syntax in a parameter, or whatever.
23
+ USAGE_ERROR = BASE # 64
24
+
25
+ # The input data was incorrect in some way.
26
+ # This should only be used for user's data & not system files.
27
+ DATA_ERROR = BASE + 1 # 65
28
+
29
+ # An input file (not a system file) did not exist or was not readable.
30
+ NO_INPUT = BASE + 2 # 66
31
+
32
+ # The user specified did not exist. This might be used for mail
33
+ # addresses or remote logins.
34
+ NO_USER = BASE + 3 # 67
35
+
36
+ # The host specified did not exist. This is used in mail addresses
37
+ # or network requests.
38
+ NO_HOST = BASE + 4 # 68
39
+
40
+ # A service is unavailable. This can occur if a support program
41
+ # or file does not exist. This can also be used as a catchall
42
+ # message when something you wanted to do doesn't work,
43
+ # but you don't know why.
44
+ SERVICE_UNAVAILABLE = BASE + 5 # 69
45
+
46
+ # An internal software error has been detected. This should be
47
+ # limited to non-operating system related errors as possible.
48
+ SOFTWARE_ERROR = BASE + 6 # 70
49
+
50
+ # An operating system error has been detected. This is intended
51
+ # to be used for such things as "cannot fork", "cannot create pipe",
52
+ # or the like. It includes things like getuid returning a user that
53
+ # does not exist in the passwd file.
54
+ SYSTEM_ERROR = BASE + 7 # 71
55
+
56
+ # Some system file (e.g., /etc/passwd, /etc/utmp, etc.) does not exist,
57
+ # cannot be opened, or has some sort of error (e.g., syntax error).
58
+ SYSTEM_FILE_MISSING = BASE + 8 #72
59
+
60
+ # A (user specified) output file cannot be created.
61
+ CANT_CREATE = BASE + 9 # 73
62
+
63
+ # An error occurred while doing I/O on some file.
64
+ IO_ERROR = BASE + 10 # 74
65
+
66
+ # Temporary failure, indicating something that is not really an error.
67
+ # For example that a mailer could not create a connection, and the
68
+ # request should be reattempted later.
69
+ TEMP_FAIL = BASE + 11 # 75
70
+
71
+ # The remote system returned something that was 'not possible' during
72
+ # a protocol exchange.
73
+ PROTOCOL = BASE + 12 # 76
74
+
75
+ # You did not have sufficient permission to perform the operation.
76
+ # This is not intended for file system problems, which should use
77
+ # NO_INPUT or CANT_CREATE, but rather for higher level permissions.
78
+ NO_PERM = BASE + 13 # 77
79
+
80
+ # Something was found in an unconfigured or misconfigured state.
81
+ CONFIG_ERROR = BASE + 14 # 78
82
+
83
+ # Command invoked cannot execute. This may be due to permission
84
+ # issues.
85
+ CANNOT_EXECUTE = 126
86
+
87
+ # "command not found", possible typos in shell command or
88
+ # unrecognized characters
89
+ COMMAND_NOT_FOUND = 127
90
+
91
+ # The start base code for the system interrupt signals.
92
+ SIGNAL_BASE = 128
93
+
94
+ # Exit takes only integer args in the range 0 - 255,
95
+ # e.g. exit 3.14159 is invalid.
96
+ INVALID_ARGUMENT = SIGNAL_BASE
97
+
98
+ # This indicates that program received SIGHUP signal.
99
+ # It means that the controlling pseudo or virtual terminal
100
+ # has been closed.
101
+ HANGUP = SIGNAL_BASE + 1 # 129
102
+
103
+ # This indicates that program received SIGINT signal.
104
+ # An interrupt signal that by default this causes the
105
+ # process to terminate.
106
+ INTERRUPT = SIGNAL_BASE + 2 # 130
107
+
108
+ # This indicates that program received SIGQUIT signal.
109
+ QUIT = SIGNAL_BASE + 3 # 131
110
+
111
+ # This indicates that program received SIGQUIT signal.
112
+ ILLEGAL_INSTRUCTION = SIGNAL_BASE + 4 # 132
113
+
114
+ # This indicates that program received SIGTRAP signal.
115
+ TRACE_TRAP = SIGNAL_BASE + 5 # 133
116
+
117
+ # This indicates that program received SIGABRT signal.
118
+ ABORT = SIGNAL_BASE + 6 # 134
119
+
120
+ # This indicates that program received SIGKILL signal.
121
+ KILL = SIGNAL_BASE + 9 # 137
122
+
123
+ # This indicates that program received SIGBUS signal.
124
+ # Access to an undefined portion of a memory object
125
+ BUS_ERROR = SIGNAL_BASE + 10 # 138
126
+
127
+ # This indicates that program received SIGSEGV signal.
128
+ MEMORY_ERROR = SIGNAL_BASE + 11 # 139
129
+
130
+ # This indicates that program received SIGPIPE signal.
131
+ PIPE = SIGNAL_BASE + 13 # 141
132
+
133
+ # This indicates that program received SIGALARM signal.
134
+ ALARM = SIGNAL_BASE + 14 # 142
135
+
136
+ # This indicates that program received SIGUSR1 signal.
137
+ USER1 = SIGNAL_BASE + 30 # 158
138
+
139
+ # This indicates that program received SIGUSR2 signal.
140
+ USER2 = SIGNAL_BASE + 31 # 159
141
+ end # Code
142
+ end # Exit
143
+ end # TTY
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TTY
4
+ module Exit
5
+ module Registry
6
+ # A storage for custom exit codes
7
+ #
8
+ # @api private
9
+ def self.exits
10
+ @exits ||= {}
11
+ end
12
+
13
+ # Register a custom exit code
14
+ #
15
+ # @param [String] name
16
+ # @param [Integer] code
17
+ # @param [String] message
18
+ #
19
+ # @api public
20
+ def self.register_exit(name, code, message)
21
+ exits[name] = {code: code, message: message}
22
+ exits[code] = {code: code, message: message}
23
+ end
24
+ end # Registry
25
+ end # Exit
26
+ end # TTY
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TTY
4
+ module Exit
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tty-exit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Piotr Murach
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-02-01 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Terminal exit codes for humans and machines
14
+ email:
15
+ - piotr@piotrmurach.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files:
19
+ - README.md
20
+ - CHANGELOG.md
21
+ files:
22
+ - CHANGELOG.md
23
+ - LICENSE.txt
24
+ - README.md
25
+ - lib/tty-exit.rb
26
+ - lib/tty/exit.rb
27
+ - lib/tty/exit/code.rb
28
+ - lib/tty/exit/registry.rb
29
+ - lib/tty/exit/version.rb
30
+ homepage: https://ttytoolkit.org
31
+ licenses:
32
+ - MIT
33
+ metadata:
34
+ allowed_push_host: https://rubygems.org
35
+ bug_tracker_uri: https://github.com/piotrmurach/tty-exit/issues
36
+ changelog_uri: https://github.com/piotrmurach/tty-exit/blob/master/CHANGELOG.md
37
+ documentation_uri: https://www.rubydoc.info/gems/tty-exit
38
+ homepage_uri: https://ttytoolkit.org
39
+ source_code_uri: https://github.com/piotrmurach/tty-exit
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 2.0.0
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubygems_version: 3.1.2
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: Terminal exit codes for humans and machines
59
+ test_files: []