From e3bd96047bfc19342a1302dac9a7675cadb237c1 Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Thu, 14 Dec 2023 11:30:11 +0900 Subject: [PATCH 1/4] Generate rdoc from git repository --- bin/generate_docs.sh | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/bin/generate_docs.sh b/bin/generate_docs.sh index 865db5783..59ef404d9 100755 --- a/bin/generate_docs.sh +++ b/bin/generate_docs.sh @@ -2,22 +2,32 @@ set -ex -if [ -z ${RUBY_VERSION} ]; then - RUBY_VERSION=`ruby -e 'puts RUBY_VERSION'` +if [ -z ${RUBY_COMMIT} ]; then + RUBY_COMMIT=v`ruby -e 'puts RUBY_VERSION.gsub(".", "_")'` fi -echo "RUBY_VERSION = ${RUBY_VERSION}" +if [ -z ${RBS_RDOC_BASE_DIR} ]; then + RBS_RDOC_BASE_DIR=/tmp/rbs-rdoc +fi REPO_ROOT=$(cd $(dirname $(dirname $0)); pwd) -rm -f /tmp/ruby.tar.gz -rm -rf /tmp/ruby-${RUBY_VERSION} +echo "RBS_RDOC_BASE_DIR = ${RBS_RDOC_BASE_DIR}" +echo "RUBY_COMMIT = ${RUBY_COMMIT}" + +RUBY_SRC_DIR=${RBS_RDOC_BASE_DIR}/ruby-${RUBY_COMMIT} +RDOC_OUT_DIR=${RBS_RDOC_BASE_DIR}/rdoc-${RUBY_COMMIT} -curl -L https://cache.ruby-lang.org/pub/ruby/${RUBY_VERSION%.*}/ruby-${RUBY_VERSION}.tar.gz | tar xzf - -C /tmp +rm -rf ${RUBY_SRC_DIR} ${RDOC_OUT_DIR} -rm -rf /tmp/rdoc-${RUBY_VERSION} +( + mkdir -p ${RUBY_SRC_DIR} + cd ${RUBY_SRC_DIR} + git init + git remote add origin https://github.com/ruby/ruby.git + git fetch --depth 1 origin ${RUBY_COMMIT} + git checkout FETCH_HEAD + bundle exec --gemfile=${REPO_ROOT}/Gemfile rdoc --output=${RDOC_OUT_DIR} --root="." --all --ri --page-dir="doc" "." +) -cd /tmp/ruby-${RUBY_VERSION} -bundle exec --gemfile=${REPO_ROOT}/Gemfile rdoc --output=/tmp/rdoc-${RUBY_VERSION} --root="." --all --ri --page-dir="doc" "." -cd ${REPO_ROOT} -bundle exec rbs annotate --no-system --no-gems --no-site --no-home -d /tmp/rdoc-${RUBY_VERSION} core stdlib +bundle exec rbs annotate --no-system --no-gems --no-site --no-home -d ${RDOC_OUT_DIR} core stdlib From d0f0a9560276ba3f9b930576e07db012fc9cf56f Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Thu, 14 Dec 2023 11:44:09 +0900 Subject: [PATCH 2/4] Update GitHub Actions --- .github/workflows/comments.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/comments.yml b/.github/workflows/comments.yml index bef5b3786..2aab94b31 100644 --- a/.github/workflows/comments.yml +++ b/.github/workflows/comments.yml @@ -12,6 +12,8 @@ jobs: runs-on: "ubuntu-latest" container: image: rubylang/ruby:3.2-dev-focal + env: + RUBY_COMMIT: v3_3_0_preview3 steps: - uses: actions/checkout@v4 - name: Install dependencies @@ -22,11 +24,6 @@ jobs: run: | ruby -v gem update --system - - name: bundle config set with - run: | - echo "NO_MINITEST=true" >> $GITHUB_ENV - bundle config set --local without 'minitest' - if: "contains(matrix.container_tag, 'master-nightly')" - name: bin/setup run: | bin/setup From 77fad94a979b1dae8c409165d1174ac431e2fc64 Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Thu, 14 Dec 2023 12:01:11 +0900 Subject: [PATCH 3/4] bundle update rdoc --- Gemfile | 2 +- Gemfile.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 3639a8014..b46613d91 100644 --- a/Gemfile +++ b/Gemfile @@ -17,7 +17,7 @@ gem "goodcheck" gem "dbm" gem 'digest' gem 'tempfile' -gem "rdoc", "~> 6.4.0" +gem "rdoc" # Test gems gem "rbs-amber", path: "test/assets/test-gem" diff --git a/Gemfile.lock b/Gemfile.lock index da3e73f5f..f811b784e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -47,7 +47,7 @@ GEM rake (13.1.0) rake-compiler (1.2.5) rake - rdoc (6.4.0) + rdoc (6.6.1) psych (>= 4.0.0) regexp_parser (2.8.3) rexml (3.2.6) @@ -81,7 +81,7 @@ GEM rubocop (~> 1.0) ruby-progressbar (1.13.0) stackprof (0.2.25) - stringio (3.0.7) + stringio (3.1.0) strong_json (2.1.2) tempfile (0.2.1) test-unit (3.6.1) @@ -105,7 +105,7 @@ DEPENDENCIES rake-compiler rbs! rbs-amber! - rdoc (~> 6.4.0) + rdoc rspec rubocop rubocop-rubycw From edcbd39670eb056cc1e342c269edb5849c95a8f7 Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Thu, 14 Dec 2023 11:41:14 +0900 Subject: [PATCH 4/4] Generate RDoc from 3.3.0-preview3 --- core/array.rbs | 68 +- core/basic_object.rbs | 4 +- core/comparable.rbs | 10 +- core/data.rbs | 6 +- core/dir.rbs | 831 +++++--- core/enumerable.rbs | 29 +- core/enumerator.rbs | 68 +- core/errors.rbs | 4 + core/false_class.rbs | 49 +- core/file.rbs | 420 ++-- core/float.rbs | 49 +- core/gc.rbs | 28 +- core/hash.rbs | 60 +- core/integer.rbs | 195 +- core/io.rbs | 152 +- core/io/buffer.rbs | 122 +- core/kernel.rbs | 863 ++++----- core/match_data.rbs | 63 +- core/nil_class.rbs | 133 +- core/numeric.rbs | 54 +- core/process.rbs | 1870 +++++++++++------- core/ractor.rbs | 255 +-- core/range.rbs | 4 - core/rational.rbs | 4 - core/rbs/unnamed/argf.rbs | 8 +- core/rbs/unnamed/env_class.rbs | 24 - core/regexp.rbs | 1741 +++++++++++------ core/ruby_vm.rbs | 10 +- core/rubygems/rubygems.rbs | 2 +- core/rubygems/version.rbs | 6 +- core/set.rbs | 42 +- core/signal.rbs | 8 +- core/string.rbs | 74 +- core/string_io.rbs | 16 +- core/struct.rbs | 24 +- core/symbol.rbs | 20 +- core/thread.rbs | 16 +- core/time.rbs | 52 +- core/trace_point.rbs | 7 +- core/true_class.rbs | 75 +- core/warning.rbs | 14 +- stdlib/base64/0/base64.rbs | 352 +++- stdlib/bigdecimal/0/big_decimal.rbs | 26 +- stdlib/coverage/0/coverage.rbs | 4 +- stdlib/csv/0/csv.rbs | 80 +- stdlib/date/0/date.rbs | 42 - stdlib/date/0/date_time.rbs | 14 +- stdlib/did_you_mean/0/did_you_mean.rbs | 2 +- stdlib/erb/0/erb.rbs | 4 +- stdlib/fileutils/0/fileutils.rbs | 19 - stdlib/io-console/0/io-console.rbs | 5 + stdlib/ipaddr/0/ipaddr.rbs | 3 +- stdlib/json/0/json.rbs | 26 +- stdlib/logger/0/logger.rbs | 14 +- stdlib/monitor/0/monitor.rbs | 78 + stdlib/net-http/0/net-http.rbs | 2423 ++++++++++++++++++------ stdlib/objspace/0/objspace.rbs | 32 +- stdlib/openssl/0/openssl.rbs | 633 +++++-- stdlib/optparse/0/optparse.rbs | 36 +- stdlib/pp/0/pp.rbs | 7 +- stdlib/prettyprint/0/prettyprint.rbs | 4 +- stdlib/pstore/0/pstore.rbs | 6 +- stdlib/rdoc/0/comment.rbs | 3 +- stdlib/socket/0/socket.rbs | 4 +- stdlib/socket/0/unix_socket.rbs | 4 +- stdlib/strscan/0/string_scanner.rbs | 5 +- stdlib/tempfile/0/tempfile.rbs | 2 +- stdlib/uri/0/common.rbs | 368 ++-- 68 files changed, 7573 insertions(+), 4103 deletions(-) diff --git a/core/array.rbs b/core/array.rbs index bcd93aae9..a22bc9eb6 100644 --- a/core/array.rbs +++ b/core/array.rbs @@ -607,7 +607,8 @@ class Array[unchecked out Elem] < Object # - array & other_array -> new_array # --> # Returns a new Array containing each element found in both `array` and Array - # `other_array`; duplicates are omitted; items are compared using `eql?`: + # `other_array`; duplicates are omitted; items are compared using `eql?` (items + # must also implement `hash` correctly): # # [0, 1, 2, 3] & [1, 2] # => [1, 2] # [0, 1, 0, 1] & [0, 1] # => [0, 1] @@ -837,8 +838,6 @@ class Array[unchecked out Elem] < Object # # Raises TypeError (no implicit conversion of Symbol into Integer): # a[:foo] # - # Array#slice is an alias for Array#[]. - # def []: %a{implicitly-returns-nil} (int index) -> Elem | (int start, int length) -> ::Array[Elem]? | (::Range[::Integer?] range) -> ::Array[Elem]? @@ -972,6 +971,8 @@ class Array[unchecked out Elem] < Object # --> # Returns `true` if all elements of `self` meet a given criterion. # + # If `self` has no element, returns `true` and argument or block are not used. + # # With no block given and no argument, returns `true` if `self` contains only # truthy elements, `false` otherwise: # @@ -1009,6 +1010,8 @@ class Array[unchecked out Elem] < Object # --> # Returns `true` if any element of `self` meets a given criterion. # + # If `self` has no element, returns `false` and argument or block are not used. + # # With no block given and no argument, returns `true` if `self` has any truthy # element, `false` otherwise: # @@ -1050,8 +1053,6 @@ class Array[unchecked out Elem] < Object # a1 = a.push([:baz, :bat], [:bam, :bad]) # a1 # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]] # - # Array#append is an alias for Array#push. - # # Related: #pop, #shift, #unshift. # alias append push @@ -1135,8 +1136,6 @@ class Array[unchecked out Elem] < Object # a1 = a.map # a1 # => # # - # Array#collect is an alias for Array#map. - # def collect: [U] () { (Elem item) -> U } -> ::Array[U] | () -> ::Enumerator[Elem, ::Array[untyped]] @@ -1157,8 +1156,6 @@ class Array[unchecked out Elem] < Object # a1 = a.map! # a1 # => # # - # Array#collect! is an alias for Array#map!. - # def collect!: () { (Elem item) -> Elem } -> self | () -> ::Enumerator[Elem, self] @@ -1388,18 +1385,16 @@ class Array[unchecked out Elem] < Object # - array.delete_if {|element| ... } -> self # - array.delete_if -> Enumerator # --> - # Removes each element in +self+ for which the block returns a truthy value; - # returns +self+: - # - # a = [:foo, 'bar', 2, 'bat'] - # a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2] + # Removes each element in `self` for which the block returns a truthy value; + # returns `self`: # - # Returns a new \Enumerator if no block given: + # a = [:foo, 'bar', 2, 'bat'] + # a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2] # - # a = [:foo, 'bar', 2] - # a.delete_if # => # + # Returns a new Enumerator if no block given: # - # 3 + # a = [:foo, 'bar', 2] + # a.delete_if # => # # def delete_if: () { (Elem item) -> boolish } -> self | () -> ::Enumerator[Elem, self] @@ -1854,8 +1849,6 @@ class Array[unchecked out Elem] < Object # a = [:foo, 'bar', 2, :bam] # a.select # => # # - # Array#filter is an alias for Array#select. - # def filter: () { (Elem item) -> boolish } -> ::Array[Elem] | () -> ::Enumerator[Elem, ::Array[Elem]] @@ -1875,8 +1868,6 @@ class Array[unchecked out Elem] < Object # a = [:foo, 'bar', 2, :bam] # a.select! # => # # - # Array#filter! is an alias for Array#select!. - # def filter!: () { (Elem item) -> boolish } -> self? | () -> ::Enumerator[Elem, self?] @@ -1912,8 +1903,6 @@ class Array[unchecked out Elem] < Object # e # => # # e.each {|element| element == 'bar' } # => 1 # - # Array#find_index is an alias for Array#index. - # # Related: #rindex. # def find_index: (untyped obj) -> ::Integer? @@ -1921,7 +1910,7 @@ class Array[unchecked out Elem] < Object | () -> ::Enumerator[Elem, ::Integer?] # @@ -2078,8 +2067,6 @@ class Array[unchecked out Elem] < Object # e # => # # e.each {|element| element == 'bar' } # => 1 # - # Array#find_index is an alias for Array#index. - # # Related: #rindex. # alias index find_index @@ -2130,8 +2117,6 @@ class Array[unchecked out Elem] < Object # a = [:foo, 'bar', 2] # a.inspect # => "[:foo, \"bar\", 2]" # - # Array#to_s is an alias for Array#inspect. - # def inspect: () -> String # # Returns a new Array containing each element found both in `self` and in all of # the given Arrays `other_arrays`; duplicates are omitted; items are compared - # using `eql?`: + # using `eql?` (items must also implement `hash` correctly): # # [0, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1] # [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1] @@ -2221,7 +2209,7 @@ class Array[unchecked out Elem] < Object | () -> ::Enumerator[Elem, self] # @@ -2277,8 +2265,6 @@ class Array[unchecked out Elem] < Object # a1 = a.map # a1 # => # # - # Array#collect is an alias for Array#map. - # alias map collect # @@ -2294,8 +2280,6 @@ class Array[unchecked out Elem] < Object # a1 = a.map! # a1 # => # # - # Array#collect! is an alias for Array#map!. - # alias map! collect! # - # Defines a new Data class. If the first argument is a string, the class is - # stored in `Data::` constant. + # Defines a new Data class. # # measure = Data.define(:amount, :unit) # #=> # diff --git a/core/dir.rbs b/core/dir.rbs index ed4f2bc38..9c2337e64 100644 --- a/core/dir.rbs +++ b/core/dir.rbs @@ -1,11 +1,85 @@ # -# Objects of class Dir are directory streams representing directories in the -# underlying file system. They provide a variety of ways to list directories and -# their contents. See also File. +# An object of class Dir represents a directory in the underlying file system. # -# The directory used in these examples contains the two regular files -# (`config.h` and `main.rb`), the parent directory (`..`), and the directory -# itself (`.`). +# It consists mainly of: +# +# * A string *path*, given when the object is created, that specifies a +# directory in the underlying file system; method #path returns the path. +# * A collection of string *entry names*, each of which is the name of a +# directory or file in the underlying file system; the entry names may be +# retrieved in an [array-like fashion](rdoc-ref:Dir@Dir+As+Array-Like) or in +# a [stream-like fashion](rdoc-ref:Dir@Dir+As+Stream-Like). +# +# +# ## About the Examples +# +# Some examples on this page use this simple file tree: +# +# example/ +# ├── config.h +# ├── lib/ +# │ ├── song/ +# │ │ └── karaoke.rb +# │ └── song.rb +# └── main.rb +# +# Others use the file tree for the [Ruby project +# itself](https://github.com/ruby/ruby). +# +# ## Dir As Array-Like +# +# A Dir object is in some ways array-like: +# +# * It has instance methods #children, #each, and #each_child. +# * It includes [module Enumerable](rdoc-ref:Enumerable@What-27s+Here). +# +# +# ## Dir As Stream-Like +# +# A Dir object is in some ways stream-like. +# +# The stream is initially open for reading, but may be closed manually (using +# method #close), and will be closed on block exit if created by Dir.open called +# with a block. The closed stream may not be further manipulated, and may not be +# reopened. +# +# The stream has a *position*, which is the index of an entry in the directory: +# +# * The initial position is zero (before the first entry). +# * Method #tell (aliased as #pos) returns the position. +# * Method #pos= sets the position (but ignores a value outside the stream), +# and returns the position. +# * Method #seek is like #pos=, but returns `self` (convenient for chaining). +# * Method #read, if not at end-of-stream, reads the next entry and increments +# the position; if at end-of-stream, does not increment the position. +# * Method #rewind sets the position to zero. +# +# +# Examples (using the [simple file tree](rdoc-ref:Dir@About+the+Examples)): +# +# dir = Dir.new('example') # => # +# dir.pos # => 0 +# +# dir.read # => "." +# dir.read # => ".." +# dir.read # => "config.h" +# dir.read # => "lib" +# dir.read # => "main.rb" +# dir.pos # => 5 +# dir.read # => nil +# dir.pos # => 5 +# +# dir.rewind # => # +# dir.pos # => 0 +# +# dir.pos = 3 # => 3 +# dir.pos # => 3 +# +# dir.seek(4) # => # +# dir.pos # => 4 +# +# dir.close # => nil +# dir.read # Raises IOError. # # ## What's Here # @@ -94,358 +168,511 @@ class Dir # - # Returns a new directory object for the named directory. + # Returns a new Dir object for the directory at `dirpath`: + # + # Dir.new('.') # => # # - # The optional *encoding* keyword argument specifies the encoding of the - # directory. If not specified, the filesystem encoding is used. + # The value given with optional keyword argument `encoding` specifies the + # encoding for the directory entry names; if `nil` (the default), the file + # system's encoding is used: + # + # Dir.new('.').read.encoding # => # + # Dir.new('.', encoding: 'US-ASCII').read.encoding # => # # def initialize: (path dir, ?encoding: encoding?) -> self # - # Equivalent to calling `Dir.glob([`*string,...*`], 0)`. + # Calls Dir.glob with argument `patterns` and the values of keyword arguments + # `base` and `sort`; returns the array of selected entry names. # def self.[]: (*path patterns, ?base: path?, ?sort: bool) -> Array[String] # - # Changes the current working directory of the process to the given string. When - # called without an argument, changes the directory to the value of the - # environment variable `HOME`, or `LOGDIR`. SystemCallError (probably - # Errno::ENOENT) if the target directory does not exist. - # - # If a block is given, it is passed the name of the new current directory, and - # the block is executed with that as the current directory. The original working - # directory is restored when the block exits. The return value of `chdir` is the - # value of the block. `chdir` blocks can be nested, but in a multi-threaded - # program an error will be raised if a thread attempts to open a `chdir` block - # while another thread has one open or a call to `chdir` without a block occurs - # inside a block passed to `chdir` (even in the same thread). - # - # Dir.chdir("/var/spool/mail") - # puts Dir.pwd - # Dir.chdir("/tmp") do - # puts Dir.pwd - # Dir.chdir("/usr") do - # puts Dir.pwd + # Changes the current working directory. + # + # With argument `new_dirpath` and no block, changes to the given `dirpath`: + # + # Dir.pwd # => "/example" + # Dir.chdir('..') # => 0 + # Dir.pwd # => "/" + # + # With no argument and no block: + # + # * Changes to the value of environment variable `HOME` if defined. + # * Otherwise changes to the value of environment variable `LOGDIR` if + # defined. + # * Otherwise makes no change. + # + # + # With argument `new_dirpath` and a block, temporarily changes the working + # directory: + # + # * Calls the block with the argument. + # * Changes to the given directory. + # * Executes the block + # * Restores the previous working directory. + # * Returns the block's return value. + # + # + # Example: + # + # Dir.chdir('/var/spool/mail') + # Dir.pwd # => "/var/spool/mail" + # Dir.chdir('/tmp') do + # Dir.pwd # => "/tmp" + # end + # Dir.pwd # => "/var/spool/mail" + # + # With no argument and a block, calls the block with the current working + # directory (string) and returns the block's return value. + # + # Calls to Dir.chdir with blocks may be nested: + # + # Dir.chdir('/var/spool/mail') + # Dir.pwd # => "/var/spool/mail" + # Dir.chdir('/tmp') do + # Dir.pwd # => "/tmp" + # Dir.chdir('/usr') do + # Dir.pwd # => "/usr" # end - # puts Dir.pwd + # Dir.pwd # => "/tmp" # end - # puts Dir.pwd + # Dir.pwd # => "/var/spool/mail" # - # *produces:* + # In a multi-threaded program an error is raised if a thread attempts to open a + # `chdir` block while another thread has one open, or a call to `chdir` without + # a block occurs inside a block passed to `chdir` (even in the same thread). # - # /var/spool/mail - # /tmp - # /usr - # /tmp - # /var/spool/mail + # Raises an exception if the target directory does not exist. # def self.chdir: (?path dir) -> 0 | [U] (?path dir) { (String dir) -> U } -> U # - # Returns an array containing all of the filenames except for "." and ".." in - # the given directory. Will raise a SystemCallError if the named directory - # doesn't exist. + # Returns an array of the entry names in the directory at `dirpath` except for + # `'.'` and `'..'`; sets the given encoding onto each returned entry name: + # + # Dir.children('/example') # => ["config.h", "lib", "main.rb"] + # Dir.children('/example').first.encoding + # # => # + # Dir.children('/example', encoding: 'US-ASCII').first.encoding + # # => # # - # The optional *encoding* keyword argument specifies the encoding of the - # directory. If not specified, the filesystem encoding is used. + # See [String Encoding](rdoc-ref:encodings.rdoc@String+Encoding). # - # Dir.children("testdir") #=> ["config.h", "main.rb"] + # Raises an exception if the directory does not exist. # def self.children: (path dirname, ?encoding: encoding?) -> Array[String] # - # Changes this process's idea of the file system root. Only a privileged process - # may make this call. Not available on all platforms. On Unix systems, see - # `chroot(2)` for more information. + # Changes the root directory of the calling process to that specified in + # `dirpath`. The new root directory is used for pathnames beginning with `'/'`. + # The root directory is inherited by all children of the calling process. + # + # Only a privileged process may call `chroot`. + # + # See [Linux chroot](https://man7.org/linux/man-pages/man2/chroot.2.html). # def self.chroot: (path root) -> 0 # - # Deletes the named directory. Raises a subclass of SystemCallError if the - # directory isn't empty. + # Removes the directory at `dirpath` from the underlying file system: + # + # Dir.rmdir('foo') # => 0 + # + # Raises an exception if the directory is not empty. # def self.delete: (path dirname) -> 0 # - # Calls the block once for each entry except for "." and ".." in the named - # directory, passing the filename of each entry as a parameter to the block. - # - # If no block is given, an enumerator is returned instead. - # - # Dir.each_child("testdir") {|x| puts "Got #{x}" } - # - # *produces:* - # - # Got config.h - # Got main.rb + # Like Dir.foreach, except that entries `'.'` and `'..'` are not included. # def self.each_child: (path dirname, ?encoding: encoding?) -> Enumerator[String, nil] | (path dirname, ?encoding: encoding?) { (String filename) -> void } -> nil # - # Returns `true` if the named file is an empty directory, `false` if it is not a - # directory or non-empty. + # Returns whether `dirpath` specifies an empty directory: + # + # dirpath = '/tmp/foo' + # Dir.mkdir(dirpath) + # Dir.empty?(dirpath) # => true + # Dir.empty?('/example') # => false + # Dir.empty?('/example/main.rb') # => false + # + # Raises an exception if `dirpath` does not specify a directory or file in the + # underlying file system. # def self.empty?: (path path_name) -> bool # - # Returns an array containing all of the filenames in the given directory. Will - # raise a SystemCallError if the named directory doesn't exist. + # Returns an array of the entry names in the directory at `dirpath`; sets the + # given encoding onto each returned entry name: # - # The optional *encoding* keyword argument specifies the encoding of the - # directory. If not specified, the filesystem encoding is used. + # Dir.entries('/example') # => ["config.h", "lib", "main.rb", "..", "."] + # Dir.entries('/example').first.encoding + # # => # + # Dir.entries('/example', encoding: 'US-ASCII').first.encoding + # # => # # - # Dir.entries("testdir") #=> [".", "..", "config.h", "main.rb"] + # See [String Encoding](rdoc-ref:encodings.rdoc@String+Encoding). + # + # Raises an exception if the directory does not exist. # def self.entries: (path dirname, ?encoding: encoding?) -> Array[String] # - # Returns `true` if the named file is a directory, `false` otherwise. + # Returns whether `dirpath` is a directory in the underlying file system: + # + # Dir.exist?('/example') # => true + # Dir.exist?('/nosuch') # => false + # Dir.exist?('/example/main.rb') # => false # def self.exist?: (path | io file_name) -> bool # - # Calls the block once for each entry in the named directory, passing the - # filename of each entry as a parameter to the block. + # Calls the block with each entry name in the directory at `dirpath`; sets the + # given encoding onto each passed `entry_name`: + # + # Dir.foreach('/example') {|entry_name| p entry_name } + # + # Output: + # + # "config.h" + # "lib" + # "main.rb" + # ".." + # "." + # + # Encoding: + # + # Dir.foreach('/example') {|entry_name| p entry_name.encoding; break } + # Dir.foreach('/example', encoding: 'US-ASCII') {|entry_name| p entry_name.encoding; break } # - # If no block is given, an enumerator is returned instead. + # Output: # - # Dir.foreach("testdir") {|x| puts "Got #{x}" } + # # + # # # - # *produces:* + # See [String Encoding](rdoc-ref:encodings.rdoc@String+Encoding). # - # Got . - # Got .. - # Got config.h - # Got main.rb + # Returns an enumerator if no block is given. # alias self.foreach self.each_child # - # Returns the path to the current working directory of this process as a string. + # Returns the path to the current working directory: # - # Dir.chdir("/tmp") #=> 0 - # Dir.getwd #=> "/tmp" - # Dir.pwd #=> "/tmp" + # Dir.chdir("/tmp") # => 0 + # Dir.pwd # => "/tmp" # def self.getwd: () -> String # - # Expands `pattern`, which is a pattern string or an Array of pattern strings, - # and returns an array containing the matching filenames. If a block is given, - # calls the block once for each matching filename, passing the filename as a - # parameter to the block. + # Forms an array *entry_names* of the entry names selected by the arguments. # - # The optional `base` keyword argument specifies the base directory for - # interpreting relative pathnames instead of the current working directory. As - # the results are not prefixed with the base directory name in this case, you - # will need to prepend the base directory name if you want real paths. + # Argument `patterns` is a string pattern or an array of string patterns; note + # that these are not regexps; see below. # - # The results which matched single wildcard or character set are sorted in - # binary ascending order, unless `false` is given as the optional `sort` keyword - # argument. The order of an Array of pattern strings and braces are preserved. + # Notes for the following examples: # - # Note that the pattern is not a regexp, it's closer to a shell glob. See - # File::fnmatch for the meaning of the `flags` parameter. Case sensitivity - # depends on your system (`File::FNM_CASEFOLD` is ignored). + # * `'*'` is the pattern that matches any entry name except those that begin + # with `'.'`. + # * We use method Array#take to shorten returned arrays that otherwise would + # be very large. # - # `*` - # : Matches any file. Can be restricted by other values in the glob. - # Equivalent to `/.*/mx` in regexp. # - # `*` - # : Matches all files - # `c*` - # : Matches all files beginning with `c` - # `*c` - # : Matches all files ending with `c` - # `*c*` - # : Match all files that have `c` in them (including at the beginning or - # end). + # With no block, returns array *entry_names*; example (using the [simple file + # tree](rdoc-ref:Dir@About+the+Examples)): # + # Dir.glob('*') # => ["config.h", "lib", "main.rb"] # - # Note, this will not match Unix-like hidden files (dotfiles). In order to - # include those in the match results, you must use the File::FNM_DOTMATCH - # flag or something like `"{*,.*}"`. + # With a block, calls the block with each of the *entry_names* and returns + # `nil`: # - # `**` - # : Matches directories recursively if followed by `/`. If this path segment - # contains any other characters, it is the same as the usual `*`. + # Dir.glob('*') {|entry_name| puts entry_name } # => nil # - # `?` - # : Matches any one character. Equivalent to `/.{1}/` in regexp. + # Output: # - # `[set]` - # : Matches any one character in `set`. Behaves exactly like character sets - # in Regexp, including set negation (`[^a-z]`). + # config.h + # lib + # main.rb # - # `{p,q}` - # : Matches either literal `p` or literal `q`. Equivalent to pattern - # alternation in regexp. + # If optional keyword argument `flags` is given, the value modifies the + # matching; see below. # - # Matching literals may be more than one character in length. More than two - # literals may be specified. + # If optional keyword argument `base` is given, its value specifies the base + # directory. Each pattern string specifies entries relative to the base + # directory; the default is `'.'`. The base directory is not prepended to the + # entry names in the result: # - # `\` - # : Escapes the next metacharacter. + # Dir.glob(pattern, base: 'lib').take(5) + # # => ["abbrev.gemspec", "abbrev.rb", "base64.gemspec", "base64.rb", "benchmark.gemspec"] + # Dir.glob(pattern, base: 'lib/irb').take(5) + # # => ["cmd", "color.rb", "color_printer.rb", "completion.rb", "context.rb"] # - # Note that this means you cannot use backslash on windows as part of a - # glob, i.e. `Dir["c:\\foo*"]` will not work, use `Dir["c:/foo*"]` instead. + # If optional keyword `sort` is given, its value specifies whether the array is + # to be sorted; the default is `true`. Passing value `false` with that keyword + # disables sorting (though the underlying file system may already have sorted + # the array). # + # **Patterns** # - # Examples: + # Each pattern string is expanded according to certain metacharacters; examples + # below use the [Ruby file tree](rdoc-ref:Dir@About+the+Examples): + # + # * `'*'`: Matches any substring in an entry name, similar in meaning to + # regexp `/.*/mx`; may be restricted by other values in the pattern strings: + # + # * `'*'` matches all entry names: + # + # Dir.glob('*').take(3) # => ["BSDL", "CONTRIBUTING.md", "COPYING"] + # + # * `'c*'` matches entry names beginning with `'c'`: + # + # Dir.glob('c*').take(3) # => ["CONTRIBUTING.md", "COPYING", "COPYING.ja"] + # + # * `'*c'` matches entry names ending with `'c'`: + # + # Dir.glob('*c').take(3) # => ["addr2line.c", "array.c", "ast.c"] + # + # * `'*c*'` matches entry names that contain `'c'`, even at the beginning + # or end: + # + # Dir.glob('*c*').take(3) # => ["CONTRIBUTING.md", "COPYING", "COPYING.ja"] + # + # + # Does not match Unix-like hidden entry names ("dot files"). To include + # those in the matched entry names, use flag IO::FNM_DOTMATCH or something + # like `'{*,.*}'`. + # + # * `'**'`: Matches entry names recursively if followed by the slash + # character `'/'`: + # + # Dir.glob('**/').take(3) # => ["basictest/", "benchmark/", "benchmark/gc/"] + # + # If the string pattern contains other characters or is not followed by a + # slash character, it is equivalent to `'*'`. + # + # * `'?'` Matches any single character; similar in meaning to regexp `/./`: + # + # Dir.glob('io.?') # => ["io.c"] + # + # * `'[*set*]'`: Matches any one character in the string *set*; behaves like a + # [Regexp character class](rdoc-ref:regexp.rdoc@Character+Classes), + # including set negation (`'[^a-z]'`): + # + # Dir.glob('*.[a-z][a-z]').take(3) + # # => ["CONTRIBUTING.md", "COPYING.ja", "KNOWNBUGS.rb"] + # + # * `'{*abc*,*xyz*}'`: Matches either string *abc* or string *xyz*; behaves + # like [Regexp alternation](rdoc-ref:regexp.rdoc@Alternation): + # + # Dir.glob('{LEGAL,BSDL}') # => ["LEGAL", "BSDL"] + # + # More than two alternatives may be given. + # + # * `\`: Escapes the following metacharacter. + # + # Note that on Windows, the backslash character may not be used in a string + # pattern: `Dir['c:\\foo*']` will not work, use `Dir['c:/foo*']` instead. + # + # + # More examples (using the [simple file tree](rdoc-ref:Dir@About+the+Examples)): + # + # # We're in the example directory. + # File.basename(Dir.pwd) # => "example" + # Dir.glob('config.?') # => ["config.h"] + # Dir.glob('*.[a-z][a-z]') # => ["main.rb"] + # Dir.glob('*.[^r]*') # => ["config.h"] + # Dir.glob('*.{rb,h}') # => ["main.rb", "config.h"] + # Dir.glob('*') # => ["config.h", "lib", "main.rb"] + # Dir.glob('*', File::FNM_DOTMATCH) # => [".", "config.h", "lib", "main.rb"] + # Dir.glob(["*.rb", "*.h"]) # => ["main.rb", "config.h"] + # + # Dir.glob('**/*.rb') + # => ["lib/song/karaoke.rb", "lib/song.rb", "main.rb"] # - # Dir["config.?"] #=> ["config.h"] - # Dir.glob("config.?") #=> ["config.h"] - # Dir.glob("*.[a-z][a-z]") #=> ["main.rb"] - # Dir.glob("*.[^r]*") #=> ["config.h"] - # Dir.glob("*.{rb,h}") #=> ["main.rb", "config.h"] - # Dir.glob("*") #=> ["config.h", "main.rb"] - # Dir.glob("*", File::FNM_DOTMATCH) #=> [".", "config.h", "main.rb"] - # Dir.glob(["*.rb", "*.h"]) #=> ["main.rb", "config.h"] + # Dir.glob('**/*.rb', base: 'lib') # => ["song/karaoke.rb", "song.rb"] # - # Dir.glob("**/*.rb") #=> ["main.rb", - # # "lib/song.rb", - # # "lib/song/karaoke.rb"] + # Dir.glob('**/lib') # => ["lib"] # - # Dir.glob("**/*.rb", base: "lib") #=> ["song.rb", - # # "song/karaoke.rb"] + # Dir.glob('**/lib/**/*.rb') # => ["lib/song/karaoke.rb", "lib/song.rb"] # - # Dir.glob("**/lib") #=> ["lib"] + # Dir.glob('**/lib/*.rb') # => ["lib/song.rb"] # - # Dir.glob("**/lib/**/*.rb") #=> ["lib/song.rb", - # # "lib/song/karaoke.rb"] + # **Flags** # - # Dir.glob("**/lib/*.rb") #=> ["lib/song.rb"] + # If optional keyword argument `flags` is given (the default is zero -- no + # flags), its value should be the bitwise OR of one or more of the constants + # defined in module File::Constants. + # + # Example: + # + # flags = File::FNM_EXTGLOB | File::FNM_DOTMATCH + # + # Specifying flags can extend, restrict, or otherwise modify the matching. + # + # The flags for this method (other constants in File::Constants do not apply): + # + # * File::FNM_DOTMATCH: specifies that entry names beginning with `'.'` should + # be considered for matching: + # + # Dir.glob('*').take(5) + # # => ["BSDL", "CONTRIBUTING.md", "COPYING", "COPYING.ja", "GPL"] + # Dir.glob('*', flags: File::FNM_DOTMATCH).take(5) + # # => [".", ".appveyor.yml", ".cirrus.yml", ".dir-locals.el", ".document"] + # + # * File::FNM_EXTGLOB: enables the pattern extension `'{*a*,*b*}'`, which + # matches pattern *a* and pattern *b*; behaves like a [regexp + # union](rdoc-ref:Regexp.union) (e.g., `'(?:*a*|*b*)'`): + # + # pattern = '{LEGAL,BSDL}' + # Dir.glob(pattern) # => ["LEGAL", "BSDL"] + # + # * File::FNM_NOESCAPE: specifies that escaping with the backslash character + # `'\'` is disabled; the character is not an escape character. + # + # * File::FNM_PATHNAME: specifies that metacharacters `'*'` and `'?'` do not + # match directory separators. + # + # * File::FNM_SHORTNAME: specifies that patterns may match short names if they + # exist; Windows only. # def self.glob: (array[path] | path pattern, ?int flags, ?base: path?, ?sort: bool) -> Array[String] | (array[path] | path pattern, ?int flags, ?base: path?, ?sort: bool) { (String pathname) -> void } -> nil # - # Returns the home directory of the current user or the named user if given. + # Raises ArgumentError if `user_name` is not a user name. # def self.home: (?string? user) -> String # - # Makes a new directory named by *string*, with permissions specified by the - # optional parameter *anInteger*. The permissions may be modified by the value - # of File::umask, and are ignored on NT. Raises a SystemCallError if the - # directory cannot be created. See also the discussion of permissions in the - # class documentation for File. + # Creates a directory in the underlying file system at `dirpath` with the given + # `permissions`; returns zero: # - # Dir.mkdir(File.join(Dir.home, ".foo"), 0700) #=> 0 + # Dir.mkdir('foo') + # File.stat(Dir.new('foo')).mode.to_s(8)[1..4] # => "0755" + # Dir.mkdir('bar', 0644) + # File.stat(Dir.new('bar')).mode.to_s(8)[1..4] # => "0644" + # + # See [File Permissions](rdoc-ref:File@File+Permissions). Note that argument + # `permissions` is ignored on Windows. # def self.mkdir: (path dirname, ?int permissions) -> 0 # - # The optional *encoding* keyword argument specifies the encoding of the - # directory. If not specified, the filesystem encoding is used. + # Creates a new Dir object *dir* for the directory at `dirpath`. + # + # With no block, the method equivalent to Dir.new(dirpath, encoding): + # + # Dir.open('.') # => # # - # With no block, `open` is a synonym for Dir::new. If a block is present, it is - # passed *aDir* as a parameter. The directory is closed at the end of the block, - # and Dir::open returns the value of the block. + # With a block given, the block is called with the created *dir*; on block exit + # *dir* is closed and the block's value is returned: + # + # Dir.open('.') {|dir| dir.inspect } # => "#" + # + # The value given with optional keyword argument `encoding` specifies the + # encoding for the directory entry names; if `nil` (the default), the file + # system's encoding is used: + # + # Dir.open('.').read.encoding # => # + # Dir.open('.', encoding: 'US-ASCII').read.encoding # => # # def self.open: (path dirname, ?encoding: encoding?) -> instance | [U] (path dirname, ?encoding: encoding?) { (instance) -> U } -> U # - # Returns the path to the current working directory of this process as a string. + # Returns the path to the current working directory: # - # Dir.chdir("/tmp") #=> 0 - # Dir.getwd #=> "/tmp" - # Dir.pwd #=> "/tmp" + # Dir.chdir("/tmp") # => 0 + # Dir.pwd # => "/tmp" # alias self.pwd self.getwd # - # Deletes the named directory. Raises a subclass of SystemCallError if the - # directory isn't empty. + # Removes the directory at `dirpath` from the underlying file system: + # + # Dir.rmdir('foo') # => 0 + # + # Raises an exception if the directory is not empty. # alias self.rmdir self.delete # - # Deletes the named directory. Raises a subclass of SystemCallError if the - # directory isn't empty. + # Removes the directory at `dirpath` from the underlying file system: + # + # Dir.rmdir('foo') # => 0 + # + # Raises an exception if the directory is not empty. # alias self.unlink self.delete @@ -453,194 +680,210 @@ class Dir # - # Returns an array containing all of the filenames except for "." and ".." in - # this directory. + # Returns an array of the entry names in `self` except for `'.'` and `'..'`: # - # d = Dir.new("testdir") - # d.children #=> ["config.h", "main.rb"] + # dir = Dir.new('/example') + # dir.children # => ["config.h", "lib", "main.rb"] # def children: () -> Array[String] # - # Closes the directory stream. Calling this method on closed Dir object is - # ignored since Ruby 2.3. + # Closes the stream in `self`, if it is open, and returns `nil`; ignored if + # `self` is already closed: # - # d = Dir.new("testdir") - # d.close #=> nil + # dir = Dir.new('example') + # dir.read # => "." + # dir.close # => nil + # dir.close # => nil + # dir.read # Raises IOError. # def close: () -> nil # - # Calls the block once for each entry in this directory, passing the filename of - # each entry as a parameter to the block. + # Calls the block with each entry name in `self`: # - # If no block is given, an enumerator is returned instead. + # Dir.new('example').each {|entry_name| p entry_name } # - # d = Dir.new("testdir") - # d.each {|x| puts "Got #{x}" } + # Output: # - # *produces:* + # "." + # ".." + # "config.h" + # "lib" + # "main.rb" # - # Got . - # Got .. - # Got config.h - # Got main.rb + # With no block given, returns an Enumerator. # def each: () { (String) -> void } -> self | () -> Enumerator[String, self] # - # Calls the block once for each entry except for "." and ".." in this directory, - # passing the filename of each entry as a parameter to the block. + # Calls the block with each entry name in `self` except `'.'` and `'..'`: # - # If no block is given, an enumerator is returned instead. + # dir = Dir.new('/example') + # dir.each_child {|entry_name| p entry_name } # - # d = Dir.new("testdir") - # d.each_child {|x| puts "Got #{x}" } + # Output: # - # *produces:* + # "config.h" + # "lib" + # "main.rb" # - # Got config.h - # Got main.rb + # If no block is given, returns an enumerator. # def each_child: () { (String) -> void } -> self | () -> Enumerator[String, self] # # Returns the file descriptor used in *dir*. # - # d = Dir.new("..") - # d.fileno #=> 8 + # d = Dir.new('..') + # d.fileno # => 8 # - # This method uses dirfd() function defined by POSIX 2008. NotImplementedError - # is raised on other platforms, such as Windows, which doesn't provide the - # function. + # This method uses the + # [dirfd()](https://www.man7.org/linux/man-pages/man3/dirfd.3.html) function + # defined by POSIX 2008; the method is not implemented on non-POSIX platforms + # (raises NotImplementedError). # def fileno: () -> Integer # - # Return a string describing this Dir object. + # Returns a string description of `self`: + # + # Dir.new('example').inspect # => "#" # def inspect: () -> String # - # Returns the path parameter passed to *dir*'s constructor. + # Returns the `dirpath` string that was used to create `self` (or `nil` if + # created by method Dir.for_fd): # - # d = Dir.new("..") - # d.path #=> ".." + # Dir.new('example').path # => "example" # def path: () -> String? # - # Returns the current position in *dir*. See also Dir#seek. + # Returns the current position of `self`; see [Dir As + # Stream-Like](rdoc-ref:Dir@Dir+As+Stream-Like): # - # d = Dir.new("testdir") - # d.tell #=> 0 - # d.read #=> "." - # d.tell #=> 12 + # dir = Dir.new('example') + # dir.tell # => 0 + # dir.read # => "." + # dir.tell # => 1 # def pos: () -> Integer # - # Synonym for Dir#seek, but returns the position parameter. + # Sets the position in `self` and returns `position`. The value of `position` + # should have been returned from an earlier call to #tell; if not, the return + # values from subsequent calls to #read are unspecified. + # + # See [Dir As Stream-Like](rdoc-ref:Dir@Dir+As+Stream-Like). + # + # Examples: # - # d = Dir.new("testdir") #=> # - # d.read #=> "." - # i = d.pos #=> 12 - # d.read #=> ".." - # d.pos = i #=> 12 - # d.read #=> ".." + # dir = Dir.new('example') + # dir.pos # => 0 + # dir.pos = 3 # => 3 + # dir.pos # => 3 + # dir.pos = 30 # => 30 + # dir.pos # => 5 # def pos=: [U < _ToInt] (U pos) -> U # - # Reads the next entry from *dir* and returns it as a string. Returns `nil` at - # the end of the stream. + # Reads and returns the next entry name from `self`; returns `nil` if at + # end-of-stream; see [Dir As Stream-Like](rdoc-ref:Dir@Dir+As+Stream-Like): # - # d = Dir.new("testdir") - # d.read #=> "." - # d.read #=> ".." - # d.read #=> "config.h" + # dir = Dir.new('example') + # dir.read # => "." + # dir.read # => ".." + # dir.read # => "config.h" # def read: () -> String? # - # Repositions *dir* to the first entry. + # Sets the position in `self` to zero; see [Dir As + # Stream-Like](rdoc-ref:Dir@Dir+As+Stream-Like): # - # d = Dir.new("testdir") - # d.read #=> "." - # d.rewind #=> # - # d.read #=> "." + # dir = Dir.new('example') + # dir.read # => "." + # dir.read # => ".." + # dir.pos # => 2 + # dir.rewind # => # + # dir.pos # => 0 # def rewind: () -> self # - # Seeks to a particular location in *dir*. *integer* must be a value returned by - # Dir#tell. + # Sets the position in `self` and returns `self`. The value of `position` should + # have been returned from an earlier call to #tell; if not, the return values + # from subsequent calls to #read are unspecified. + # + # See [Dir As Stream-Like](rdoc-ref:Dir@Dir+As+Stream-Like). + # + # Examples: # - # d = Dir.new("testdir") #=> # - # d.read #=> "." - # i = d.tell #=> 12 - # d.read #=> ".." - # d.seek(i) #=> # - # d.read #=> ".." + # dir = Dir.new('example') + # dir.pos # => 0 + # dir.seek(3) # => # + # dir.pos # => 3 + # dir.seek(30) # => # + # dir.pos # => 5 # def seek: (int pos) -> self # - # Returns the current position in *dir*. See also Dir#seek. + # Returns the current position of `self`; see [Dir As + # Stream-Like](rdoc-ref:Dir@Dir+As+Stream-Like): # - # d = Dir.new("testdir") - # d.tell #=> 0 - # d.read #=> "." - # d.tell #=> 12 + # dir = Dir.new('example') + # dir.tell # => 0 + # dir.read # => "." + # dir.tell # => 1 # alias tell pos # - # Returns the path parameter passed to *dir*'s constructor. + # Returns the `dirpath` string that was used to create `self` (or `nil` if + # created by method Dir.for_fd): # - # d = Dir.new("..") - # d.path #=> ".." + # Dir.new('example').path # => "example" # alias to_path path end diff --git a/core/enumerable.rbs b/core/enumerable.rbs index 0f1f3e6e0..f00ca59cb 100644 --- a/core/enumerable.rbs +++ b/core/enumerable.rbs @@ -5,7 +5,8 @@ # # * [Querying](rdoc-ref:Enumerable@Methods+for+Querying) # * [Fetching](rdoc-ref:Enumerable@Methods+for+Fetching) -# * [Searching](rdoc-ref:Enumerable@Methods+for+Searching) +# * [Searching and +# Filtering](rdoc-ref:Enumerable@Methods+for+Searching+and+Filtering) # * [Sorting](rdoc-ref:Enumerable@Methods+for+Sorting) # * [Iterating](rdoc-ref:Enumerable@Methods+for+Iterating) # * [And more....](rdoc-ref:Enumerable@Other+Methods) @@ -210,6 +211,8 @@ module Enumerable[unchecked out Elem] : _Each[Elem] # --> # Returns whether every element meets a given criterion. # + # If `self` has no element, returns `true` and argument or block are not used. + # # With no argument and no block, returns whether every element is truthy: # # (1..4).all? # => true @@ -252,6 +255,8 @@ module Enumerable[unchecked out Elem] : _Each[Elem] # --> # Returns whether any element meets a given criterion. # + # If `self` has no element, returns `false` and argument or block are not used. + # # With no argument and no block, returns whether any element is truthy: # # (1..4).any? # => true @@ -521,8 +526,6 @@ module Enumerable[unchecked out Elem] : _Each[Elem] # # (0..4).to_a # => [0, 1, 2, 3, 4] # - # Enumerable#entries is an alias for Enumerable#to_a. - # def entries: () -> ::Array[Elem] # # When `self` consists of 2-element arrays, returns a hash each of whose entries # is the key-value pair formed from one of those arrays: @@ -1570,8 +1569,6 @@ module Enumerable[unchecked out Elem] : _Each[Elem] # {foo: 0, bar: 1, baz: 2}.include?('foo') # => false # {foo: 0, bar: 1, baz: 2}.include?(0) # => false # - # Enumerable#member? is an alias for Enumerable#include?. - # def member?: (Elem arg0) -> bool # @@ -1717,20 +1714,16 @@ module Enumerable[unchecked out Elem] : _Each[Elem] # "Memo: 3; element: 3" # "Memo: 6; element: 4" # - # Enumerable#reduce is an alias for Enumerable#inject. - # alias reduce inject # # Returns an array containing the items in `self`: # # (0..4).to_a # => [0, 1, 2, 3, 4] # - # Enumerable#entries is an alias for Enumerable#to_a. - # def to_a: () -> ::Array[Elem] # +# for RubyGems without Bundler environment. If loading library is not part of +# the default gems and the bundled gems, warn it. +# class LoadError < ScriptError # # the path failed to load diff --git a/core/false_class.rbs b/core/false_class.rbs index 70b958406..eac38fe7b 100644 --- a/core/false_class.rbs +++ b/core/false_class.rbs @@ -8,32 +8,47 @@ class FalseClass # - # And---Returns `false`. *obj* is always evaluated as it is the argument to a - # method call---there is no short-circuit evaluation in this case. + # Returns `false`: + # + # false & true # => false + # false & Object.new # => false + # + # Argument `object` is evaluated: + # + # false & raise # Raises RuntimeError. # def &: (untyped obj) -> false # - # Case Equality -- For class Object, effectively the same as calling `#==`, but - # typically overridden by descendants to provide meaningful semantics in `case` - # statements. + # Returns `true` or `false`. + # + # Like Object#==, if `object` is an instance of Object (and not an instance of + # one of its many subclasses). + # + # This method is commonly overridden by those subclasses, to provide meaningful + # semantics in `case` statements. # def ===: (false) -> true | (untyped obj) -> bool # - # Exclusive Or---If *obj* is `nil` or `false`, returns `false`; otherwise, - # returns `true`. + # Returns `false` if `object` is `nil` or `false`, `true` otherwise: + # + # nil ^ nil # => false + # nil ^ false # => false + # nil ^ Object.new # => true # def ^: (false | nil) -> false | (untyped obj) -> bool @@ -53,10 +68,14 @@ class FalseClass # - # Or---Returns `false` if *obj* is `nil` or `false`; `true` otherwise. + # Returns `false` if `object` is `nil` or `false`, `true` otherwise: + # + # nil | nil # => false + # nil | false # => false + # nil | Object.new # => true # def |: (nil | false) -> false | (untyped obj) -> bool diff --git a/core/file.rbs b/core/file.rbs index a82bfeb79..b96fba416 100644 --- a/core/file.rbs +++ b/core/file.rbs @@ -4,7 +4,7 @@ # Class File extends module FileTest, supporting such singleton methods as # `File.exist?`. # -# ### About the Examples +# ## About the Examples # # Many examples here use these variables: # @@ -643,7 +643,7 @@ # of an actual file in the underlying platform. # # Note that file permissions are quite different from the *mode* of a file -# stream (File object). See IO@Modes. +# stream (File object). # # In a File object, the permissions are available thus, where method `mode`, # despite its name, returns permissions: @@ -697,8 +697,7 @@ # # * Inherits from [class IO](rdoc-ref:IO@What-27s+Here), in particular, # methods for creating, reading, and writing files -# * Includes [module FileTest](rdoc-ref:FileTest@What-27s+Here). which -# provides dozens of additional methods. +# * Includes module FileTest, which provides dozens of additional methods. # # # Here, class File provides methods that are useful for: @@ -1441,7 +1440,7 @@ class File < IO # --> # Returns the string representation of the path # - # File.path("/dev/null") #=> "/dev/null" + # File.path(File::NULL) #=> "/dev/null" # File.path(Pathname.new("/tmp")) #=> "/tmp" # def self.path: (string | _ToPath path) -> String @@ -1972,170 +1971,375 @@ File::SEPARATOR: String File::Separator: String # -# File::Constants provides file-related constants. All possible file constants -# are listed in the documentation but they may not all be present on your -# platform. +# Module `File::Constants` defines file-related constants. # -# If the underlying platform doesn't define a constant the corresponding Ruby -# constant is not defined. +# There are two families of constants here: # -# Your platform documentations (e.g. man open(2)) may describe more detailed -# information. +# * Those having to do with [file +# access](rdoc-ref:File::Constants@File+Access). +# * Those having to do with [filename +# globbing](rdoc-ref:File::Constants@Filename+Globbing+Constants+-28File-3A- +# 3AFNM_-2A-29). +# +# +# File constants defined for the local process may be retrieved with method +# File::Constants.constants: +# +# File::Constants.constants.take(5) +# # => [:RDONLY, :WRONLY, :RDWR, :APPEND, :CREAT] +# +# ## File Access +# +# File-access constants may be used with optional argument `mode` in calls to +# the following methods: +# +# * File.new. +# * File.open. +# * IO.for_fd. +# * IO.new. +# * IO.open. +# * IO.popen. +# * IO.reopen. +# * IO.sysopen. +# * StringIO.new. +# * StringIO.open. +# * StringIO#reopen. +# +# +# ### Read/Write Access +# +# Read-write access for a stream may be specified by a file-access constant. +# +# The constant may be specified as part of a bitwise OR of other such constants. +# +# Any combination of the constants in this section may be specified. +# +# #### File::RDONLY +# +# Flag File::RDONLY specifies the the stream should be opened for reading only: +# +# filepath = '/tmp/t.tmp' +# f = File.new(filepath, File::RDONLY) +# f.write('Foo') # Raises IOError (not opened for writing). +# +# #### File::WRONLY +# +# Flag File::WRONLY specifies that the stream should be opened for writing only: +# +# f = File.new(filepath, File::WRONLY) +# f.read # Raises IOError (not opened for reading). +# +# #### File::RDWR +# +# Flag File::RDWR specifies that the stream should be opened for both reading +# and writing: +# +# f = File.new(filepath, File::RDWR) +# f.write('Foo') # => 3 +# f.rewind # => 0 +# f.read # => "Foo" +# +# ### File Positioning +# +# #### File::APPEND +# +# Flag File::APPEND specifies that the stream should be opened in append mode. +# +# Before each write operation, the position is set to end-of-stream. The +# modification of the position and the following write operation are performed +# as a single atomic step. +# +# #### File::TRUNC +# +# Flag File::TRUNC specifies that the stream should be truncated at its +# beginning. If the file exists and is successfully opened for writing, it is to +# be truncated to position zero; its ctime and mtime are updated. +# +# There is no effect on a FIFO special file or a terminal device. The effect on +# other file types is implementation-defined. The result of using File::TRUNC +# with File::RDONLY is undefined. +# +# ### Creating and Preserving +# +# #### File::CREAT +# +# Flag File::CREAT specifies that the stream should be created if it does not +# already exist. +# +# If the file exists: +# +# - Raise an exception if File::EXCL is also specified. +# - Otherwise, do nothing. +# +# If the file does not exist, then it is created. Upon successful completion, +# the atime, ctime, and mtime of the file are updated, and the ctime and mtime +# of the parent directory are updated. +# +# #### File::EXCL +# +# Flag File::EXCL specifies that the stream should not already exist; If flags +# File::CREAT and File::EXCL are both specified and the stream already exists, +# an exception is raised. +# +# The check for the existence and creation of the file is performed as an atomic +# operation. +# +# If both File::EXCL and File::CREAT are specified and the path names a symbolic +# link, an exception is raised regardless of the contents of the symbolic link. +# +# If File::EXCL is specified and File::CREAT is not specified, the result is +# undefined. +# +# ### POSIX File Constants +# +# Some file-access constants are defined only on POSIX-compliant systems; those +# are: +# +# * File::SYNC. +# * File::DSYNC. +# * File::RSYNC. +# * File::DIRECT. +# * File::NOATIME. +# * File::NOCTTY. +# * File::NOFOLLOW. +# * File::TMPFILE. +# +# +# #### File::SYNC, File::RSYNC, and File::DSYNC +# +# Flag File::SYNC, File::RSYNC, or File::DSYNC specifies synchronization of I/O +# operations with the underlying file system. +# +# These flags are valid only for POSIX-compliant systems. +# +# * File::SYNC specifies that all write operations (both data and metadata) +# are immediately to be flushed to the underlying storage device. This means +# that the data is written to the storage device, and the file's metadata +# (e.g., file size, timestamps, permissions) are also synchronized. This +# guarantees that data is safely stored on the storage medium before +# returning control to the calling program. This flag can have a significant +# impact on performance since it requires synchronous writes, which can be +# slower compared to asynchronous writes. +# +# * File::RSYNC specifies that any read operations on the file will not return +# until all outstanding write operations (those that have been issued but +# not completed) are also synchronized. This is useful when you want to read +# the most up-to-date data, which may still be in the process of being +# written. +# +# * File::DSYNC specifies that all *data* write operations are immediately to +# be flushed to the underlying storage device; this differs from File::SYNC, +# which requires that *metadata* also be synchronized. +# +# +# Note that the behavior of these flags may vary slightly depending on the +# operating system and filesystem being used. Additionally, using these flags +# can have an impact on performance due to the synchronous nature of the I/O +# operations, so they should be used judiciously, especially in +# performance-critical applications. +# +# #### File::NOCTTY +# +# Flag File::NOCTTY specifies that if the stream is a terminal device, that +# device does not become the controlling terminal for the process. +# +# Defined only for POSIX-compliant systems. +# +# #### File::DIRECT +# +# Flag File::DIRECT requests that cache effects of the I/O to and from the +# stream be minimized. +# +# Defined only for POSIX-compliant systems. +# +# #### File::NOATIME +# +# Flag File::NOATIME specifies that act of opening the stream should not modify +# its access time (atime). +# +# Defined only for POSIX-compliant systems. +# +# #### File::NOFOLLOW +# +# Flag File::NOFOLLOW specifies that if path is a symbolic link, it should not +# be followed. +# +# Defined only for POSIX-compliant systems. +# +# #### File::TMPFILE +# +# Flag File::TMPFILE specifies that the opened stream should be a new temporary +# file. +# +# Defined only for POSIX-compliant systems. +# +# ### Other File-Access Constants +# +# #### File::NONBLOCK +# +# When possible, the file is opened in nonblocking mode. Neither the open +# operation nor any subsequent I/O operations on the file will cause the calling +# process to wait. +# +# #### File::BINARY +# +# Flag File::BINARY specifies that the stream is to be accessed in binary mode. +# +# #### File::SHARE_DELETE (Windows Only) +# +# Flag File::SHARE_DELETE enables other processes to open the stream with delete +# access. +# +# If the stream is opened for (local) delete access without File::SHARE_DELETE, +# and another process attempts to open it with delete access, the attempt fails +# and the stream is not opened for that process. +# +# ## Locking +# +# Four file constants relate to stream locking; see File#flock: +# +# #### File::LOCK_EX +# +# Flag File::LOCK_EX specifies an exclusive lock; only one process a a time may +# lock the stream. +# +# #### File::LOCK_NB +# +# Flag File::LOCK_NB specifies non-blocking locking for the stream; may be +# combined with File::LOCK_EX or File::LOCK_SH. +# +# #### File::LOCK_SH +# +# Flag File::LOCK_SH specifies that multiple processes may lock the stream at +# the same time. +# +# #### File::LOCK_UN +# +# Flag File::LOCK_UN specifies that the stream is not to be locked. +# +# ## Filename Globbing Constants (File::FNM_*) +# +# Filename-globbing constants may be used with optional argument `flags` in +# calls to the following methods: +# +# * Dir.glob. +# * File.fnmatch. +# * Pathname#fnmatch. +# * Pathname.glob. +# * Pathname#glob. +# +# +# The constants are: +# +# #### File::FNM_CASEFOLD +# +# Flag File::FNM_CASEFOLD makes patterns case insensitive for File.fnmatch (but +# not Dir.glob). +# +# #### File::FNM_DOTMATCH +# +# Flag File::FNM_DOTMATCH makes the `'*'` pattern match a filename starting with +# `'.'`. +# +# #### File::FNM_EXTGLOB +# +# Flag File::FNM_EXTGLOB enables pattern `'{*a*,*b*}'`, which matches pattern +# '*a*' and pattern '*b*'; behaves like a [regexp union](rdoc-ref:Regexp.union) +# (e.g., `'(?:*a*|*b*)'`): +# +# pattern = '{LEGAL,BSDL}' +# Dir.glob(pattern) # => ["LEGAL", "BSDL"] +# Pathname.glob(pattern) # => [#, #] +# pathname.glob(pattern) # => [#, #] +# +# #### File::FNM_NOESCAPE +# +# Flag File::FNM_NOESCAPE disables `'\'` escaping. +# +# #### File::FNM_PATHNAME +# +# Flag File::FNM_PATHNAME specifies that patterns `'*'` and `'?'` do not match +# the directory separator (the value of constant File::SEPARATOR). +# +# #### File::FNM_SHORTNAME (Windows Only) +# +# Flag File::FNM_SHORTNAME Allows patterns to match short names if they exist. +# +# #### File::FNM_SYSCASE +# +# Flag File::FNM_SYSCASE specifies that case sensitivity is the same as in the +# underlying operating system; effective for File.fnmatch, but not Dir.glob. +# +# ## Other Constants +# +# #### File::NULL +# +# Flag File::NULL contains the string value of the null device: +# +# * On a Unix-like OS, `'/dev/null'`. +# * On Windows, `'NUL'`. # module File::Constants end -# -# append on each write -# File::Constants::APPEND: Integer -# -# disable line code conversion -# File::Constants::BINARY: Integer -# -# create file if it does not exist -# File::Constants::CREAT: Integer -# -# Try to minimize cache effects of the I/O to and from this file. -# File::Constants::DIRECT: Integer -# -# any write operation perform synchronously except some meta data -# File::Constants::DSYNC: Integer -# -# error if CREAT and the file exists -# File::Constants::EXCL: Integer -# -# Makes File.fnmatch patterns case insensitive (but not Dir.glob patterns). -# File::Constants::FNM_CASEFOLD: Integer -# -# The '*' wildcard matches filenames starting with "." in File.fnmatch and -# Dir.glob patterns -# File::Constants::FNM_DOTMATCH: Integer -# -# Allows file globbing through "{a,b}" in File.fnmatch patterns. -# File::Constants::FNM_EXTGLOB: Integer -# -# Disables escapes in File.fnmatch and Dir.glob patterns -# File::Constants::FNM_NOESCAPE: Integer -# -# Wildcards in File.fnmatch and Dir.glob patterns do not match directory -# separators -# File::Constants::FNM_PATHNAME: Integer -# -# Makes patterns to match short names if existing. Valid only on Microsoft -# Windows. -# File::Constants::FNM_SHORTNAME: Integer -# -# System default case insensitiveness, equals to FNM_CASEFOLD or 0. -# File::Constants::FNM_SYSCASE: Integer -# -# exclusive lock. see File#flock -# File::Constants::LOCK_EX: Integer -# -# non-blocking lock. used with LOCK_SH or LOCK_EX. see File#flock -# File::Constants::LOCK_NB: Integer -# -# shared lock. see File#flock -# File::Constants::LOCK_SH: Integer -# -# unlock. see File#flock -# File::Constants::LOCK_UN: Integer -# -# do not change atime -# File::Constants::NOATIME: Integer -# -# not to make opened IO the controlling terminal device -# File::Constants::NOCTTY: Integer -# -# do not follow symlinks -# File::Constants::NOFOLLOW: Integer -# -# do not block on open or for data to become available -# File::Constants::NONBLOCK: Integer -# -# Name of the null device -# File::Constants::NULL: String -# -# open for reading only -# File::Constants::RDONLY: Integer -# -# open for reading and writing -# File::Constants::RDWR: Integer -# -# any read operation perform synchronously. used with SYNC or DSYNC. -# File::Constants::RSYNC: Integer -# -# can delete opened file -# File::Constants::SHARE_DELETE: Integer -# -# any write operation perform synchronously -# File::Constants::SYNC: Integer -# -# Create an unnamed temporary file -# File::Constants::TMPFILE: Integer -# -# truncate size to 0 -# File::Constants::TRUNC: Integer -# -# open for writing only -# File::Constants::WRONLY: Integer # @@ -2151,8 +2355,10 @@ class File::Stat < Object # + # File::Stat.new(file_name) -> stat + # # Create a File::Stat object for the given file name (raising an exception if # the file doesn't exist). # @@ -2554,7 +2760,7 @@ class File::Stat < Object # Returns `nil` if *stat* is a zero-length file, the size of the file otherwise. # # File.stat("testfile").size? #=> 66 - # File.stat("/dev/null").size? #=> nil + # File.stat(File::NULL).size? #=> nil # def size?: () -> Integer? diff --git a/core/float.rbs b/core/float.rbs index 46b17be8a..4bea96531 100644 --- a/core/float.rbs +++ b/core/float.rbs @@ -6,8 +6,8 @@ # should know its esoteric system. See following: # # * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html -# * https://github.com/rdp/ruby_tutorials_core/wiki/Ruby-Talk-FAQ#floats_impre -# cise +# * https://github.com/rdp/ruby_tutorials_core/wiki/Ruby-Talk-FAQ#-why-are-rub +# ys-floats-imprecise # * https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems # # @@ -109,8 +109,6 @@ class Float < Numeric # 10.0 % 4.0 # => 2.0 # 10.0 % Rational(4, 1) # => 2.0 # - # Float#modulo is an alias for Float#%. - # def %: (Integer) -> Float | (Float) -> Float | (Rational) -> Float @@ -181,9 +179,9 @@ class Float < Numeric # - # Returns `float`, negated. + # Returns `self`, negated. # def -@: () -> Float @@ -326,16 +324,13 @@ class Float < Numeric # - # Returns the absolute value of `float`. - # - # (-34.56).abs #=> 34.56 - # -34.56.abs #=> 34.56 - # 34.56.abs #=> 34.56 + # Returns the absolute value of `self`: # - # Float#magnitude is an alias for Float#abs. + # (-34.56).abs # => 34.56 + # -34.56.abs # => 34.56 + # 34.56.abs # => 34.56 # def abs: () -> Float @@ -481,8 +476,6 @@ class Float < Numeric # f.quo(Rational(2, 1)) # => 1.57 # f.quo(Complex(2, 0)) # => (1.57+0.0i) # - # Float#fdiv is an alias for Float#quo. - # def fdiv: (Complex) -> Complex | (Numeric) -> Float @@ -630,8 +623,6 @@ class Float < Numeric # 10.0 % 4.0 # => 2.0 # 10.0 % Rational(4, 1) # => 2.0 # - # Float#modulo is an alias for Float#%. - # def modulo: (Numeric) -> Float # - # Returns `true` if `float` is less than 0. + # Returns `true` if `self` is less than 0, `false` otherwise. # def negative?: () -> bool @@ -725,9 +716,9 @@ class Float < Numeric # - # Returns `true` if `float` is greater than 0. + # Returns `true` if `self` is greater than 0, `false` otherwise. # def positive?: () -> bool @@ -779,8 +770,6 @@ class Float < Numeric # f.quo(Rational(2, 1)) # => 1.57 # f.quo(Complex(2, 0)) # => (1.57+0.0i) # - # Float#fdiv is an alias for Float#quo. - # def quo: (Complex) -> Complex | (Numeric) -> Float @@ -875,9 +864,9 @@ class Float < Numeric # - # Since `float` is already a Float, returns `self`. + # Returns `self` (which is already a Float). # def to_f: () -> Float @@ -895,8 +884,6 @@ class Float < Numeric # # (0.3 / 0.1).to_i # => 2 (!) # - # Float#to_int is an alias for Float#to_i. - # def to_i: () -> Integer # @@ -910,8 +897,6 @@ class Float < Numeric # # (0.3 / 0.1).to_i # => 2 (!) # - # Float#to_int is an alias for Float#to_i. - # alias to_int to_i # - # Returns `true` if `float` is 0.0. + # Returns `true` if `self` is 0.0, `false` otherwise. # def zero?: () -> bool end diff --git a/core/gc.rbs b/core/gc.rbs index f572fc30f..89ebd296e 100644 --- a/core/gc.rbs +++ b/core/gc.rbs @@ -44,21 +44,27 @@ module GC # # Initiates garbage collection, even if manually disabled. # - # This method is defined with keyword arguments that default to true: + # The `full_mark` keyword argument determines whether or not to perform a major + # garbage collection cycle. When set to `true`, a major garbage collection cycle + # is ran, meaning all objects are marked. When set to `false`, a minor garbage + # collection cycle is ran, meaning only young objects are marked. # - # def GC.start(full_mark: true, immediate_sweep: true); end + # The `immediate_mark` keyword argument determines whether or not to perform + # incremental marking. When set to `true`, marking is completed during the call + # to this method. When set to `false`, marking is performed in steps that is + # interleaved with future Ruby code execution, so marking might not be completed + # during this method call. Note that if `full_mark` is `false` then marking will + # always be immediate, regardless of the value of `immediate_mark`. # - # Use full_mark: false to perform a minor GC. Use immediate_sweep: false to - # defer sweeping (use lazy sweep). + # The `immedate_sweep` keyword argument determines whether or not to defer + # sweeping (using lazy sweep). When set to `true`, sweeping is performed in + # steps that is interleaved with future Ruby code execution, so sweeping might + # not be completed during this method call. When set to `false`, sweeping is + # completed during the call to this method. # # Note: These keyword arguments are implementation and version dependent. They # are not guaranteed to be future-compatible, and may be ignored if the @@ -258,7 +264,7 @@ module GC end # -# internal constants +# Internal constants in the garbage collector. # GC::INTERNAL_CONSTANTS: Hash[Symbol, Integer] diff --git a/core/hash.rbs b/core/hash.rbs index 76152a112..a645068be 100644 --- a/core/hash.rbs +++ b/core/hash.rbs @@ -247,7 +247,7 @@ # alias eql? == # # def hash -# @author.hash ^ @title.hash # XOR +# [self.class, @author, @title].hash # end # end # @@ -345,6 +345,10 @@ # Note that setting the default proc will clear the default value and vice # versa. # +# Be aware that a default proc that modifies the hash is not thread-safe in the +# sense that multiple threads can call into the default proc concurrently for +# the same key. +# # ### What's Here # # First, what's elsewhere. Class Hash: @@ -412,7 +416,7 @@ # * #<=: Returns whether `self` is a subset of a given object. # * #==: Returns whether a given object is equal to `self`. # * #>: Returns whether `self` is a proper superset of a given object -# * #>=: Returns whether `self` is a proper superset of a given object. +# * #>=: Returns whether `self` is a superset of a given object. # # # #### Methods for Fetching @@ -652,8 +656,6 @@ class Hash[unchecked out K, unchecked out V] < Object # - hash[key] = value -> value # - hash.store(key, value) # --> - # Hash#store is an alias for Hash#[]=. - # # Associates the given `value` with the given `key`; returns `value`. # # If the given `key` exists, replaces its value with the given `value`; the @@ -680,6 +682,8 @@ class Hash[unchecked out K, unchecked out V] < Object # --> # Returns `true` if any element satisfies a given criterion; `false` otherwise. # + # If `self` has no element, returns `false` and argument or block are not used. + # # With no argument and no block, returns `true` if `self` is non-empty; `false` # if empty. # @@ -696,6 +700,8 @@ class Hash[unchecked out K, unchecked out V] < Object # h.any? {|key, value| value < 3 } # => true # h.any? {|key, value| value > 3 } # => false # + # Related: Enumerable#any? + # def any?: () -> bool | (untyped pattern) -> bool | () { (K, V) -> boolish } -> bool @@ -928,8 +934,6 @@ class Hash[unchecked out K, unchecked out V] < Object def dig: (K, *untyped) -> untyped # - # Hash#each is an alias for Hash#each_pair. - # # Calls the given block with each key-value pair; returns `self`: # h = {foo: 0, bar: 1, baz: 2} # h.each_pair {|key, value| puts "#{key}: #{value}"} # => {:foo=>0, :bar=>1, :baz=>2} @@ -988,8 +992,6 @@ class Hash[unchecked out K, unchecked out V] < Object # - hash.each -> new_enumerator # - hash.each_pair -> new_enumerator # --> - # Hash#each is an alias for Hash#each_pair. - # # Calls the given block with each key-value pair; returns `self`: # h = {foo: 0, bar: 1, baz: 2} # h.each_pair {|key, value| puts "#{key}: #{value}"} # => {:foo=>0, :bar=>1, :baz=>2} @@ -1133,8 +1135,6 @@ class Hash[unchecked out K, unchecked out V] < Object | [X] (*K) { (K) -> X } -> ::Array[V | X] # - # Hash#filter is an alias for Hash#select. - # # Returns a new Hash object whose entries are those for which the block returns # a truthy value: # h = {foo: 0, bar: 1, baz: 2} @@ -1149,8 +1149,6 @@ class Hash[unchecked out K, unchecked out V] < Object | () -> ::Enumerator[[ K, V ], ::Hash[K, V]] # - # Hash#filter! is an alias for Hash#select!. - # # Returns `self`, whose entries are those for which the block returns a truthy # value: # h = {foo: 0, bar: 1, baz: 2} @@ -1201,8 +1199,6 @@ class Hash[unchecked out K, unchecked out V] < Object | (Integer level) -> Array[untyped] # - # Methods #has_key?, #key?, and #member? are aliases for #include?. - # # Returns `true` if `key` is a key in `self`, otherwise `false`. # def has_key?: (K arg0) -> bool @@ -1212,8 +1208,6 @@ class Hash[unchecked out K, unchecked out V] < Object # - hash.has_value?(value) -> true or false # - hash.value?(value) -> true or false # --> - # Method #value? is an alias for #has_value?. - # # Returns `true` if `value` is a value in `self`, otherwise `false`. # def has_value?: (V arg0) -> bool @@ -1225,7 +1219,7 @@ class Hash[unchecked out K, unchecked out V] < Object # Returns the Integer hash-code for the hash. # # Two Hash objects have the same hash-code if their content is the same - # (regardless or order): + # (regardless of order): # h1 = {foo: 0, bar: 1, baz: 2} # h2 = {baz: 2, bar: 1, foo: 0} # h2.hash == h1.hash # => true @@ -1240,8 +1234,6 @@ class Hash[unchecked out K, unchecked out V] < Object # - hash.key?(key) -> true or false # - hash.member?(key) -> true or false # --> - # Methods #has_key?, #key?, and #member? are aliases for #include?. - # # Returns `true` if `key` is a key in `self`, otherwise `false`. # alias include? has_key? @@ -1251,11 +1243,10 @@ class Hash[unchecked out K, unchecked out V] < Object # - hash.inspect -> new_string # --> # Returns a new String containing the hash entries: + # # h = {foo: 0, bar: 1, baz: 2} # h.inspect # => "{:foo=>0, :bar=>1, :baz=>2}" # - # Hash#to_s is an alias for Hash#inspect. - # def inspect: () -> String # - # Methods #has_key?, #key?, and #member? are aliases for #include?. - # # Returns `true` if `key` is a key in `self`, otherwise `false`. # alias key? has_key? @@ -1325,15 +1314,12 @@ class Hash[unchecked out K, unchecked out V] < Object # # Returns the count of entries in `self`: - # {foo: 0, bar: 1, baz: 2}.length # => 3 # - # Hash#length is an alias for Hash#size. + # {foo: 0, bar: 1, baz: 2}.length # => 3 # def length: () -> Integer # - # Methods #has_key?, #key?, and #member? are aliases for #include?. - # # Returns `true` if `key` is a key in `self`, otherwise `false`. # alias member? has_key? @@ -1400,8 +1386,6 @@ class Hash[unchecked out K, unchecked out V] < Object # # Each argument in `other_hashes` must be a Hash. # - # Method #update is an alias for #merge!. - # # With arguments and no block: # * Returns `self`, after the given hashes are merged into it. # * The given hashes are merged left to right. @@ -1526,8 +1510,6 @@ class Hash[unchecked out K, unchecked out V] < Object # - hash.select {|key, value| ... } -> new_hash # - hash.select -> new_enumerator # --> - # Hash#filter is an alias for Hash#select. - # # Returns a new Hash object whose entries are those for which the block returns # a truthy value: # h = {foo: 0, bar: 1, baz: 2} @@ -1545,8 +1527,6 @@ class Hash[unchecked out K, unchecked out V] < Object # - hash.select! {|key, value| ... } -> self or nil # - hash.select! -> new_enumerator # --> - # Hash#filter! is an alias for Hash#select!. - # # Returns `self`, whose entries are those for which the block returns a truthy # value: # h = {foo: 0, bar: 1, baz: 2} @@ -1581,9 +1561,8 @@ class Hash[unchecked out K, unchecked out V] < Object # - hash.size -> integer # --> # Returns the count of entries in `self`: - # {foo: 0, bar: 1, baz: 2}.length # => 3 # - # Hash#length is an alias for Hash#size. + # {foo: 0, bar: 1, baz: 2}.length # => 3 # alias size length @@ -1600,8 +1579,6 @@ class Hash[unchecked out K, unchecked out V] < Object def slice: (*K) -> ::Hash[K, V] # - # Hash#store is an alias for Hash#[]=. - # # Associates the given `value` with the given `key`; returns `value`. # # If the given `key` exists, replaces its value with the given `value`; the @@ -1674,11 +1651,10 @@ class Hash[unchecked out K, unchecked out V] < Object # # Returns a new String containing the hash entries: + # # h = {foo: 0, bar: 1, baz: 2} # h.inspect # => "{:foo=>0, :bar=>1, :baz=>2}" # - # Hash#to_s is an alias for Hash#inspect. - # alias to_s inspect # - # Method #value? is an alias for #has_value?. - # # Returns `true` if `value` is a value in `self`, otherwise `false`. # alias value? has_value? diff --git a/core/integer.rbs b/core/integer.rbs index e60235e06..76a5616bf 100644 --- a/core/integer.rbs +++ b/core/integer.rbs @@ -131,7 +131,7 @@ class Integer < Numeric def self.sqrt: (int n) -> Integer # # If `object` is an Integer object, returns `object`. @@ -178,8 +178,6 @@ class Integer < Numeric # 10 % 3.0 # => 1.0 # 10 % Rational(3, 1) # => (1/1) # - # Integer#modulo is an alias for Integer#%. - # def %: (Float) -> Float | (Rational) -> Rational | (Integer) -> Integer @@ -277,9 +275,9 @@ class Integer < Numeric # - # Returns `int`, negated. + # Returns `self`, negated. # def -@: () -> Integer @@ -391,8 +389,6 @@ class Integer < Numeric # # Related: Integer#eql? (requires `other` to be an Integer). # - # Integer#=== is an alias for Integer#==. - # def ==: (untyped) -> bool # - # Returns the absolute value of `int`. + # Returns the absolute value of `self`. # - # (-12345).abs #=> 12345 - # -12345.abs #=> 12345 - # 12345.abs #=> 12345 - # - # Integer#magnitude is an alias for Integer#abs. + # (-12345).abs # => 12345 + # -12345.abs # => 12345 + # 12345.abs # => 12345 # def abs: () -> Integer @@ -586,44 +577,43 @@ class Integer < Numeric # - # Returns the number of bits of the value of `int`. - # - # "Number of bits" means the bit position of the highest bit which is different - # from the sign bit (where the least significant bit has bit position 1). If - # there is no such bit (zero or minus one), zero is returned. - # - # I.e. this method returns *ceil(log2(int < 0 ? -int : int+1))*. - # - # (-2**1000-1).bit_length #=> 1001 - # (-2**1000).bit_length #=> 1000 - # (-2**1000+1).bit_length #=> 1000 - # (-2**12-1).bit_length #=> 13 - # (-2**12).bit_length #=> 12 - # (-2**12+1).bit_length #=> 12 - # -0x101.bit_length #=> 9 - # -0x100.bit_length #=> 8 - # -0xff.bit_length #=> 8 - # -2.bit_length #=> 1 - # -1.bit_length #=> 0 - # 0.bit_length #=> 0 - # 1.bit_length #=> 1 - # 0xff.bit_length #=> 8 - # 0x100.bit_length #=> 9 - # (2**12-1).bit_length #=> 12 - # (2**12).bit_length #=> 13 - # (2**12+1).bit_length #=> 13 - # (2**1000-1).bit_length #=> 1000 - # (2**1000).bit_length #=> 1001 - # (2**1000+1).bit_length #=> 1001 - # - # This method can be used to detect overflow in Array#pack as follows: + # Returns the number of bits of the value of `self`, which is the bit position + # of the highest-order bit that is different from the sign bit (where the least + # significant bit has bit position 1). If there is no such bit (zero or minus + # one), returns zero. + # + # This method returns `ceil(log2(self < 0 ? -self : self + 1))`>. + # + # (-2**1000-1).bit_length # => 1001 + # (-2**1000).bit_length # => 1000 + # (-2**1000+1).bit_length # => 1000 + # (-2**12-1).bit_length # => 13 + # (-2**12).bit_length # => 12 + # (-2**12+1).bit_length # => 12 + # -0x101.bit_length # => 9 + # -0x100.bit_length # => 8 + # -0xff.bit_length # => 8 + # -2.bit_length # => 1 + # -1.bit_length # => 0 + # 0.bit_length # => 0 + # 1.bit_length # => 1 + # 0xff.bit_length # => 8 + # 0x100.bit_length # => 9 + # (2**12-1).bit_length # => 12 + # (2**12).bit_length # => 13 + # (2**12+1).bit_length # => 13 + # (2**1000-1).bit_length # => 1000 + # (2**1000).bit_length # => 1001 + # (2**1000+1).bit_length # => 1001 + # + # For Integer *n*, this method can be used to detect overflow in Array#pack: # # if n.bit_length < 32 - # [n].pack("l") # no overflow + # [n].pack('l') # No overflow. # else - # raise "overflow" + # raise 'Overflow' # end # def bit_length: () -> Integer @@ -655,16 +645,16 @@ class Integer < Numeric # - # Returns the result of division `self` by `other`. The result is rounded up to - # the nearest integer. + # Returns the result of division `self` by `numeric`. rounded up to the nearest + # integer. # - # 3.ceildiv(3) # => 1 - # 4.ceildiv(3) # => 2 + # 3.ceildiv(3) # => 1 + # 4.ceildiv(3) # => 2 # - # 4.ceildiv(-3) # => -1 - # -4.ceildiv(3) # => -1 + # 4.ceildiv(-3) # => -1 + # -4.ceildiv(3) # => -1 # -4.ceildiv(-3) # => 2 # # 3.ceildiv(1.2) # => 3 @@ -712,9 +702,9 @@ class Integer < Numeric # - # Returns 1. + # Returns `1`. # def denominator: () -> Integer @@ -806,9 +796,9 @@ class Integer < Numeric # - # Returns `true` if `int` is an even number. + # Returns `true` if `self` is an even number, `false` otherwise. # def even?: () -> bool @@ -904,15 +894,13 @@ class Integer < Numeric # # Raises an exception if `base` is out of range. # - # Integer#inspect is an alias for Integer#to_s. - # alias inspect to_s # - # Since `int` is already an Integer, this always returns `true`. + # Since `self` is already an Integer, always returns `true`. # def integer?: () -> true @@ -961,8 +949,6 @@ class Integer < Numeric # 10 % 3.0 # => 1.0 # 10 % Rational(3, 1) # => (1/1) # - # Integer#modulo is an alias for Integer#%. - # alias modulo % def negative?: () -> bool @@ -973,8 +959,6 @@ class Integer < Numeric # 1.succ #=> 2 # -1.succ #=> 0 # - # Integer#next is an alias for Integer#succ. - # # Related: Integer#pred (predecessor value). # def next: () -> Integer @@ -1006,31 +990,25 @@ class Integer < Numeric # - # Returns self. + # Returns `self`. # def numerator: () -> Integer # - # Returns `true` if `int` is an odd number. + # Returns `true` if `self` is an odd number, `false` otherwise. # def odd?: () -> bool # - # Returns the `int` itself. - # - # 97.ord #=> 97 - # - # This method is intended for compatibility to character literals in Ruby 1.9. - # - # For example, `?a.ord` returns 97 both in 1.8 and 1.9. + # Returns `self`; intended for compatibility to character literals in Ruby 1.9. # def ord: () -> Integer @@ -1168,19 +1146,17 @@ class Integer < Numeric # - # Document-method: Integer#size + # Returns the number of bytes in the machine representation of `self`; the value + # is system-dependent: # - # Returns the number of bytes in the machine representation of `int` (machine - # dependent). - # - # 1.size #=> 8 - # -1.size #=> 8 - # 2147483647.size #=> 8 - # (256**10 - 1).size #=> 10 - # (256**20 - 1).size #=> 20 - # (256**40 - 1).size #=> 40 + # 1.size # => 8 + # -1.size # => 8 + # 2147483647.size # => 8 + # (256**10 - 1).size # => 10 + # (256**20 - 1).size # => 20 + # (256**40 - 1).size # => 40 # def size: () -> Integer @@ -1204,14 +1180,12 @@ class Integer < Numeric # 1.succ #=> 2 # -1.succ #=> 0 # - # Integer#next is an alias for Integer#succ. - # # Related: Integer#pred (predecessor value). # def succ: () -> Integer # @@ -1246,19 +1220,17 @@ class Integer < Numeric # - # Since `int` is already an Integer, returns `self`. - # - # #to_int is an alias for #to_i. + # Returns `self` (which is already an Integer). # def to_i: () -> Integer # - # Since `int` is already an Integer, returns `self`. + # Returns `self` (which is already an Integer). # alias to_int to_i @@ -1290,8 +1262,6 @@ class Integer < Numeric # # Raises an exception if `base` is out of range. # - # Integer#inspect is an alias for Integer#to_s. - # def to_s: () -> String | (2) -> String | (3) -> String @@ -1377,9 +1347,9 @@ class Integer < Numeric # - # Returns `true` if `int` has a zero value. + # Returns `true` if `self` has a zero value, `false` otherwise. # def zero?: () -> bool @@ -1400,16 +1370,15 @@ class Integer < Numeric # - # One's complement: returns a number where each bit is flipped. + # One's complement: returns the value of `self` with each bit inverted. # - # Inverts the bits in an Integer. As integers are conceptually of infinite - # length, the result acts as if it had an infinite number of one bits to the - # left. In hex representations, this is displayed as two periods to the left of - # the digits. + # Because an integer value is conceptually of infinite length, the result acts + # as if it had an infinite number of one bits to the left. In hex + # representations, this is displayed as two periods to the left of the digits: # - # sprintf("%X", ~0x1122334455) #=> "..FEEDDCCBBAA" + # sprintf("%X", ~0x1122334455) # => "..FEEDDCCBBAA" # def ~: () -> Integer end diff --git a/core/io.rbs b/core/io.rbs index 16b43cc2c..5b878f0b9 100644 --- a/core/io.rbs +++ b/core/io.rbs @@ -110,7 +110,7 @@ # # # Also available are the options offered in String#encode, which may control -# conversion between external internal encoding. +# conversion between external and internal encoding. # # ## Basic IO # @@ -398,7 +398,7 @@ # # => 41 # f.close # -# * When a stream is read, `#.` is set to the line number for that stream: +# * When a stream is read, `$.` is set to the line number for that stream: # # f0 = File.new('t.txt') # f1 = File.new('t.dat') @@ -684,14 +684,14 @@ class IO < Object # --> # Sets auto-close flag. # - # f = open("/dev/null") - # IO.for_fd(f.fileno) - # # ... - # f.gets # may cause Errno::EBADF + # f = File.open(File::NULL) + # IO.for_fd(f.fileno).close + # f.gets # raises Errno::EBADF # - # f = open("/dev/null") - # IO.for_fd(f.fileno).autoclose = false - # # ... + # f = File.open(File::NULL) + # g = IO.for_fd(f.fileno) + # g.autoclose = false + # g.close # f.gets # won't cause Errno::EBADF # def autoclose=: (boolish bool) -> boolish @@ -700,8 +700,8 @@ class IO < Object # rdoc-file=io.c # - ios.autoclose? -> true or false # --> - # Returns `true` if the underlying file descriptor of *ios* will be closed - # automatically at its finalization, otherwise `false`. + # Returns `true` if the underlying file descriptor of *ios* will be closed at + # its finalization or at calling #close, otherwise `false`. # def autoclose?: () -> bool @@ -764,7 +764,7 @@ class IO < Object # --> # Sets a close-on-exec flag. # - # f = open("/dev/null") + # f = File.open(File::NULL) # f.close_on_exec = true # system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory # f.closed? #=> false @@ -976,8 +976,6 @@ class IO < Object # not behave as you intend with IO#eof?, unless you call IO#rewind first (which # is not available for some streams). # - # IO#eof? is an alias for IO#eof. - # def eof: () -> bool # # See [Encodings](rdoc-ref:File@Encodings). # - # Argument `ext_enc`, if given, must be an Encoding object; it is assigned as - # the encoding for the stream. + # Argument `ext_enc`, if given, must be an Encoding object or a String with the + # encoding name; it is assigned as the encoding for the stream. # - # Argument `int_enc`, if given, must be an Encoding object; it is assigned as - # the encoding for the internal string. + # Argument `int_enc`, if given, must be an Encoding object or a String with the + # encoding name; it is assigned as the encoding for the internal string. # # Argument `'ext_enc:int_enc'`, if given, is a string containing two # colon-separated encoding names; corresponding Encoding objects are assigned as # the external and internal encodings for the stream. # + # If the external encoding of a string is binary/ASCII-8BIT, the internal + # encoding of the string is set to nil, since no transcoding is needed. + # # Optional keyword arguments `enc_opts` specify [Encoding # options](rdoc-ref:encodings.rdoc@Encoding+Options). # @@ -2067,8 +2064,6 @@ class IO < Object # # Related: IO#pos=, IO#seek. # - # IO#pos is an alias for IO#tell. - # def tell: () -> Integer # @@ -2083,8 +2078,6 @@ class IO < Object # # Related: IO#pos=, IO#seek. # - # IO#pos is an alias for IO#tell. - # alias pos tell # - # Set the internal timeout to the specified duration or nil. The timeout applies - # to all blocking operations where possible. + # Sets the internal timeout to the specified duration or nil. The timeout + # applies to all blocking operations where possible. + # + # When the operation performs longer than the timeout set, IO::TimeoutError is + # raised. # # This affects the following methods (but is not limited to): #gets, #puts, # #read, #write, #wait_readable and #wait_writable. This also affects blocking @@ -2132,8 +2128,6 @@ class IO < Object # f = File.new('/dev/tty').isatty #=> true # f.close # - # IO#tty? is an alias for IO#isatty. - # alias tty? isatty # # Behaves like IO.read, except that the stream is opened in binary mode with @@ -2313,7 +2306,6 @@ class IO < Object # # Behaves like IO.write, except that the stream is opened in binary mode with @@ -2551,9 +2543,6 @@ class IO < Object # - IO.foreach(path, sep = $/, **opts) {|line| block } -> nil # - IO.foreach(path, limit, **opts) {|line| block } -> nil # - IO.foreach(path, sep, limit, **opts) {|line| block } -> nil - # - IO.foreach(command, sep = $/, **opts) {|line| block } -> nil - # - IO.foreach(command, limit, **opts) {|line| block } -> nil - # - IO.foreach(command, sep, limit, **opts) {|line| block } -> nil # - IO.foreach(...) -> an_enumerator # --> # Calls the block with each successive line read from the stream. @@ -2562,17 +2551,7 @@ class IO < Object # potential security vulnerabilities if called with untrusted input; see # [Command Injection](rdoc-ref:command_injection.rdoc). # - # The first argument must be a string that is one of the following: - # - # * Path: if `self` is a subclass of IO (File, for example), or if the string - # *does* *not* start with the pipe character (`'|'`), the string is the path - # to a file. - # * Command: if `self` is the class IO, and if the string starts with the pipe - # character, the rest of the string is a command to be executed as a - # subprocess. This usage has potential security vulnerabilities if called - # with untrusted input; see [Command - # Injection](rdoc-ref:command_injection.rdoc). - # + # The first argument must be a string that is the path to a file. # # With only argument `path` given, parses lines from the file at the given # `path`, as determined by the default line separator, and calls the block with @@ -2632,7 +2611,7 @@ class IO < Object # # * [Open Options](rdoc-ref:IO@Open+Options). # * [Encoding options](rdoc-ref:encodings.rdoc@Encoding+Options). - # * [Line Options](rdoc-ref:IO@Line+Options). + # * [Line Options](rdoc-ref:IO@Line+IO). # # # Returns an Enumerator if no block is given. @@ -2645,9 +2624,9 @@ class IO < Object # - IO.pipe(**opts) -> [read_io, write_io] # - IO.pipe(enc, **opts) -> [read_io, write_io] # - IO.pipe(ext_enc, int_enc, **opts) -> [read_io, write_io] - # - IO.pipe(**opts) {|read_io, write_io] ...} -> object - # - IO.pipe(enc, **opts) {|read_io, write_io] ...} -> object - # - IO.pipe(ext_enc, int_enc, **opts) {|read_io, write_io] ...} -> object + # - IO.pipe(**opts) {|read_io, write_io| ...} -> object + # - IO.pipe(enc, **opts) {|read_io, write_io| ...} -> object + # - IO.pipe(ext_enc, int_enc, **opts) {|read_io, write_io| ...} -> object # --> # Creates a pair of pipe endpoints, `read_io` and `write_io`, connected to each # other. @@ -2723,7 +2702,6 @@ class IO < Object # # Opens the stream, reads and returns some or all of its content, and closes the @@ -2733,19 +2711,7 @@ class IO < Object # potential security vulnerabilities if called with untrusted input; see # [Command Injection](rdoc-ref:command_injection.rdoc). # - # The first argument must be a string; its meaning depends on whether it starts - # with the pipe character (`'|'`): - # - # * If so (and if `self` is IO), the rest of the string is a command to be - # executed as a subprocess. - # * Otherwise, the string is the path to a file. - # - # - # With only argument `command` given, executes the command in a shell, returns - # its entire $stdout: - # - # IO.read('| cat t.txt') - # # => "First line\nSecond line\n\nThird line\nFourth line\n" + # The first argument must be a string that is the path to a file. # # With only argument `path` given, reads in text mode and returns the entire # content of the file at the given path: @@ -2757,8 +2723,6 @@ class IO < Object # when encountering certain special bytes. Consider using IO.binread if all # bytes in the file should be read. # - # For both forms, command and path, the remaining arguments are the same. - # # With argument `length`, returns `length` bytes if available: # # IO.read('t.txt', 7) # => "First l" @@ -2780,9 +2744,6 @@ class IO < Object # # Opens the stream, writes the given `data` to it, and closes the stream; @@ -3033,25 +2978,10 @@ class IO < Object # potential security vulnerabilities if called with untrusted input; see # [Command Injection](rdoc-ref:command_injection.rdoc). # - # The first argument must be a string; its meaning depends on whether it starts - # with the pipe character (`'|'`): - # - # * If so (and if `self` is IO), the rest of the string is a command to be - # executed as a subprocess. - # * Otherwise, the string is the path to a file. - # + # The first argument must be a string that is the path to a file. # - # With argument `command` given, executes the command in a shell, passes `data` - # through standard input, writes its output to $stdout, and returns the length - # of the given `data`: - # - # IO.write('| cat', 'Hello World!') # => 12 - # - # Output: - # - # Hello World! - # - # With argument `path` given, writes the given `data` to the file at that path: + # With only argument `path` given, writes the given `data` to the file at that + # path: # # IO.write('t.tmp', 'abc') # => 3 # File.read('t.tmp') # => "abc" @@ -3201,8 +3131,6 @@ class IO < Object # # Returns an Enumerator if no block is given. # - # IO#each is an alias for IO#each_line. - # def each_line: (?String sep, ?Integer limit) { (String line) -> void } -> self | (?String sep, ?Integer limit) -> ::Enumerator[String, self] @@ -3308,8 +3236,6 @@ class IO < Object # # Returns an Enumerator if no block is given. # - # IO#each is an alias for IO#each_line. - # alias each each_line # @@ -3343,8 +3269,6 @@ class IO < Object # not behave as you intend with IO#eof?, unless you call IO#rewind first (which # is not available for some streams). # - # IO#eof? is an alias for IO#eof. - # alias eof? eof # @@ -3356,8 +3280,6 @@ class IO < Object # File.open('t.txt').fileno # => 10 # f.close # - # IO#to_i is an alias for IO#fileno. - # alias to_i fileno end diff --git a/core/io/buffer.rbs b/core/io/buffer.rbs index bdb0eb96c..cebf6ed73 100644 --- a/core/io/buffer.rbs +++ b/core/io/buffer.rbs @@ -4,8 +4,8 @@ class IO # IO::Buffer is a low-level efficient buffer for input/output. There are three # ways of using buffer: # - # * Create an empty buffer with ::new, fill it with data using #copy or - # #set_value, #set_string, get data with #get_string; + # * Create an empty buffer with ::new, fill it with buffer using #copy or + # #set_value, #set_string, get buffer with #get_string; # * Create a buffer mapped to some string with ::for, then it could be used # both for reading with #get_string or #get_value, and writing (writing will # change the source string, too); @@ -39,7 +39,7 @@ class IO # # Buffer from string: # - # string = 'data' + # string = 'buffer' # buffer = IO::Buffer.for(string) # # => # # # @@ -47,7 +47,7 @@ class IO # buffer # # => # # # - # # 0x00000000 64 61 74 61 data + # # 0x00000000 64 61 74 61 buffer # # buffer.get_string(2) # read content starting from offset 2 # # => "ta" @@ -62,7 +62,7 @@ class IO # # Buffer from file: # - # File.write('test.txt', 'test data') + # File.write('test.txt', 'test buffer') # # => 9 # buffer = IO::Buffer.map(File.open('test.txt')) # # => @@ -79,7 +79,7 @@ class IO # buffer.set_string('---', 1) # # => 3 -- bytes written # File.read('test.txt') - # # => "t--- data" + # # => "t--- buffer" # # **The class is experimental and the interface is subject to change.** # @@ -94,13 +94,14 @@ class IO # Creates a IO::Buffer from the given string's memory. Without a block a frozen # internal copy of the string is created efficiently and used as the buffer # source. When a block is provided, the buffer is associated directly with the - # string's internal data and updating the buffer will update the string. + # string's internal buffer and updating the buffer will update the string. # # Until #free is invoked on the buffer, either explicitly or via the garbage # collector, the source string will be locked and cannot be modified. # # If the string is frozen, it will create a read-only buffer which cannot be - # modified. + # modified. If the string is shared, it may trigger a copy-on-write when using + # the block form. # # string = 'test' # buffer = IO::Buffer.for(string) @@ -212,8 +213,8 @@ class IO # rdoc-file=io_buffer.c # - copy(source, [offset, [length, [source_offset]]]) -> size # --> - # Efficiently copy data from a source IO::Buffer into the buffer, at `offset` - # using `memcpy`. For copying String instances, see #set_string. + # Efficiently copy from a source IO::Buffer into the buffer, at `offset` using + # `memcpy`. For copying String instances, see #set_string. # # buffer = IO::Buffer.new(32) # # => @@ -222,22 +223,22 @@ class IO # # 0x00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * # # buffer.copy(IO::Buffer.for("test"), 8) - # # => 4 -- size of data copied + # # => 4 -- size of buffer copied # buffer # # => # # # # # 0x00000000 00 00 00 00 00 00 00 00 74 65 73 74 00 00 00 00 ........test.... # # 0x00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * # - # #copy can be used to put data into strings associated with buffer: + # #copy can be used to put buffer into strings associated with buffer: # - # string= "data: " - # # => "data: " + # string= "buffer: " + # # => "buffer: " # buffer = IO::Buffer.for(string) # buffer.copy(IO::Buffer.for("test"), 5) # # => 4 # string - # # => "data:test" + # # => "buffer:test" # # Attempt to copy into a read-only buffer will fail: # @@ -254,12 +255,12 @@ class IO # File.read('test.txt') # # => "boom" # - # Attempt to copy the data which will need place outside of buffer's bounds will - # fail: + # Attempt to copy the buffer which will need place outside of buffer's bounds + # will fail: # # buffer = IO::Buffer.new(2) # buffer.copy(IO::Buffer.for('test'), 0) - # # in `copy': Specified offset+length exceeds source size! (ArgumentError) + # # in `copy': Specified offset+length is bigger than the buffer size! (ArgumentError) # def copy: (Buffer source, ?Integer offset, ?Integer length, ?Integer source_offset) -> Integer @@ -336,9 +337,9 @@ class IO # - # Read from buffer a value of `type` at `offset`. `data_type` should be one of + # Read from buffer a value of `type` at `offset`. `buffer_type` should be one of # symbols: # # * `:U8`: unsigned integer, 1 byte @@ -361,9 +362,9 @@ class IO # * `:F64`: double, 8 bytes, big-endian # # - # A data type refers specifically to the type of binary data that is stored in - # the buffer. For example, a `:u32` data type is a 32-bit unsigned integer in - # little-endian format. + # A buffer type refers specifically to the type of binary buffer that is stored + # in the buffer. For example, a `:u32` buffer type is a 32-bit unsigned integer + # in little-endian format. # # Example: # @@ -493,13 +494,19 @@ class IO # - # Read at most `length` bytes from `io` into the buffer, starting at `from`, and - # put it in buffer starting from specified `offset`. If an error occurs, return + # Read at least `length` bytes from the `io` starting at the specified `from` + # position, into the buffer starting at `offset`. If an error occurs, return # `-errno`. # - # If `offset` is not given, put it at the beginning of the buffer. + # If `length` is not given or `nil`, it defaults to the size of the buffer minus + # the offset, i.e. the entire buffer. + # + # If `length` is zero, exactly one `pread` operation will occur. + # + # If `offset` is not given, it defaults to zero, i.e. the beginning of the + # buffer. # # Example: # @@ -522,14 +529,24 @@ class IO # - # Writes `length` bytes from buffer into `io`, starting at `offset` in the - # buffer. If an error occurs, return `-errno`. + # Write at least `length` bytes from the buffer starting at `offset`, into the + # `io` starting at the specified `from` position. If an error occurs, return + # `-errno`. + # + # If `length` is not given or `nil`, it defaults to the size of the buffer minus + # the offset, i.e. the entire buffer. + # + # If `length` is zero, exactly one `pwrite` operation will occur. + # + # If `offset` is not given, it defaults to zero, i.e. the beginning of the + # buffer. # - # If `offset` is not given, the bytes are taken from the beginning of the - # buffer. If the `offset` is given and is beyond the end of the file, the gap - # will be filled with null (0 value) bytes. + # If the `from` position is beyond the end of the file, the gap will be filled + # with null (0 value) bytes. + # + # Example: # # out = File.open('output.txt', File::RDWR) # open for read/write, no truncation # IO::Buffer.for('1234567').pwrite(out, 2, 3, 1) @@ -541,14 +558,18 @@ class IO # - # Read at most `length` bytes from `io` into the buffer, starting at `offset`. - # If an error occurs, return `-errno`. + # Read at least `length` bytes from the `io`, into the buffer starting at + # `offset`. If an error occurs, return `-errno`. # - # If `offset` is not given, read from the beginning of the buffer. + # If `length` is not given or `nil`, it defaults to the size of the buffer minus + # the offset, i.e. the entire buffer. # - # If `length` is 0, read nothing. + # If `length` is zero, exactly one `read` operation will occur. + # + # If `offset` is not given, it defaults to zero, i.e. the beginning of the + # buffer. # # Example: # @@ -600,15 +621,15 @@ class IO # rdoc-file=io_buffer.c # - set_string(string, [offset, [length, [source_offset]]]) -> size # --> - # Efficiently copy data from a source String into the buffer, at `offset` using - # `memcpy`. + # Efficiently copy buffer from a source String into the buffer, at `offset` + # using `memcpy`. # # buf = IO::Buffer.new(8) # # => # # # # # 0x00000000 00 00 00 00 00 00 00 00 ........ # - # # set data starting from offset 1, take 2 bytes starting from string's + # # set buffer starting from offset 1, take 2 bytes starting from string's # # second # buf.set_string('test', 1, 2, 1) # # => 2 @@ -667,7 +688,7 @@ class IO # # Produce another IO::Buffer which is a slice (or view into) the current one # starting at `offset` bytes and going for `length` bytes. @@ -762,7 +783,7 @@ class IO # rdoc-file=io_buffer.c # - valid? -> true or false # --> - # Returns whether the buffer data is accessible. + # Returns whether the buffer buffer is accessible. # # A buffer becomes invalid if it is a slice of another buffer which has been # freed. @@ -771,14 +792,21 @@ class IO # - # Writes `length` bytes from buffer into `io`, starting at `offset` in the - # buffer. If an error occurs, return `-errno`. + # Write at least `length` bytes from the buffer starting at `offset`, into the + # `io`. If an error occurs, return `-errno`. # - # If `offset` is not given, the bytes are taken from the beginning of the + # If `length` is not given or `nil`, it defaults to the size of the buffer minus + # the offset, i.e. the entire buffer. + # + # If `length` is zero, exactly one `write` operation will occur. + # + # If `offset` is not given, it defaults to zero, i.e. the beginning of the # buffer. # + # Example: + # # out = File.open('output.txt', 'wb') # IO::Buffer.for('1234567').write(out, 3) # diff --git a/core/kernel.rbs b/core/kernel.rbs index 138118d93..174ef2523 100644 --- a/core/kernel.rbs +++ b/core/kernel.rbs @@ -362,25 +362,63 @@ module Kernel : BasicObject # - # Creates a subprocess. If a block is specified, that block is run in the - # subprocess, and the subprocess terminates with a status of zero. Otherwise, - # the `fork` call returns twice, once in the parent, returning the process ID of - # the child, and once in the child, returning *nil*. The child process can exit - # using Kernel.exit! to avoid running any `at_exit` functions. The parent - # process should use Process.wait to collect the termination statuses of its - # children or use Process.detach to register disinterest in their status; - # otherwise, the operating system may accumulate zombie processes. + # Creates a child process. # - # The thread calling fork is the only thread in the created child process. fork - # doesn't copy other threads. + # With a block given, runs the block in the child process; on block exit, the + # child terminates with a status of zero: # - # If fork is not usable, Process.respond_to?(:fork) returns false. + # puts "Before the fork: #{Process.pid}" + # fork do + # puts "In the child process: #{Process.pid}" + # end # => 382141 + # puts "After the fork: #{Process.pid}" # - # Note that fork(2) is not available on some platforms like Windows and NetBSD - # 4. Therefore you should use spawn() instead of fork(). + # Output: + # + # Before the fork: 420496 + # After the fork: 420496 + # In the child process: 420520 + # + # With no block given, the `fork` call returns twice: + # + # * Once in the parent process, returning the pid of the child process. + # * Once in the child process, returning `nil`. + # + # + # Example: + # + # puts "This is the first line before the fork (pid #{Process.pid})" + # puts fork + # puts "This is the second line after the fork (pid #{Process.pid})" + # + # Output: + # + # This is the first line before the fork (pid 420199) + # 420223 + # This is the second line after the fork (pid 420199) + # + # This is the second line after the fork (pid 420223) + # + # In either case, the child process may exit using Kernel.exit! to avoid the + # call to Kernel#at_exit. + # + # To avoid zombie processes, the parent process should call either: + # + # * Process.wait, to collect the termination statuses of its children. + # * Process.detach, to register disinterest in their status. + # + # + # The thread calling `fork` is the only thread in the created child process; + # `fork` doesn't copy other threads. + # + # Note that method `fork` is available on some platforms, but not on others: + # + # Process.respond_to?(:fork) # => true # Would be false on some. + # + # If not, you may use ::spawn instead of `fork`. # def self?.fork: () -> Integer? | () { () -> void } -> Integer @@ -493,7 +531,7 @@ module Kernel : BasicObject | [K, V] (hash[K, V] hash_like) -> Hash[K, V] # # Returns an integer converted from `object`. @@ -511,7 +549,7 @@ module Kernel : BasicObject # Integer(-1) # => -1 # # With floating-point argument `object` given, returns `object` truncated to an - # intger: + # integer: # # Integer(1.9) # => 1 # Rounds toward zero. # Integer(-1.9) # => -1 # Rounds toward zero. @@ -700,11 +738,13 @@ module Kernel : BasicObject # - # Terminate execution immediately, effectively by calling `Kernel.exit(false)`. - # If *msg* is given, it is written to STDERR prior to terminating. + # Terminates execution immediately, effectively by calling `Kernel.exit(false)`. + # + # If string argument `msg` is given, it is written to STDERR prior to + # termination; otherwise, if an exception was raised, prints its message and + # backtrace. # def self?.abort: (?string msg) -> bot @@ -759,68 +799,102 @@ module Kernel : BasicObject # rdoc-file=proc.c # - binding -> a_binding # --> - # Returns a `Binding` object, describing the variable and method bindings at the - # point of call. This object can be used when calling `eval` to execute the - # evaluated command in this environment. See also the description of class - # `Binding`. + # Returns a Binding object, describing the variable and method bindings at the + # point of call. This object can be used when calling Binding#eval to execute + # the evaluated command in this environment, or extracting its local variables. + # + # class User + # def initialize(name, position) + # @name = name + # @position = position + # end + # + # def get_binding + # binding + # end + # end + # + # user = User.new('Joan', 'manager') + # template = '{name: @name, position: @position}' + # + # # evaluate template in context of the object + # eval(template, user.get_binding) + # #=> {:name=>"Joan", :position=>"manager"} # - # def get_binding(param) - # binding + # Binding#local_variable_get can be used to access the variables whose names are + # reserved Ruby keywords: + # + # # This is valid parameter declaration, but `if` parameter can't + # # be accessed by name, because it is a reserved word. + # def validate(field, validation, if: nil) + # condition = binding.local_variable_get('if') + # return unless condition + # + # # ...Some implementation ... # end - # b = get_binding("hello") - # eval("param", b) #=> "hello" + # + # validate(:name, :empty?, if: false) # skips validation + # validate(:name, :empty?, if: true) # performs validation # def self?.binding: () -> Binding # - # Initiates the termination of the Ruby script by raising the SystemExit - # exception. This exception may be caught. The optional parameter is used to - # return a status code to the invoking environment. `true` and `FALSE` of - # *status* means success and failure respectively. The interpretation of other - # integer values are system dependent. + # Initiates termination of the Ruby script by raising SystemExit; the exception + # may be caught. Returns exit status `status` to the underlying operating + # system. + # + # Values `true` and `false` for argument `status` indicate, respectively, + # success and failure; The meanings of integer values are system-dependent. + # + # Example: # # begin # exit - # puts "never get here" + # puts 'Never get here.' # rescue SystemExit - # puts "rescued a SystemExit exception" + # puts 'Rescued a SystemExit exception.' # end - # puts "after begin block" + # puts 'After begin block.' # - # *produces:* + # Output: # - # rescued a SystemExit exception - # after begin block + # Rescued a SystemExit exception. + # After begin block. # - # Just prior to termination, Ruby executes any `at_exit` functions (see - # Kernel::at_exit) and runs any object finalizers (see + # Just prior to final termination, Ruby executes any at-exit procedures (see + # Kernel::at_exit) and any object finalizers (see # ObjectSpace::define_finalizer). # - # at_exit { puts "at_exit function" } - # ObjectSpace.define_finalizer("string", proc { puts "in finalizer" }) + # Example: + # + # at_exit { puts 'In at_exit function.' } + # ObjectSpace.define_finalizer('string', proc { puts 'In finalizer.' }) # exit # - # *produces:* + # Output: # - # at_exit function - # in finalizer + # In at_exit function. + # In finalizer. # def self?.exit: (?int | bool status) -> bot # - # Exits the process immediately. No exit handlers are run. *status* is returned - # to the underlying system as the exit status. + # Exits the process immediately; no exit handlers are called. Returns exit + # status `status` to the underlying operating system. # # Process.exit!(true) # + # Values `true` and `false` for argument `status` indicate, respectively, + # success and failure; The meanings of integer values are system-dependent. + # def self?.exit!: (?int | bool status) -> bot # @@ -882,8 +956,6 @@ module Kernel : BasicObject # For details on `format_string`, see [Format # Specifications](rdoc-ref:format_specifications.rdoc). # - # Kernel#format is an alias for Kernel#sprintf. - # def self?.format: (String format, *untyped args) -> String # # Loads and executes the Ruby program in the file *filename*. # @@ -975,7 +1045,7 @@ module Kernel : BasicObject def self?.load: (String filename, ?Module | bool) -> bool # @@ -1011,21 +1081,10 @@ module Kernel : BasicObject # - open(path, mode = 'r', perm = 0666, **opts) -> io or nil # - open(path, mode = 'r', perm = 0666, **opts) {|io| ... } -> obj # --> - # Creates an IO object connected to the given stream, file, or subprocess. - # - # Required string argument `path` determines which of the following occurs: - # - # * The file at the specified `path` is opened. - # * The process forks. - # * A subprocess is created. - # + # Creates an IO object connected to the given file. # - # Each of these is detailed below. - # - # **File Opened** - # - # If `path` does *not* start with a pipe character (`'|'`), a file stream is - # opened with `File.open(path, mode, perm, **opts)`. + # This method has potential security vulnerabilities if called with untrusted + # input; see [Command Injection](rdoc-ref:command_injection.rdoc). # # With no block given, file stream is returned: # @@ -1042,66 +1101,6 @@ module Kernel : BasicObject # # See File.open for details. # - # **Process Forked** - # - # If `path` is the 2-character string `'|-'`, the process forks and the child - # process is connected to the parent. - # - # With no block given: - # - # io = open('|-') - # if io - # $stderr.puts "In parent, child pid is #{io.pid}." - # else - # $stderr.puts "In child, pid is #{$$}." - # end - # - # Output: - # - # In parent, child pid is 27903. - # In child, pid is 27903. - # - # With a block given: - # - # open('|-') do |io| - # if io - # $stderr.puts "In parent, child pid is #{io.pid}." - # else - # $stderr.puts "In child, pid is #{$$}." - # end - # end - # - # Output: - # - # In parent, child pid is 28427. - # In child, pid is 28427. - # - # **Subprocess Created** - # - # If `path` is `'|command'` (`'command' != '-'`), a new subprocess runs the - # command; its open stream is returned. Note that the command may be processed - # by shell if it contains shell metacharacters. - # - # With no block given: - # - # io = open('|echo "Hi!"') # => # - # print io.gets - # io.close - # - # Output: - # - # "Hi!" - # - # With a block given, calls the block with the stream, then closes the stream: - # - # open('|echo "Hi!"') do |io| - # print io.gets - # end - # - # Output: - # - # "Hi!" - # def self?.open: (String name, ?String mode, ?Integer perm) -> IO? | [T] (String name, ?String mode, ?Integer perm) { (IO) -> T } -> T @@ -1255,6 +1254,10 @@ module Kernel : BasicObject # 0..4 # [0..4, 0..4, 0..4] # + # Kernel#p is designed for debugging purposes. Ruby implementations may define + # Kernel#p to be uninterruptible in whole or in part. On CRuby, Kernel#p's + # writing of data is uninterruptible. + # def self?.p: [T < _Inspect] (T arg0) -> T | (_Inspect arg0, _Inspect arg1, *_Inspect rest) -> Array[_Inspect] | () -> nil @@ -1399,7 +1402,7 @@ module Kernel : BasicObject # # Ruby tries to load the library named *string* relative to the directory # containing the requiring file. If the file does not exist a LoadError is @@ -1551,19 +1554,17 @@ module Kernel : BasicObject # - # Suspends the current thread for *duration* seconds (which may be any number, - # including a `Float` with fractional seconds). Returns the actual number of - # seconds slept (rounded), which may be less than that asked for if another - # thread calls Thread#run. Called without an argument, sleep() will sleep - # forever. + # Suspends execution of the current thread for the number of seconds specified + # by numeric argument `secs`, or forever if `secs` is `nil`; returns the integer + # number of seconds suspended (rounded). # - # Time.new #=> 2008-03-08 19:56:19 +0900 - # sleep 1.2 #=> 1 - # Time.new #=> 2008-03-08 19:56:20 +0900 - # sleep 1.9 #=> 2 - # Time.new #=> 2008-03-08 19:56:22 +0900 + # Time.new # => 2008-03-08 19:56:19 +0900 + # sleep 1.2 # => 1 + # Time.new # => 2008-03-08 19:56:20 +0900 + # sleep 1.9 # => 2 + # Time.new # => 2008-03-08 19:56:22 +0900 # def self?.sleep: (?nil) -> bot | (Integer | Float | _Divmod duration) -> Integer @@ -1676,31 +1677,31 @@ module Kernel : BasicObject # newline character to the string if the string does not end in a newline, and # calls Warning.warn with the string. # - # warn("warning 1", "warning 2") + # warn("warning 1", "warning 2") # - # produces: + # *produces:* # - # warning 1 - # warning 2 + # warning 1 + # warning 2 # # If the `uplevel` keyword argument is given, the string will be prepended with # information for the given caller frame in the same format used by the # `rb_warn` C function. # - # # In baz.rb - # def foo - # warn("invalid call to foo", uplevel: 1) - # end + # # In baz.rb + # def foo + # warn("invalid call to foo", uplevel: 1) + # end # - # def bar - # foo - # end + # def bar + # foo + # end # - # bar + # bar # - # produces: + # *produces:* # - # baz.rb:6: warning: invalid call to foo + # baz.rb:6: warning: invalid call to foo # # If `category` keyword argument is given, passes the category to # `Warning.warn`. The category given must be be one of the following @@ -1716,76 +1717,92 @@ module Kernel : BasicObject # - # Replaces the current process by running the given external *command*, which - # can take one of the following forms: + # Replaces the current process by doing one of the following: + # + # * Passing string `command_line` to the shell. + # * Invoking the executable at `exe_path`. + # + # + # This method has potential security vulnerabilities if called with untrusted + # input; see [Command Injection](rdoc-ref:command_injection.rdoc). + # + # The new process is created using the [exec system + # call](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/e + # xecve.html); it may inherit some of its environment from the calling program + # (possibly including open file descriptors). + # + # Argument `env`, if given, is a hash that affects `ENV` for the new process; + # see [Execution Environment](rdoc-ref:Process@Execution+Environment). + # + # Argument `options` is a hash of options for the new process; see [Execution + # Options](rdoc-ref:Process@Execution+Options). + # + # The first required argument is one of the following: + # + # * `command_line` if it is a string, and if it begins with a shell reserved + # word or special built-in, or if it contains one or more meta characters. + # * `exe_path` otherwise. # - # `exec(commandline)` - # : command line string which is passed to the standard shell - # `exec(cmdname, arg1, ...)` - # : command name and one or more arguments (no shell) - # `exec([cmdname, argv0], arg1, ...)` - # : command name, `argv[0]` and zero or more arguments (no shell) # + # **Argument `command_line`** # - # In the first form, the string is taken as a command line that is subject to - # shell expansion before being executed. + # String argument `command_line` is a command line to be passed to a shell; it + # must begin with a shell reserved word, begin with a special built-in, or + # contain meta characters: # - # The standard shell always means `"/bin/sh"` on Unix-like systems, otherwise, - # `ENV["RUBYSHELL"]` or `ENV["COMSPEC"]` on Windows and similar. The command is - # passed as an argument to the `"-c"` switch to the shell, except in the case of - # `COMSPEC`. + # exec('if true; then echo "Foo"; fi') # Shell reserved word. + # exec('echo') # Built-in. + # exec('date > date.tmp') # Contains meta character. # - # If the string from the first form (`exec("command")`) follows these simple - # rules: + # The command line may also contain arguments and options for the command: # - # * no meta characters, - # * not starting with shell reserved word or special built-in, + # exec('echo "Foo"') # + # Output: + # + # Foo + # + # See [Execution Shell](rdoc-ref:Process@Execution+Shell) for details about the + # shell. + # + # Raises an exception if the new process could not execute. + # + # **Argument `exe_path`** # - # Ruby invokes the command directly without shell. + # Argument `exe_path` is one of the following: # - # You can force shell invocation by adding ";" to the string (because ";" is a - # meta character). + # * The string path to an executable to be called. + # * A 2-element array containing the path to an executable and the string to + # be used as the name of the executing process. # - # Note that this behavior is observable by pid obtained (return value of spawn() - # and IO#pid for IO.popen) is the pid of the invoked command, not shell. # - # In the second form (`exec("command1", "arg1", ...)`), the first is taken as a - # command name and the rest are passed as parameters to command with no shell - # expansion. + # Example: # - # In the third form (`exec(["command", "argv0"], "arg1", ...)`), starting a - # two-element array at the beginning of the command, the first element is the - # command to be executed, and the second argument is used as the `argv[0]` - # value, which may show up in process listings. + # exec('/usr/bin/date') # - # In order to execute the command, one of the `exec(2)` system calls are used, - # so the running command may inherit some of the environment of the original - # program (including open file descriptors). + # Output: # - # This behavior is modified by the given `env` and `options` parameters. See - # ::spawn for details. + # Sat Aug 26 09:38:00 AM CDT 2023 # - # If the command fails to execute (typically Errno::ENOENT when it was not - # found) a SystemCallError exception is raised. + # Ruby invokes the executable directly, with no shell and no shell expansion: # - # This method modifies process attributes according to given `options` before - # `exec(2)` system call. See ::spawn for more details about the given `options`. + # exec('doesnt_exist') # Raises Errno::ENOENT # - # The modified attributes may be retained when `exec(2)` system call fails. + # If one or more `args` is given, each is an argument or option to be passed to + # the executable: # - # For example, hard resource limits are not restorable. + # exec('echo', 'C*') + # exec('echo', 'hello', 'world') # - # Consider to create a child process using ::spawn or Kernel#system if this is - # not acceptable. + # Output: # - # exec "echo *" # echoes list of files in current directory - # # never get here + # C* + # hello world # - # exec "echo", "*" # echoes an asterisk - # # never get here + # Raises an exception if the new process could not execute. # def self?.exec: (String command, *String args, ?unsetenv_others: boolish, ?pgroup: true | Integer, ?umask: Integer, ?in: redirect_fd, ?out: redirect_fd, ?err: redirect_fd, ?close_others: boolish, ?chdir: String) -> bot | (Hash[string, string?] env, String command, *String args, ?unsetenv_others: boolish, ?pgroup: true | Integer, ?umask: Integer, ?in: redirect_fd, ?out: redirect_fd, ?err: redirect_fd, ?close_others: boolish, ?chdir: String) -> bot @@ -1794,304 +1811,235 @@ module Kernel : BasicObject # - # spawn executes specified command and return its pid. - # - # pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2") - # Process.wait pid - # - # pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'") - # Process.wait pid - # - # This method is similar to Kernel#system but it doesn't wait for the command to - # finish. - # - # The parent process should use Process.wait to collect the termination status - # of its child or use Process.detach to register disinterest in their status; - # otherwise, the operating system may accumulate zombie processes. - # - # spawn has bunch of options to specify process attributes: - # - # env: hash - # name => val : set the environment variable - # name => nil : unset the environment variable - # - # the keys and the values except for +nil+ must be strings. - # command...: - # commandline : command line string which is passed to the standard shell - # cmdname, arg1, ... : command name and one or more arguments (This form does not use the shell. See below for caveats.) - # [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell) - # options: hash - # clearing environment variables: - # :unsetenv_others => true : clear environment variables except specified by env - # :unsetenv_others => false : don't clear (default) - # process group: - # :pgroup => true or 0 : make a new process group - # :pgroup => pgid : join the specified process group - # :pgroup => nil : don't change the process group (default) - # create new process group: Windows only - # :new_pgroup => true : the new process is the root process of a new process group - # :new_pgroup => false : don't create a new process group (default) - # resource limit: resourcename is core, cpu, data, etc. See Process.setrlimit. - # :rlimit_resourcename => limit - # :rlimit_resourcename => [cur_limit, max_limit] - # umask: - # :umask => int - # redirection: - # key: - # FD : single file descriptor in child process - # [FD, FD, ...] : multiple file descriptor in child process - # value: - # FD : redirect to the file descriptor in parent process - # string : redirect to file with open(string, "r" or "w") - # [string] : redirect to file with open(string, File::RDONLY) - # [string, open_mode] : redirect to file with open(string, open_mode, 0644) - # [string, open_mode, perm] : redirect to file with open(string, open_mode, perm) - # [:child, FD] : redirect to the redirected file descriptor - # :close : close the file descriptor in child process - # FD is one of follows - # :in : the file descriptor 0 which is the standard input - # :out : the file descriptor 1 which is the standard output - # :err : the file descriptor 2 which is the standard error - # integer : the file descriptor of specified the integer - # io : the file descriptor specified as io.fileno - # file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not - # :close_others => false : inherit - # current directory: - # :chdir => str - # - # The `cmdname, arg1, ...` form does not use the shell. However, on different - # OSes, different things are provided as built-in commands. An example of this - # is +'echo'+, which is a built-in on Windows, but is a normal program on Linux - # and Mac OS X. This means that `Process.spawn 'echo', '%Path%'` will display - # the contents of the `%Path%` environment variable on Windows, but - # `Process.spawn 'echo', '$PATH'` prints the literal `$PATH`. - # - # If a hash is given as `env`, the environment is updated by `env` before - # `exec(2)` in the child process. If a pair in `env` has nil as the value, the - # variable is deleted. - # - # # set FOO as BAR and unset BAZ. - # pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command) - # - # If a hash is given as `options`, it specifies process group, create new - # process group, resource limit, current directory, umask and redirects for the - # child process. Also, it can be specified to clear environment variables. - # - # The `:unsetenv_others` key in `options` specifies to clear environment - # variables, other than specified by `env`. - # - # pid = spawn(command, :unsetenv_others=>true) # no environment variable - # pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only - # - # The `:pgroup` key in `options` specifies a process group. The corresponding - # value should be true, zero, a positive integer, or nil. true and zero cause - # the process to be a process leader of a new process group. A non-zero positive - # integer causes the process to join the provided process group. The default - # value, nil, causes the process to remain in the same process group. - # - # pid = spawn(command, :pgroup=>true) # process leader - # pid = spawn(command, :pgroup=>10) # belongs to the process group 10 - # - # The `:new_pgroup` key in `options` specifies to pass - # `CREATE_NEW_PROCESS_GROUP` flag to `CreateProcessW()` that is Windows API. - # This option is only for Windows. true means the new process is the root - # process of the new process group. The new process has CTRL+C disabled. This - # flag is necessary for `Process.kill(:SIGINT, pid)` on the subprocess. - # :new_pgroup is false by default. - # - # pid = spawn(command, :new_pgroup=>true) # new process group - # pid = spawn(command, :new_pgroup=>false) # same process group - # - # The `:rlimit_`*foo* key specifies a resource limit. *foo* should be one of - # resource types such as `core`. The corresponding value should be an integer or - # an array which have one or two integers: same as cur_limit and max_limit - # arguments for Process.setrlimit. - # - # cur, max = Process.getrlimit(:CORE) - # pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary. - # pid = spawn(command, :rlimit_core=>max) # enable core dump - # pid = spawn(command, :rlimit_core=>0) # never dump core. - # - # The `:umask` key in `options` specifies the umask. - # - # pid = spawn(command, :umask=>077) - # - # The :in, :out, :err, an integer, an IO and an array key specifies a - # redirection. The redirection maps a file descriptor in the child process. - # - # For example, stderr can be merged into stdout as follows: - # - # pid = spawn(command, :err=>:out) - # pid = spawn(command, 2=>1) - # pid = spawn(command, STDERR=>:out) - # pid = spawn(command, STDERR=>STDOUT) - # - # The hash keys specifies a file descriptor in the child process started by - # #spawn. :err, 2 and STDERR specifies the standard error stream (stderr). - # - # The hash values specifies a file descriptor in the parent process which - # invokes #spawn. :out, 1 and STDOUT specifies the standard output stream - # (stdout). - # - # In the above example, the standard output in the child process is not - # specified. So it is inherited from the parent process. + # - spawn([env, ] command_line, options = {}) -> pid + # - spawn([env, ] exe_path, *args, options = {}) -> pid + # --> + # Creates a new child process by doing one of the following in that process: + # + # * Passing string `command_line` to the shell. + # * Invoking the executable at `exe_path`. # - # The standard input stream (stdin) can be specified by :in, 0 and STDIN. # - # A filename can be specified as a hash value. + # This method has potential security vulnerabilities if called with untrusted + # input; see [Command Injection](rdoc-ref:command_injection.rdoc). + # + # Returns the process ID (pid) of the new process, without waiting for it to + # complete. + # + # To avoid zombie processes, the parent process should call either: + # + # * Process.wait, to collect the termination statuses of its children. + # * Process.detach, to register disinterest in their status. # - # pid = spawn(command, :in=>"/dev/null") # read mode - # pid = spawn(command, :out=>"/dev/null") # write mode - # pid = spawn(command, :err=>"log") # write mode - # pid = spawn(command, [:out, :err]=>"/dev/null") # write mode - # pid = spawn(command, 3=>"/dev/null") # read mode # - # For stdout and stderr (and combination of them), it is opened in write mode. - # Otherwise read mode is used. + # The new process is created using the [exec system + # call](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/e + # xecve.html); it may inherit some of its environment from the calling program + # (possibly including open file descriptors). # - # For specifying flags and permission of file creation explicitly, an array is - # used instead. + # Argument `env`, if given, is a hash that affects `ENV` for the new process; + # see [Execution Environment](rdoc-ref:Process@Execution+Environment). # - # pid = spawn(command, :in=>["file"]) # read mode is assumed - # pid = spawn(command, :in=>["file", "r"]) - # pid = spawn(command, :out=>["log", "w"]) # 0644 assumed - # pid = spawn(command, :out=>["log", "w", 0600]) - # pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600]) + # Argument `options` is a hash of options for the new process; see [Execution + # Options](rdoc-ref:Process@Execution+Options). # - # The array specifies a filename, flags and permission. The flags can be a - # string or an integer. If the flags is omitted or nil, File::RDONLY is assumed. - # The permission should be an integer. If the permission is omitted or nil, 0644 - # is assumed. + # The first required argument is one of the following: # - # If an array of IOs and integers are specified as a hash key, all the elements - # are redirected. + # * `command_line` if it is a string, and if it begins with a shell reserved + # word or special built-in, or if it contains one or more meta characters. + # * `exe_path` otherwise. # - # # stdout and stderr is redirected to log file. - # # The file "log" is opened just once. - # pid = spawn(command, [:out, :err]=>["log", "w"]) # - # Another way to merge multiple file descriptors is [:child, fd]. [:child, fd] - # means the file descriptor in the child process. This is different from fd. For - # example, :err=>:out means redirecting child stderr to parent stdout. But - # :err=>[:child, :out] means redirecting child stderr to child stdout. They - # differ if stdout is redirected in the child process as follows. + # **Argument `command_line`** # - # # stdout and stderr is redirected to log file. - # # The file "log" is opened just once. - # pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out]) + # String argument `command_line` is a command line to be passed to a shell; it + # must begin with a shell reserved word, begin with a special built-in, or + # contain meta characters: # - # [:child, :out] can be used to merge stderr into stdout in IO.popen. In this - # case, IO.popen redirects stdout to a pipe in the child process and [:child, - # :out] refers the redirected stdout. + # spawn('if true; then echo "Foo"; fi') # => 798847 # Shell reserved word. + # Process.wait # => 798847 + # spawn('echo') # => 798848 # Built-in. + # Process.wait # => 798848 + # spawn('date > /tmp/date.tmp') # => 798879 # Contains meta character. + # Process.wait # => 798849 + # spawn('date > /nop/date.tmp') # => 798882 # Issues error message. + # Process.wait # => 798882 # - # io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]]) - # p io.read #=> "out\nerr\n" + # The command line may also contain arguments and options for the command: # - # The `:chdir` key in `options` specifies the current directory. + # spawn('echo "Foo"') # => 799031 + # Process.wait # => 799031 # - # pid = spawn(command, :chdir=>"/var/tmp") + # Output: + # + # Foo + # + # See [Execution Shell](rdoc-ref:Process@Execution+Shell) for details about the + # shell. # - # spawn closes all non-standard unspecified descriptors by default. The - # "standard" descriptors are 0, 1 and 2. This behavior is specified by - # :close_others option. :close_others doesn't affect the standard descriptors - # which are closed only if :close is specified explicitly. + # Raises an exception if the new process could not execute. # - # pid = spawn(command, :close_others=>true) # close 3,4,5,... (default) - # pid = spawn(command, :close_others=>false) # don't close 3,4,5,... + # **Argument `exe_path`** # - # :close_others is false by default for spawn and IO.popen. + # Argument `exe_path` is one of the following: # - # Note that fds which close-on-exec flag is already set are closed regardless of - # :close_others option. + # * The string path to an executable to be called: # - # So IO.pipe and spawn can be used as IO.popen. + # spawn('/usr/bin/date') # Path to date on Unix-style system. + # Process.wait # - # # similar to r = IO.popen(command) - # r, w = IO.pipe - # pid = spawn(command, :out=>w) # r, w is closed in the child process. - # w.close + # Output: # - # :close is specified as a hash value to close a fd individually. + # Thu Aug 31 10:06:48 AM CDT 2023 # - # f = open(foo) - # system(command, f=>:close) # don't inherit f. + # * A 2-element array containing the path to an executable and the string to + # be used as the name of the executing process: # - # If a file descriptor need to be inherited, io=>io can be used. + # pid = spawn(['sleep', 'Hello!'], '1') # 2-element array. + # p `ps -p #{pid} -o command=` # - # # valgrind has --log-fd option for log destination. - # # log_w=>log_w indicates log_w.fileno inherits to child process. - # log_r, log_w = IO.pipe - # pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w) - # log_w.close - # p log_r.read + # Output: # - # It is also possible to exchange file descriptors. + # "Hello! 1\n" # - # pid = spawn(command, :out=>:err, :err=>:out) # - # The hash keys specify file descriptors in the child process. The hash values - # specifies file descriptors in the parent process. So the above specifies - # exchanging stdout and stderr. Internally, `spawn` uses an extra file - # descriptor to resolve such cyclic file descriptor mapping. + # Ruby invokes the executable directly, with no shell and no shell expansion. # - # See Kernel.exec for the standard shell. + # If one or more `args` is given, each is an argument or option to be passed to + # the executable: + # + # spawn('echo', 'C*') # => 799392 + # Process.wait # => 799392 + # spawn('echo', 'hello', 'world') # => 799393 + # Process.wait # => 799393 + # + # Output: + # + # C* + # hello world + # + # Raises an exception if the new process could not execute. # def self?.spawn: (String command, *String args, ?unsetenv_others: boolish, ?pgroup: true | Integer, ?umask: Integer, ?in: redirect_fd, ?out: redirect_fd, ?err: redirect_fd, ?close_others: boolish, ?chdir: String) -> Integer | (Hash[string, string?] env, String command, *String args, ?unsetenv_others: boolish, ?pgroup: true | Integer, ?umask: Integer, ?in: redirect_fd, ?out: redirect_fd, ?err: redirect_fd, ?close_others: boolish, ?chdir: String) -> Integer # - # Executes *command...* in a subshell. *command...* is one of following forms. + # Creates a new child process by doing one of the following in that process: + # + # * Passing string `command_line` to the shell. + # * Invoking the executable at `exe_path`. + # # # This method has potential security vulnerabilities if called with untrusted # input; see [Command Injection](rdoc-ref:command_injection.rdoc). # - # `commandline` - # : command line string which is passed to the standard shell - # `cmdname, arg1, ...` - # : command name and one or more arguments (no shell) - # `[cmdname, argv0], arg1, ...` - # : command name, `argv[0]` and zero or more arguments (no shell) + # Returns: # + # * `true` if the command exits with status zero. + # * `false` if the exit status is a non-zero integer. + # * `nil` if the command could not execute. # - # system returns `true` if the command gives zero exit status, `false` for non - # zero exit status. Returns `nil` if command execution fails. An error status is - # available in `$?`. # - # If the `exception: true` argument is passed, the method raises an exception - # instead of returning `false` or `nil`. + # Raises an exception (instead of returning `false` or `nil`) if keyword + # argument `exception` is set to `true`. # - # The arguments are processed in the same way as for Kernel#spawn. + # Assigns the command's error status to `$?`. # - # The hash arguments, env and options, are same as #exec and #spawn. See - # Kernel#spawn for details. + # The new process is created using the [system system + # call](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/s + # ystem.html); it may inherit some of its environment from the calling program + # (possibly including open file descriptors). # - # system("echo *") - # system("echo", "*") + # Argument `env`, if given, is a hash that affects `ENV` for the new process; + # see [Execution Environment](rdoc-ref:Process@Execution+Environment). # - # *produces:* + # Argument `options` is a hash of options for the new process; see [Execution + # Options](rdoc-ref:Process@Execution+Options). + # + # The first required argument is one of the following: + # + # * `command_line` if it is a string, and if it begins with a shell reserved + # word or special built-in, or if it contains one or more meta characters. + # * `exe_path` otherwise. + # + # + # **Argument `command_line`** + # + # String argument `command_line` is a command line to be passed to a shell; it + # must begin with a shell reserved word, begin with a special built-in, or + # contain meta characters: + # + # system('if true; then echo "Foo"; fi') # => true # Shell reserved word. + # system('echo') # => true # Built-in. + # system('date > /tmp/date.tmp') # => true # Contains meta character. + # system('date > /nop/date.tmp') # => false + # system('date > /nop/date.tmp', exception: true) # Raises RuntimeError. + # + # Assigns the command's error status to `$?`: + # + # system('echo') # => true # Built-in. + # $? # => # + # system('date > /nop/date.tmp') # => false + # $? # => # + # + # The command line may also contain arguments and options for the command: + # + # system('echo "Foo"') # => true + # + # Output: + # + # Foo + # + # See [Execution Shell](rdoc-ref:Process@Execution+Shell) for details about the + # shell. # - # config.h main.rb - # * + # Raises an exception if the new process could not execute. # - # Error handling: + # **Argument `exe_path`** # - # system("cat nonexistent.txt") - # # => false - # system("catt nonexistent.txt") - # # => nil + # Argument `exe_path` is one of the following: # - # system("cat nonexistent.txt", exception: true) - # # RuntimeError (Command failed with exit 1: cat) - # system("catt nonexistent.txt", exception: true) - # # Errno::ENOENT (No such file or directory - catt) + # * The string path to an executable to be called. + # * A 2-element array containing the path to an executable and the string to + # be used as the name of the executing process. # - # See Kernel#exec for the standard shell. + # + # Example: + # + # system('/usr/bin/date') # => true # Path to date on Unix-style system. + # system('foo') # => nil # Command failed. + # + # Output: + # + # Mon Aug 28 11:43:10 AM CDT 2023 + # + # Assigns the command's error status to `$?`: + # + # system('/usr/bin/date') # => true + # $? # => # + # system('foo') # => nil + # $? # => # + # + # Ruby invokes the executable directly, with no shell and no shell expansion: + # + # system('doesnt_exist') # => nil + # + # If one or more `args` is given, each is an argument or option to be passed to + # the executable: + # + # system('echo', 'C*') # => true + # system('echo', 'hello', 'world') # => true + # + # Output: + # + # C* + # hello world + # + # Raises an exception if the new process could not execute. # def self?.system: (String command, *String args, ?unsetenv_others: boolish, ?pgroup: true | Integer, ?umask: Integer, ?in: redirect_fd, ?out: redirect_fd, ?err: redirect_fd, ?close_others: boolish, ?chdir: String) -> (NilClass | FalseClass | TrueClass) | (Hash[string, string?] env, String command, *String args, ?unsetenv_others: boolish, ?pgroup: true | Integer, ?umask: Integer, ?in: redirect_fd, ?out: redirect_fd, ?err: redirect_fd, ?close_others: boolish, ?chdir: String) -> (NilClass | FalseClass | TrueClass) @@ -2956,15 +2904,6 @@ module Kernel : BasicObject # # "my string".yield_self {|s| s.upcase } #=> "MY STRING" # - # Good usage for `then` is value piping in method chains: - # - # require 'open-uri' - # require 'json' - # - # construct_url(arguments). - # then {|url| URI(url).read }. - # then {|response| JSON.parse(response) } - # def yield_self: [X] () { (self) -> X } -> X | () -> Enumerator[self, untyped] diff --git a/core/match_data.rbs b/core/match_data.rbs index 1d0a63370..bdb297cd0 100644 --- a/core/match_data.rbs +++ b/core/match_data.rbs @@ -53,8 +53,6 @@ class MatchData # Returns `true` if `object` is another MatchData object whose target string, # regexp, match, and captures are the same as `self`, `false` otherwise. # - # MatchData#eql? is an alias for MatchData#==. - # def ==: (MatchData other) -> bool | (untyped) -> false @@ -180,7 +178,7 @@ class MatchData # m.deconstruct_keys([:hours, :minutes]) # => {:hours => "18", :minutes => "37"} # m.deconstruct_keys(nil) # => {:hours => "18", :minutes => "37", :seconds => "22"} # - # Returns an empty hash of no named captures were defined: + # Returns an empty hash if no named captures were defined: # # m = /(\d{2}):(\d{2}):(\d{2})/.match("18:37:22") # m.deconstruct_keys(nil) # => {} @@ -232,8 +230,6 @@ class MatchData # Returns `true` if `object` is another MatchData object whose target string, # regexp, match, and captures are the same as `self`, `false` otherwise. # - # MatchData#eql? is an alias for MatchData#==. - # alias eql? == # # Returns a string representation of `self`: # - # m = /.$/.match("foo") - # # => # - # m.inspect # => "#" + # m = /.$/.match("foo") + # # => # + # m.inspect # => "#" # - # m = /(.)(.)(.)/.match("foo") - # # => # - # m.inspect # => "# # + # m.inspect # => "# # - # m.inspect # => "#" + # m = /(.)(.)?(.)/.match("fo") + # # => # + # m.inspect # => "#" # - # Related: MatchData#to_s. + # Related: MatchData#to_s. # def inspect: () -> String @@ -276,32 +272,37 @@ class MatchData # # => # # m.size # => 5 # - # MatchData#length is an alias for MatchData.size. - # alias length size # - # Returns a hash of the named captures; each key is a capture name; each value - # is its captured string or `nil`: + # Returns a hash of the named captures; + # each key is a capture name; each value is its captured string or +nil+: # - # m = /(?.)(.)(?.+)/.match("hoge") - # # => # - # m.named_captures # => {"foo"=>"h", "bar"=>"ge"} + # m = /(?.)(.)(?.+)/.match("hoge") + # # => # + # m.named_captures # => {"foo"=>"h", "bar"=>"ge"} + # + # m = /(?.)(?.)/.match("01") + # # => # + # m.named_captures #=> {"a" => "0", "b" => "1"} # - # m = /(?.)(?.)/.match("01") - # # => # - # m.named_captures #=> {"a" => "0", "b" => "1"} + # m = /(?.)(?.)?/.match("0") + # # => # + # m.named_captures #=> {"a" => "0", "b" => nil} # - # m = /(?.)(?.)?/.match("0") - # # => # - # m.named_captures #=> {"a" => "0", "b" => nil} + # m = /(?.)(?.)/.match("01") + # # => # + # m.named_captures #=> {"a" => "1"} + # + # If keyword argument `symbolize_names` is given a true value, the keys in the + # resulting hash are Symbols: # # m = /(?.)(?.)/.match("01") # # => # - # m.named_captures #=> {"a" => "1"} + # m.named_captures(symbolize_names: true) #=> {:a => "1"} # def named_captures: () -> Hash[String, String?] @@ -473,8 +474,6 @@ class MatchData # # => # # m.size # => 5 # - # MatchData#length is an alias for MatchData.size. - # def size: () -> Integer # # The class of the singleton object `nil`. # +# Several of its methods act as operators: +# +# * #& +# * #| +# * #=== +# * #=~ +# * #^ +# +# +# Others act as converters, carrying the concept of *nullity* to other classes: +# +# * #rationalize +# * #to_a +# * #to_c +# * #to_h +# * #to_r +# * #to_s +# +# +# Another method provides inspection: +# +# * #inspect +# +# +# Finally, there is this query method: +# +# * #nil? +# class NilClass def !: () -> true # - # And---Returns `false`. *obj* is always evaluated as it is the argument to a - # method call---there is no short-circuit evaluation in this case. + # Returns `false`: + # + # false & true # => false + # false & Object.new # => false + # + # Argument `object` is evaluated: + # + # false & raise # Raises RuntimeError. # def &: (untyped obj) -> false # - # Case Equality -- For class Object, effectively the same as calling `#==`, but - # typically overridden by descendants to provide meaningful semantics in `case` - # statements. + # Returns `true` or `false`. + # + # Like Object#==, if `object` is an instance of Object (and not an instance of + # one of its many subclasses). + # + # This method is commonly overridden by those subclasses, to provide meaningful + # semantics in `case` statements. # def ===: (nil) -> true | (untyped obj) -> bool # - # Dummy pattern matching -- always returns nil. + # Returns `nil`. # - # This method makes it possible to `while gets =~ /re/ do`. + # This method makes it useful to write: + # + # while gets =~ /re/ + # # ... + # end # def =~: (untyped obj) -> nil # - # Exclusive Or---If *obj* is `nil` or `false`, returns `false`; otherwise, - # returns `true`. + # Returns `false` if `object` is `nil` or `false`, `true` otherwise: + # + # nil ^ nil # => false + # nil ^ false # => false + # nil ^ Object.new # => true # def ^: (false | nil) -> false | (untyped obj) -> bool # - # Always returns the string "nil". + # Returns string `'nil'`: + # + # nil.inspect # => "nil" # def inspect: () -> "nil" # - # Only the object *nil* responds `true` to `nil?`. + # Returns `true`. For all other objects, method `nil?` returns `false`. # def nil?: () -> true # - # Returns zero as a rational. The optional argument `eps` is always ignored. + # Returns zero as a Rational: + # + # nil.rationalize # => (0/1) + # + # Argument `eps` is ignored. # def rationalize: (?untyped eps) -> Rational # - # Always returns an empty array. + # Returns an empty Array. # - # nil.to_a #=> [] + # nil.to_a # => [] # def to_a: () -> [] # - # Returns zero as a complex. + # Returns zero as a Complex: + # + # nil.to_c # => (0+0i) # def to_c: () -> Complex @@ -100,9 +155,9 @@ class NilClass # - # Always returns an empty hash. + # Returns an empty Hash. # # nil.to_h #=> {} # @@ -120,26 +175,34 @@ class NilClass # - # Returns zero as a rational. + # Returns zero as a Rational: + # + # nil.to_r # => (0/1) # def to_r: () -> Rational # - # Always returns the empty string. + # Returns an empty String: + # + # nil.to_s # => "" # def to_s: () -> "" # - # Or---Returns `false` if *obj* is `nil` or `false`; `true` otherwise. + # Returns `false` if `object` is `nil` or `false`, `true` otherwise: + # + # nil | nil # => false + # nil | false # => false + # nil | Object.new # => true # def |: (nil | false) -> false | (untyped obj) -> bool diff --git a/core/numeric.rbs b/core/numeric.rbs index de87b7d36..d8247f4e6 100644 --- a/core/numeric.rbs +++ b/core/numeric.rbs @@ -196,8 +196,6 @@ class Numeric # (-r) % r2 # => (119/100) # (-r) %-r2 # => (-21/100) # - # Numeric#modulo is an alias for Numeric#%. - # def %: (Numeric) -> Numeric # Performs addition: the class of the resulting object depends on the class of @@ -246,8 +244,6 @@ class Numeric # (-34.56).abs #=> 34.56 # -34.56.abs #=> 34.56 # - # Numeric#magnitude is an alias for Numeric#abs. - # def abs: () -> Numeric # - # Returns self. + # Returns `self`. # def conjugate: () -> Numeric @@ -421,9 +416,9 @@ class Numeric # - # Returns `true` if `num` is a finite number, otherwise returns `false`. + # Returns `true` if `self` is a finite number, `false` otherwise. # def finite?: () -> bool @@ -463,8 +458,7 @@ class Numeric # # Returns zero. # @@ -472,21 +466,21 @@ class Numeric # - # Returns `nil`, -1, or 1 depending on whether the value is finite, `-Infinity`, - # or `+Infinity`. + # Returns `nil`, -1, or 1 depending on whether `self` is finite, `-Infinity`, or + # `+Infinity`. # def infinite?: () -> Integer? # - # Returns `true` if `num` is an Integer. + # Returns `true` if `self` is an Integer. # - # 1.0.integer? #=> false - # 1.integer? #=> true + # 1.0.integer? # => false + # 1.integer? # => true # def integer?: () -> bool @@ -497,8 +491,6 @@ class Numeric # (-34.56).abs #=> 34.56 # -34.56.abs #=> 34.56 # - # Numeric#magnitude is an alias for Numeric#abs. - # alias magnitude abs # @@ -530,8 +522,6 @@ class Numeric # (-r) % r2 # => (119/100) # (-r) %-r2 # => (-21/100) # - # Numeric#modulo is an alias for Numeric#%. - # def modulo: (Numeric) -> Numeric # - # Returns self. + # Returns `self`. # def real: () -> Numeric # - # Returns `true` if `num` is a real number (i.e. not Complex). + # Returns `true` if `self` is a real number (i.e. not Complex). # def real?: () -> bool @@ -697,11 +687,11 @@ class Numeric # The generated sequence: # # - Begins with +self+. - # - Continues at intervals of +step+ (which may not be zero). - # - Ends with the last number that is within or equal to +limit+; - # that is, less than or equal to +limit+ if +step+ is positive, - # greater than or equal to +limit+ if +step+ is negative. - # If +limit+ is not given, the sequence is of infinite length. + # - Continues at intervals of +by+ (which may not be zero). + # - Ends with the last number that is within or equal to +to+; + # that is, less than or equal to +to+ if +by+ is positive, + # greater than or equal to +to+ if +by+ is negative. + # If +to+ is +nil+, the sequence is of infinite length. # # If a block is given, calls the block with each number in the sequence; # returns +self+. If no block is given, returns an Enumerator::ArithmeticSequence. @@ -743,7 +733,7 @@ class Numeric # # Positional Arguments # - # With optional positional arguments +limit+ and +step+, + # With optional positional arguments +to+ and +by+, # their values (or defaults) determine the step and limit: # # squares = [] diff --git a/core/process.rbs b/core/process.rbs index a85d209b5..8e6eba961 100644 --- a/core/process.rbs +++ b/core/process.rbs @@ -1,18 +1,329 @@ # -# The module contains several groups of functionality for handling OS processes: -# -# * Low-level property introspection and management of the current process, -# like Process.argv0, Process.pid; -# * Low-level introspection of other processes, like Process.getpgid, -# Process.getpriority; -# * Management of the current process: Process.abort, Process.exit, -# Process.daemon, etc. (for convenience, most of those are also available as -# global functions and module functions of Kernel); -# * Creation and management of child processes: Process.fork, Process.spawn, -# and related methods; -# * Management of low-level system clock: Process.times and -# Process.clock_gettime, which could be important for proper benchmarking -# and other elapsed time measurement tasks. +# Module `Process` represents a process in the underlying operating system. Its +# methods support management of the current process and its child processes. +# +# ## Process Creation +# +# Each of the following methods executes a given command in a new process or +# subshell, or multiple commands in new processes and/or subshells. The choice +# of process or subshell depends on the form of the command; see [Argument +# command_line or exe_path](rdoc-ref:Process@Argument+command_line+or+exe_path). +# +# * Process.spawn, Kernel#spawn: Executes the command; returns the new pid +# without waiting for completion. +# * Process.exec: Replaces the current process by executing the command. +# +# +# In addition: +# +# * Method Kernel#system executes a given command-line (string) in a subshell; +# returns `true`, `false`, or `nil`. +# * Method Kernel#` executes a given command-line (string) in a subshell; +# returns its $stdout string. +# * Module Open3 supports creating child processes with access to their +# $stdin, $stdout, and $stderr streams. +# +# +# ### Execution Environment +# +# Optional leading argument `env` is a hash of name/value pairs, where each name +# is a string and each value is a string or `nil`; each name/value pair is added +# to ENV in the new process. +# +# Process.spawn( 'ruby -e "p ENV[\"Foo\"]"') +# Process.spawn({'Foo' => '0'}, 'ruby -e "p ENV[\"Foo\"]"') +# +# Output: +# +# "0" +# +# The effect is usually similar to that of calling ENV#update with argument +# `env`, where each named environment variable is created or updated (if the +# value is non-`nil`), or deleted (if the value is `nil`). +# +# However, some modifications to the calling process may remain if the new +# process fails. For example, hard resource limits are not restored. +# +# ### Argument `command_line` or `exe_path` +# +# The required string argument is one of the following: +# +# * `command_line` if it begins with a shell reserved word or special +# built-in, or if it contains one or more meta characters. +# * `exe_path` otherwise. +# +# +# **Argument `command_line`** +# +# String argument `command_line` is a command line to be passed to a shell; it +# must begin with a shell reserved word, begin with a special built-in, or +# contain meta characters: +# +# system('if true; then echo "Foo"; fi') # => true # Shell reserved word. +# system('echo') # => true # Built-in. +# system('date > /tmp/date.tmp') # => true # Contains meta character. +# system('date > /nop/date.tmp') # => false +# system('date > /nop/date.tmp', exception: true) # Raises RuntimeError. +# +# The command line may also contain arguments and options for the command: +# +# system('echo "Foo"') # => true +# +# Output: +# +# Foo +# +# See [Execution Shell](rdoc-ref:Process@Execution+Shell) for details about the +# shell. +# +# **Argument `exe_path`** +# +# Argument `exe_path` is one of the following: +# +# * The string path to an executable to be called. +# * A 2-element array containing the path to an executable to be called, and +# the string to be used as the name of the executing process. +# +# +# Example: +# +# system('/usr/bin/date') # => true # Path to date on Unix-style system. +# system('foo') # => nil # Command failed. +# +# Output: +# +# Mon Aug 28 11:43:10 AM CDT 2023 +# +# ### Execution Options +# +# Optional trailing argument `options` is a hash of execution options. +# +# #### Working Directory (`:chdir`) +# +# By default, the working directory for the new process is the same as that of +# the current process: +# +# Dir.chdir('/var') +# Process.spawn('ruby -e "puts Dir.pwd"') +# +# Output: +# +# /var +# +# Use option `:chdir` to set the working directory for the new process: +# +# Process.spawn('ruby -e "puts Dir.pwd"', {chdir: '/tmp'}) +# +# Output: +# +# /tmp +# +# The working directory of the current process is not changed: +# +# Dir.pwd # => "/var" +# +# #### File Redirection (File Descriptor) +# +# Use execution options for file redirection in the new process. +# +# The key for such an option may be an integer file descriptor (fd), specifying +# a source, or an array of fds, specifying multiple sources. +# +# An integer source fd may be specified as: +# +# * *n*: Specifies file descriptor *n*. +# +# +# There are these shorthand symbols for fds: +# +# * `:in`: Specifies file descriptor 0 (STDIN). +# * `:out`: Specifies file descriptor 1 (STDOUT). +# * `:err`: Specifies file descriptor 2 (STDERR). +# +# +# The value given with a source is one of: +# +# * *n*: Redirects to fd *n* in the parent process. +# * `filepath`: Redirects from or to the file at `filepath` via +# `open(filepath, mode, 0644)`, where `mode` is `'r'` for source `:in`, or +# `'w'` for source `:out` or `:err`. +# * `[filepath]`: Redirects from the file at `filepath` via `open(filepath, +# 'r', 0644)`. +# * `[filepath, mode]`: Redirects from or to the file at `filepath` via +# `open(filepath, mode, 0644)`. +# * `[filepath, mode, perm]`: Redirects from or to the file at `filepath` via +# `open(filepath, mode, perm)`. +# * `[:child, fd]`: Redirects to the redirected `fd`. +# * `:close`: Closes the file descriptor in child process. +# +# +# See [Access Modes](rdoc-ref:File@Access+Modes) and [File +# Permissions](rdoc-ref:File@File+Permissions). +# +# #### Environment Variables (`:unsetenv_others`) +# +# By default, the new process inherits environment variables from the parent +# process; use execution option key `:unsetenv_others` with value `true` to +# clear environment variables in the new process. +# +# Any changes specified by execution option `env` are made after the new process +# inherits or clears its environment variables; see [Execution +# Environment](rdoc-ref:Process@Execution+Environment). +# +# #### File-Creation Access (`:umask`) +# +# Use execution option `:umask` to set the file-creation access for the new +# process; see [Access Modes](rdoc-ref:File@Access+Modes): +# +# command = 'ruby -e "puts sprintf(\"0%o\", File.umask)"' +# options = {:umask => 0644} +# Process.spawn(command, options) +# +# Output: +# +# 0644 +# +# #### Process Groups (`:pgroup` and `:new_pgroup`) +# +# By default, the new process belongs to the same [process +# group](https://en.wikipedia.org/wiki/Process_group) as the parent process. +# +# To specify a different process group. use execution option `:pgroup` with one +# of the following values: +# +# * `true`: Create a new process group for the new process. +# * *pgid*: Create the new process in the process group whose id is *pgid*. +# +# +# On Windows only, use execution option `:new_pgroup` with value `true` to +# create a new process group for the new process. +# +# #### Resource Limits +# +# Use execution options to set resource limits. +# +# The keys for these options are symbols of the form `:rlimit_*resource_name`*, +# where *resource_name* is the downcased form of one of the string resource +# names described at method Process.setrlimit. For example, key `:rlimit_cpu` +# corresponds to resource limit `'CPU'`. +# +# The value for such as key is one of: +# +# * An integer, specifying both the current and maximum limits. +# * A 2-element array of integers, specifying the current and maximum limits. +# +# +# #### File Descriptor Inheritance +# +# By default, the new process inherits file descriptors from the parent process. +# +# Use execution option `:close_others => true` to modify that inheritance by +# closing non-standard fds (3 and greater) that are not otherwise redirected. +# +# ### Execution Shell +# +# On a Unix-like system, the shell invoked is `/bin/sh`; otherwise the shell +# invoked is determined by environment variable `ENV['RUBYSHELL']`, if defined, +# or `ENV['COMSPEC']` otherwise. +# +# Except for the `COMSPEC` case, the entire string `command_line` is passed as +# an argument to [shell option +# -c](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/sh. +# html). +# +# The shell performs normal shell expansion on the command line: +# +# spawn('echo C*') # => 799139 +# Process.wait # => 799139 +# +# Output: +# +# CONTRIBUTING.md COPYING COPYING.ja +# +# ## What's Here +# +# ### Current-Process Getters +# +# * ::argv0: Returns the process name as a frozen string. +# * ::egid: Returns the effective group ID. +# * ::euid: Returns the effective user ID. +# * ::getpgrp: Return the process group ID. +# * ::getrlimit: Returns the resource limit. +# * ::gid: Returns the (real) group ID. +# * ::pid: Returns the process ID. +# * ::ppid: Returns the process ID of the parent process. +# * ::uid: Returns the (real) user ID. +# +# +# ### Current-Process Setters +# +# * ::egid=: Sets the effective group ID. +# * ::euid=: Sets the effective user ID. +# * ::gid=: Sets the (real) group ID. +# * ::setproctitle: Sets the process title. +# * ::setpgrp: Sets the process group ID of the process to zero. +# * ::setrlimit: Sets a resource limit. +# * ::setsid: Establishes the process as a new session and process group +# leader, with no controlling tty. +# * ::uid=: Sets the user ID. +# +# +# ### Current-Process Execution +# +# * ::abort: Immediately terminates the process. +# * ::daemon: Detaches the process from its controlling terminal and continues +# running it in the background as system daemon. +# * ::exec: Replaces the process by running a given external command. +# * ::exit: Initiates process termination by raising exception SystemExit +# (which may be caught). +# * ::exit!: Immediately exits the process. +# * ::warmup: Notifies the Ruby virtual machine that the boot sequence for the +# application is completed, and that the VM may begin optimizing the +# application. +# +# +# ### Child Processes +# +# * ::detach: Guards against a child process becoming a zombie. +# * ::fork: Creates a child process. +# * ::kill: Sends a given signal to processes. +# * ::spawn: Creates a child process. +# * ::wait, ::waitpid: Waits for a child process to exit; returns its process +# ID. +# * ::wait2, ::waitpid2: Waits for a child process to exit; returns its +# process ID and status. +# * ::waitall: Waits for all child processes to exit; returns their process +# IDs and statuses. +# +# +# ### Process Groups +# +# * ::getpgid: Returns the process group ID for a process. +# * ::getpriority: Returns the scheduling priority for a process, process +# group, or user. +# * ::getsid: Returns the session ID for a process. +# * ::groups: Returns an array of the group IDs in the supplemental group +# access list for this process. +# * ::groups=: Sets the supplemental group access list to the given array of +# group IDs. +# * ::initgroups: Initializes the supplemental group access list. +# * ::last_status: Returns the status of the last executed child process in +# the current thread. +# * ::maxgroups: Returns the maximum number of group IDs allowed in the +# supplemental group access list. +# * ::maxgroups=: Sets the maximum number of group IDs allowed in the +# supplemental group access list. +# * ::setpgid: Sets the process group ID of a process. +# * ::setpriority: Sets the scheduling priority for a process, process group, +# or user. +# +# +# ### Timing +# +# * ::clock_getres: Returns the resolution of a system clock. +# * ::clock_gettime: Returns the time from a system clock. +# * ::times: Returns a Process::Tms object containing times for the current +# process and its child processes. # module Process # - # Returns an estimate of the resolution of a `clock_id` using the POSIX - # `clock_getres()` function. + # Returns a clock resolution as determined by POSIX function + # [clock_getres()](https://man7.org/linux/man-pages/man3/clock_getres.3.html): # - # Note the reported resolution is often inaccurate on most platforms due to - # underlying bugs for this function and therefore the reported resolution often - # differs from the actual resolution of the clock in practice. Inaccurate - # reported resolutions have been observed for various clocks including - # CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW when using Linux, macOS, BSD or AIX - # platforms, when using ARM processors, or when using virtualization. + # Process.clock_getres(:CLOCK_REALTIME) # => 1.0e-09 # - # `clock_id` specifies a kind of clock. See the document of - # `Process.clock_gettime` for details. `clock_id` can be a symbol as for - # `Process.clock_gettime`. + # See Process.clock_gettime for the values of `clock_id` and `unit`. # - # If the given `clock_id` is not supported, Errno::EINVAL is raised. + # Examples: # - # `unit` specifies the type of the return value. `Process.clock_getres` accepts - # `unit` as `Process.clock_gettime`. The default value, `:float_second`, is also - # the same as `Process.clock_gettime`. + # Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :float_microsecond) # => 0.001 + # Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :float_millisecond) # => 1.0e-06 + # Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :float_second) # => 1.0e-09 + # Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :microsecond) # => 0 + # Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :millisecond) # => 0 + # Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :nanosecond) # => 1 + # Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :second) # => 0 # - # `Process.clock_getres` also accepts `:hertz` as `unit`. `:hertz` means the - # reciprocal of `:float_second`. + # In addition to the values for `unit` supported in Process.clock_gettime, this + # method supports `:hertz`, the integer number of clock ticks per second (which + # is the reciprocal of `:float_second`): # - # `:hertz` can be used to obtain the exact value of the clock ticks per second - # for the times() function and CLOCKS_PER_SEC for the clock() function. + # Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz) # => 100.0 + # Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :float_second) # => 0.01 # - # `Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)` returns - # the clock ticks per second. - # - # `Process.clock_getres(:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)` returns - # CLOCKS_PER_SEC. - # - # p Process.clock_getres(Process::CLOCK_MONOTONIC) - # #=> 1.0e-09 + # **Accuracy**: Note that the returned resolution may be inaccurate on some + # platforms due to underlying bugs. Inaccurate resolutions have been reported + # for various clocks including `:CLOCK_MONOTONIC` and `:CLOCK_MONOTONIC_RAW` on + # Linux, macOS, BSD or AIX platforms, when using ARM processors, or when using + # virtualization. # def self.clock_getres: (Symbol | Integer clock_id, ?Symbol unit) -> (Float | Integer) # - # Returns a time returned by POSIX clock_gettime() function. - # - # p Process.clock_gettime(Process::CLOCK_MONOTONIC) - # #=> 896053.968060096 - # - # `clock_id` specifies a kind of clock. It is specified as a constant which - # begins with `Process::CLOCK_` such as Process::CLOCK_REALTIME and - # Process::CLOCK_MONOTONIC. - # - # The supported constants depends on OS and version. Ruby provides following - # types of `clock_id` if available. - # - # CLOCK_REALTIME - # : SUSv2 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 2.1, macOS - # 10.12, Windows-8/Server-2012 - # CLOCK_MONOTONIC - # : SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4, macOS - # 10.12, Windows-2000 - # CLOCK_PROCESS_CPUTIME_ID - # : SUSv3 to 4, Linux 2.5.63, FreeBSD 9.3, OpenBSD 5.4, macOS 10.12 - # CLOCK_THREAD_CPUTIME_ID - # : SUSv3 to 4, Linux 2.5.63, FreeBSD 7.1, OpenBSD 5.4, macOS 10.12 - # CLOCK_VIRTUAL - # : FreeBSD 3.0, OpenBSD 2.1 - # CLOCK_PROF - # : FreeBSD 3.0, OpenBSD 2.1 - # CLOCK_REALTIME_FAST - # : FreeBSD 8.1 - # CLOCK_REALTIME_PRECISE - # : FreeBSD 8.1 - # CLOCK_REALTIME_COARSE - # : Linux 2.6.32 - # CLOCK_REALTIME_ALARM - # : Linux 3.0 - # CLOCK_MONOTONIC_FAST - # : FreeBSD 8.1 - # CLOCK_MONOTONIC_PRECISE - # : FreeBSD 8.1 - # CLOCK_MONOTONIC_COARSE - # : Linux 2.6.32 - # CLOCK_MONOTONIC_RAW - # : Linux 2.6.28, macOS 10.12 - # CLOCK_MONOTONIC_RAW_APPROX - # : macOS 10.12 - # CLOCK_BOOTTIME - # : Linux 2.6.39 - # CLOCK_BOOTTIME_ALARM - # : Linux 3.0 - # CLOCK_UPTIME - # : FreeBSD 7.0, OpenBSD 5.5 - # CLOCK_UPTIME_FAST - # : FreeBSD 8.1 - # CLOCK_UPTIME_RAW - # : macOS 10.12 - # CLOCK_UPTIME_RAW_APPROX - # : macOS 10.12 - # CLOCK_UPTIME_PRECISE - # : FreeBSD 8.1 - # CLOCK_SECOND - # : FreeBSD 8.1 - # CLOCK_TAI - # : Linux 3.10 + # - Process.clock_gettime(clock_id, unit = :float_second) -> number + # --> + # Returns a clock time as determined by POSIX function + # [clock_gettime()](https://man7.org/linux/man-pages/man3/clock_gettime.3.html): + # + # Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID) # => 198.650379677 + # + # Argument `clock_id` should be a symbol or a constant that specifies the clock + # whose time is to be returned; see below. + # + # Optional argument `unit` should be a symbol that specifies the unit to be used + # in the returned clock time; see below. + # + # **Argument `clock_id`** + # + # Argument `clock_id` specifies the clock whose time is to be returned; it may + # be a constant such as `Process::CLOCK_REALTIME`, or a symbol shorthand such as + # `:CLOCK_REALTIME`. + # + # The supported clocks depend on the underlying operating system; this method + # supports the following clocks on the indicated platforms (raises Errno::EINVAL + # if called with an unsupported clock): + # + # * `:CLOCK_BOOTTIME`: Linux 2.6.39. + # * `:CLOCK_BOOTTIME_ALARM`: Linux 3.0. + # * `:CLOCK_MONOTONIC`: SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, + # OpenBSD 3.4, macOS 10.12, Windows-2000. + # * `:CLOCK_MONOTONIC_COARSE`: Linux 2.6.32. + # * `:CLOCK_MONOTONIC_FAST`: FreeBSD 8.1. + # * `:CLOCK_MONOTONIC_PRECISE`: FreeBSD 8.1. + # * `:CLOCK_MONOTONIC_RAW`: Linux 2.6.28, macOS 10.12. + # * `:CLOCK_MONOTONIC_RAW_APPROX`: macOS 10.12. + # * `:CLOCK_PROCESS_CPUTIME_ID`: SUSv3 to 4, Linux 2.5.63, FreeBSD 9.3, + # OpenBSD 5.4, macOS 10.12. + # * `:CLOCK_PROF`: FreeBSD 3.0, OpenBSD 2.1. + # * `:CLOCK_REALTIME`: SUSv2 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, + # OpenBSD 2.1, macOS 10.12, Windows-8/Server-2012. Time.now is recommended + # over +:CLOCK_REALTIME:. + # * `:CLOCK_REALTIME_ALARM`: Linux 3.0. + # * `:CLOCK_REALTIME_COARSE`: Linux 2.6.32. + # * `:CLOCK_REALTIME_FAST`: FreeBSD 8.1. + # * `:CLOCK_REALTIME_PRECISE`: FreeBSD 8.1. + # * `:CLOCK_SECOND`: FreeBSD 8.1. + # * `:CLOCK_TAI`: Linux 3.10. + # * `:CLOCK_THREAD_CPUTIME_ID`: SUSv3 to 4, Linux 2.5.63, FreeBSD 7.1, OpenBSD + # 5.4, macOS 10.12. + # * `:CLOCK_UPTIME`: FreeBSD 7.0, OpenBSD 5.5. + # * `:CLOCK_UPTIME_FAST`: FreeBSD 8.1. + # * `:CLOCK_UPTIME_PRECISE`: FreeBSD 8.1. + # * `:CLOCK_UPTIME_RAW`: macOS 10.12. + # * `:CLOCK_UPTIME_RAW_APPROX`: macOS 10.12. + # * `:CLOCK_VIRTUAL`: FreeBSD 3.0, OpenBSD 2.1. # # # Note that SUS stands for Single Unix Specification. SUS contains POSIX and - # clock_gettime is defined in the POSIX part. SUS defines CLOCK_REALTIME - # mandatory but CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID and - # CLOCK_THREAD_CPUTIME_ID are optional. - # - # Also, several symbols are accepted as `clock_id`. There are emulations for - # clock_gettime(). - # - # For example, Process::CLOCK_REALTIME is defined as - # `:GETTIMEOFDAY_BASED_CLOCK_REALTIME` when clock_gettime() is not available. - # - # Emulations for `CLOCK_REALTIME`: - # :GETTIMEOFDAY_BASED_CLOCK_REALTIME - # : Use gettimeofday() defined by SUS. (SUSv4 obsoleted it, though.) The - # resolution is 1 microsecond. - # :TIME_BASED_CLOCK_REALTIME - # : Use time() defined by ISO C. The resolution is 1 second. - # - # - # Emulations for `CLOCK_MONOTONIC`: - # :MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC - # : Use mach_absolute_time(), available on Darwin. The resolution is CPU - # dependent. - # :TIMES_BASED_CLOCK_MONOTONIC - # : Use the result value of times() defined by POSIX. POSIX defines it as - # "times() shall return the elapsed real time, in clock ticks, since an - # arbitrary point in the past (for example, system start-up time)". For - # example, GNU/Linux returns a value based on jiffies and it is monotonic. - # However, 4.4BSD uses gettimeofday() and it is not monotonic. (FreeBSD uses - # clock_gettime(CLOCK_MONOTONIC) instead, though.) The resolution is the - # clock tick. "getconf CLK_TCK" command shows the clock ticks per second. - # (The clock ticks per second is defined by HZ macro in older systems.) If - # it is 100 and clock_t is 32 bits integer type, the resolution is 10 - # millisecond and cannot represent over 497 days. - # - # - # Emulations for `CLOCK_PROCESS_CPUTIME_ID`: - # :GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID - # : Use getrusage() defined by SUS. getrusage() is used with RUSAGE_SELF to - # obtain the time only for the calling process (excluding the time for child - # processes). The result is addition of user time (ru_utime) and system time - # (ru_stime). The resolution is 1 microsecond. - # :TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID - # : Use times() defined by POSIX. The result is addition of user time - # (tms_utime) and system time (tms_stime). tms_cutime and tms_cstime are - # ignored to exclude the time for child processes. The resolution is the - # clock tick. "getconf CLK_TCK" command shows the clock ticks per second. - # (The clock ticks per second is defined by HZ macro in older systems.) If - # it is 100, the resolution is 10 millisecond. - # :CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID - # : Use clock() defined by ISO C. The resolution is 1/CLOCKS_PER_SEC. - # CLOCKS_PER_SEC is the C-level macro defined by time.h. SUS defines - # CLOCKS_PER_SEC is 1000000. Non-Unix systems may define it a different - # value, though. If CLOCKS_PER_SEC is 1000000 as SUS, the resolution is 1 - # microsecond. If CLOCKS_PER_SEC is 1000000 and clock_t is 32 bits integer - # type, it cannot represent over 72 minutes. - # - # - # If the given `clock_id` is not supported, Errno::EINVAL is raised. - # - # `unit` specifies a type of the return value. - # - # :float_second - # : number of seconds as a float (default) - # :float_millisecond - # : number of milliseconds as a float - # :float_microsecond - # : number of microseconds as a float - # :second - # : number of seconds as an integer - # :millisecond - # : number of milliseconds as an integer - # :microsecond - # : number of microseconds as an integer - # :nanosecond - # : number of nanoseconds as an integer - # + # clock_gettime is defined in the POSIX part. SUS defines `:CLOCK_REALTIME` as + # mandatory but `:CLOCK_MONOTONIC`, `:CLOCK_PROCESS_CPUTIME_ID`, and + # `:CLOCK_THREAD_CPUTIME_ID` are optional. + # + # Certain emulations are used when the given `clock_id` is not supported + # directly: + # + # * Emulations for `:CLOCK_REALTIME`: + # + # * `:GETTIMEOFDAY_BASED_CLOCK_REALTIME`: Use gettimeofday() defined by + # SUS (deprecated in SUSv4). The resolution is 1 microsecond. + # * `:TIME_BASED_CLOCK_REALTIME`: Use time() defined by ISO C. The + # resolution is 1 second. + # + # + # * Emulations for `:CLOCK_MONOTONIC`: + # + # * `:MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC`: Use mach_absolute_time(), + # available on Darwin. The resolution is CPU dependent. + # * `:TIMES_BASED_CLOCK_MONOTONIC`: Use the result value of times() + # defined by POSIX, thus: + # > Upon successful completion, times() shall return the elapsed real + # time, in clock ticks, since an arbitrary point in the past (for + # example, system start-up time). + # + # > For example, GNU/Linux returns a value based on jiffies and it is + # monotonic. However, 4.4BSD uses gettimeofday() and it is not + # monotonic. (FreeBSD uses `:CLOCK_MONOTONIC` instead, though.) + # + # The resolution is the clock tick. "getconf CLK_TCK" command shows the + # clock ticks per second. (The clock ticks-per-second is defined by HZ + # macro in older systems.) If it is 100 and clock_t is 32 bits integer + # type, the resolution is 10 millisecond and cannot represent over 497 + # days. + # + # + # * Emulations for `:CLOCK_PROCESS_CPUTIME_ID`: + # + # * `:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID`: Use getrusage() defined + # by SUS. getrusage() is used with RUSAGE_SELF to obtain the time only + # for the calling process (excluding the time for child processes). The + # result is addition of user time (ru_utime) and system time (ru_stime). + # The resolution is 1 microsecond. + # * `:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID`: Use times() defined by POSIX. + # The result is addition of user time (tms_utime) and system time + # (tms_stime). tms_cutime and tms_cstime are ignored to exclude the time + # for child processes. The resolution is the clock tick. "getconf + # CLK_TCK" command shows the clock ticks per second. (The clock ticks + # per second is defined by HZ macro in older systems.) If it is 100, the + # resolution is 10 millisecond. + # * `:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID`: Use clock() defined by ISO C. + # The resolution is `1/CLOCKS_PER_SEC`. `CLOCKS_PER_SEC` is the C-level + # macro defined by time.h. SUS defines `CLOCKS_PER_SEC` as 1000000; + # other systems may define it differently. If `CLOCKS_PER_SEC` is + # 1000000 (as in SUS), the resolution is 1 microsecond. If + # `CLOCKS_PER_SEC` is 1000000 and clock_t is a 32-bit integer type, it + # cannot represent over 72 minutes. + # + # + # + # **Argument `unit`** + # + # Optional argument `unit` (default `:float_second`) specifies the unit for the + # returned value. + # + # * `:float_microsecond`: Number of microseconds as a float. + # * `:float_millisecond`: Number of milliseconds as a float. + # * `:float_second`: Number of seconds as a float. + # * `:microsecond`: Number of microseconds as an integer. + # * `:millisecond`: Number of milliseconds as an integer. + # * `:nanosecond`: Number of nanoseconds as an integer. + # * `::second`: Number of seconds as an integer. + # + # + # Examples: + # + # Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :float_microsecond) + # # => 203605054.825 + # Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :float_millisecond) + # # => 203643.696848 + # Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :float_second) + # # => 203.762181929 + # Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :microsecond) + # # => 204123212 + # Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :millisecond) + # # => 204298 + # Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :nanosecond) + # # => 204602286036 + # Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :second) + # # => 204 # # The underlying function, clock_gettime(), returns a number of nanoseconds. # Float object (IEEE 754 double) is not enough to represent the return value for - # CLOCK_REALTIME. If the exact nanoseconds value is required, use `:nanosecond` - # as the `unit`. + # `:CLOCK_REALTIME`. If the exact nanoseconds value is required, use + # `:nanosecond` as the `unit`. # - # The origin (zero) of the returned value varies. For example, system start up - # time, process start up time, the Epoch, etc. + # The origin (time zero) of the returned value is system-dependent, and may be, + # for example, system start up time, process start up time, the Epoch, etc. # - # The origin in CLOCK_REALTIME is defined as the Epoch (1970-01-01 00:00:00 - # UTC). But some systems count leap seconds and others doesn't. So the result - # can be interpreted differently across systems. Time.now is recommended over - # CLOCK_REALTIME. + # The origin in `:CLOCK_REALTIME` is defined as the Epoch: `1970-01-01 00:00:00 + # UTC`; some systems count leap seconds and others don't, so the result may vary + # across systems. # def self.clock_gettime: (Symbol | Integer clock_id) -> Float | (Symbol | Integer clock_id, :float_second | :float_millisecond | :float_microsecond unit) -> Float @@ -252,211 +559,236 @@ module Process # - # Detach the process from controlling terminal and run in the background as - # system daemon. Unless the argument nochdir is true (i.e. non false), it - # changes the current working directory to the root ("/"). Unless the argument - # noclose is true, daemon() will redirect standard input, standard output and - # standard error to /dev/null. Return zero on success, or raise one of Errno::*. + # Detaches the current process from its controlling terminal and runs it in the + # background as system daemon; returns zero. + # + # By default: + # + # * Changes the current working directory to the root directory. + # * Redirects $stdin, $stdout, and $stderr to the null device. + # + # + # If optional argument `nochdir` is `true`, does not change the current working + # directory. + # + # If optional argument `noclose` is `true`, does not redirect $stdin, $stdout, + # or $stderr. # def self.daemon: (?untyped nochdir, ?untyped noclose) -> Integer # - # Some operating systems retain the status of terminated child processes until - # the parent collects that status (normally using some variant of `wait()`). If - # the parent never collects this status, the child stays around as a *zombie* - # process. Process::detach prevents this by setting up a separate Ruby thread - # whose sole job is to reap the status of the process *pid* when it terminates. - # Use #detach only when you do not intend to explicitly wait for the child to - # terminate. + # Avoids the potential for a child process to become a [zombie + # process](https://en.wikipedia.org/wiki/Zombie_process). Process.detach + # prevents this by setting up a separate Ruby thread whose sole job is to reap + # the status of the process *pid* when it terminates. # - # The waiting thread returns the exit status of the detached process when it - # terminates, so you can use Thread#join to know the result. If specified *pid* - # is not a valid child process ID, the thread returns `nil` immediately. + # This method is needed only when the parent process will never wait for the + # child process. # - # The waiting thread has #pid method which returns the pid. + # This example does not reap the second child process; that process appears as a + # zombie in the process status (`ps`) output: # - # In this first example, we don't reap the first child process, so it appears as - # a zombie in the process status display. + # pid = Process.spawn('ruby', '-e', 'exit 13') # => 312691 + # sleep(1) + # # Find zombies. + # system("ps -ho pid,state -p #{pid}") # - # p1 = fork { sleep 0.1 } - # p2 = fork { sleep 0.2 } - # Process.waitpid(p2) - # sleep 2 - # system("ps -ho pid,state -p #{p1}") + # Output: # - # *produces:* + # 312716 Z # - # 27389 Z + # This example also does not reap the second child process, but it does detach + # the process so that it does not become a zombie: # - # In the next example, Process::detach is used to reap the child automatically. + # pid = Process.spawn('ruby', '-e', 'exit 13') # => 313213 + # thread = Process.detach(pid) + # sleep(1) + # # => # + # system("ps -ho pid,state -p #{pid}") # Finds no zombies. # - # p1 = fork { sleep 0.1 } - # p2 = fork { sleep 0.2 } - # Process.detach(p1) - # Process.waitpid(p2) - # sleep 2 - # system("ps -ho pid,state -p #{p1}") + # The waiting thread can return the pid of the detached child process: # - # *(produces no output)* + # thread.join.pid # => 313262 # def self.detach: (Integer pid) -> Thread # - # Returns the effective group ID for this process. Not available on all - # platforms. + # Returns the effective group ID for the current process: # - # Process.egid #=> 500 + # Process.egid # => 500 + # + # Not available on all platforms. # def self.egid: () -> Integer # - # Sets the effective group ID for this process. Not available on all platforms. + # Sets the effective group ID for the current process. + # + # Not available on all platforms. # def self.egid=: (Integer arg0) -> Integer # - # Returns the effective user ID for this process. + # Returns the effective user ID for the current process. # - # Process.euid #=> 501 + # Process.euid # => 501 # def self.euid: () -> Integer # - # Sets the effective user ID for this process. Not available on all platforms. + # Sets the effective user ID for the current process. + # + # Not available on all platforms. # def self.euid=: (Integer arg0) -> Integer # - # Returns the process group ID for the given process id. Not available on all - # platforms. + # Returns the process group ID for the given process ID +pid+: + # + # Process.getpgid(Process.ppid) # => 25527 # - # Process.getpgid(Process.ppid()) #=> 25527 + # Not available on all platforms. # def self.getpgid: (Integer pid) -> Integer # - # Returns the process group ID for this process. Not available on all platforms. + # Returns the process group ID for the current process: # - # Process.getpgid(0) #=> 25527 - # Process.getpgrp #=> 25527 + # Process.getpgid(0) # => 25527 + # Process.getpgrp # => 25527 # def self.getpgrp: () -> Integer # - # Gets the scheduling priority for specified process, process group, or user. - # *kind* indicates the kind of entity to find: one of Process::PRIO_PGRP, - # Process::PRIO_USER, or Process::PRIO_PROCESS. *integer* is an id indicating - # the particular process, process group, or user (an id of 0 means *current*). - # Lower priorities are more favorable for scheduling. Not available on all - # platforms. + # Returns the scheduling priority for specified process, process group, or user. + # + # Argument `kind` is one of: + # + # * Process::PRIO_PROCESS: return priority for process. + # * Process::PRIO_PGRP: return priority for process group. + # * Process::PRIO_USER: return priority for user. + # # - # Process.getpriority(Process::PRIO_USER, 0) #=> 19 - # Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19 + # Argument `id` is the ID for the process, process group, or user; zero + # specified the current ID for `kind`. + # + # Examples: + # + # Process.getpriority(Process::PRIO_USER, 0) # => 19 + # Process.getpriority(Process::PRIO_PROCESS, 0) # => 19 + # + # Not available on all platforms. # def self.getpriority: (Integer kind, Integer arg0) -> Integer # - # Gets the resource limit of the process. *cur_limit* means current (soft) limit - # and *max_limit* means maximum (hard) limit. + # Returns a 2-element array of the current (soft) limit and maximum (hard) limit + # for the given `resource`. + # + # Argument `resource` specifies the resource whose limits are to be returned; + # see Process.setrlimit. + # + # Each of the returned values `cur_limit` and `max_limit` is an integer; see + # Process.setrlimit. + # + # Example: # - # *resource* indicates the kind of resource to limit. It is specified as a - # symbol such as `:CORE`, a string such as `"CORE"` or a constant such as - # Process::RLIMIT_CORE. See Process.setrlimit for details. + # Process.getrlimit(:CORE) # => [0, 18446744073709551615] # - # *cur_limit* and *max_limit* may be Process::RLIM_INFINITY, - # Process::RLIM_SAVED_MAX or Process::RLIM_SAVED_CUR. See Process.setrlimit and - # the system getrlimit(2) manual for details. + # See Process.setrlimit. + # + # Not available on all platforms. # def self.getrlimit: (interned | Integer resource) -> [ Integer, Integer ] # - # Returns the session ID for the given process id. If not given, return current - # process sid. Not available on all platforms. + # Returns the session ID of the given process ID `pid`, or of the current + # process if not given: # - # Process.getsid() #=> 27422 - # Process.getsid(0) #=> 27422 - # Process.getsid(Process.pid()) #=> 27422 + # Process.getsid # => 27422 + # Process.getsid(0) # => 27422 + # Process.getsid(Process.pid()) # => 27422 + # + # Not available on all platforms. # def self.getsid: (?Integer pid) -> Integer # - # Returns the (real) group ID for this process. + # Returns the (real) group ID for the current process: # - # Process.gid #=> 500 + # Process.gid # => 1000 # def self.gid: () -> Integer # - # Sets the group ID for this process. + # Sets the group ID for the current process to `new_gid`: + # + # Process.gid = 1000 # => 1000 # def self.gid=: (Integer arg0) -> Integer # - # Get an Array of the group IDs in the supplemental group access list for this - # process. + # Returns an array of the group IDs in the supplemental group access list for + # the current process: # - # Process.groups #=> [27, 6, 10, 11] + # Process.groups # => [4, 24, 27, 30, 46, 122, 135, 136, 1000] # - # Note that this method is just a wrapper of getgroups(2). This means that the - # following characteristics of the result completely depend on your system: + # These properties of the returned array are system-dependent: # - # * the result is sorted - # * the result includes effective GIDs - # * the result does not include duplicated GIDs - # * the result size does not exceed the value of Process.maxgroups + # * Whether (and how) the array is sorted. + # * Whether the array includes effective group IDs. + # * Whether the array includes duplicate group IDs. + # * Whether the array size exceeds the value of Process.maxgroups. # # - # You can make sure to get a sorted unique GID list of the current process by - # this expression: + # Use this call to get a sorted and unique array: # # Process.groups.uniq.sort # @@ -464,132 +796,186 @@ module Process # - # Set the supplemental group access list to the given Array of group IDs. + # Sets the supplemental group access list to the given array of group IDs. # - # Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27] - # Process.groups = [27, 6, 10, 11] #=> [27, 6, 10, 11] - # Process.groups #=> [27, 6, 10, 11] + # Process.groups # => [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27] + # Process.groups = [27, 6, 10, 11] # => [27, 6, 10, 11] + # Process.groups # => [27, 6, 10, 11] # def self.groups=: (::Array[Integer] arg0) -> ::Array[Integer] # - # Initializes the supplemental group access list by reading the system group - # database and using all groups of which the given user is a member. The group - # with the specified *gid* is also added to the list. Returns the resulting - # Array of the GIDs of all the groups in the supplementary group access list. - # Not available on all platforms. + # Sets the supplemental group access list; the new list includes: + # + # * The group IDs of those groups to which the user given by `username` + # belongs. + # * The group ID `gid`. # - # Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27] - # Process.initgroups( "mgranger", 30 ) #=> [30, 6, 10, 11] - # Process.groups #=> [30, 6, 10, 11] + # + # Example: + # + # Process.groups # => [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27] + # Process.initgroups('me', 30) # => [30, 6, 10, 11] + # Process.groups # => [30, 6, 10, 11] + # + # Not available on all platforms. # def self.initgroups: (String username, Integer gid) -> ::Array[Integer] # - # Sends the given signal to the specified process id(s) if *pid* is positive. If - # *pid* is zero, *signal* is sent to all processes whose group ID is equal to - # the group ID of the process. If *pid* is negative, results are dependent on - # the operating system. *signal* may be an integer signal number or a POSIX - # signal name (either with or without a `SIG` prefix). If *signal* is negative - # (or starts with a minus sign), kills process groups instead of processes. Not - # all signals are available on all platforms. The keys and values of Signal.list - # are known signal names and numbers, respectively. + # Sends a signal to each process specified by `ids` (which must specify at least + # one ID); returns the count of signals sent. + # + # For each given `id`, if `id` is: + # + # * Positive, sends the signal to the process whose process ID is `id`. + # * Zero, send the signal to all processes in the current process group. + # * Negative, sends the signal to a system-dependent collection of processes. + # + # + # Argument `signal` specifies the signal to be sent; the argument may be: + # + # * An integer signal number: e.g., `-29`, `0`, `29`. + # * A signal name (string), with or without leading `'SIG'`, and with or + # without a further prefixed minus sign (`'-'`): e.g.: + # + # * `'SIGPOLL'`. + # * `'POLL'`, + # * `'-SIGPOLL'`. + # * `'-POLL'`. + # + # + # * A signal symbol, with or without leading `'SIG'`, and with or without a + # further prefixed minus sign (`'-'`): e.g.: + # + # * `:SIGPOLL`. + # * `:POLL`. + # * `:'-SIGPOLL'`. + # * `:'-POLL'`. + # + # + # + # If `signal` is: + # + # * A non-negative integer, or a signal name or symbol without prefixed `'-'`, + # each process with process ID `id` is signalled. + # * A negative integer, or a signal name or symbol with prefixed `'-'`, each + # process group with group ID `id` is signalled. + # + # + # Use method Signal.list to see which signals are supported by Ruby on the + # underlying platform; the method returns a hash of the string names and + # non-negative integer values of the supported signals. The size and content of + # the returned hash varies widely among platforms. + # + # Additionally, signal `0` is useful to determine if the process exists. + # + # Example: # # pid = fork do - # Signal.trap("HUP") { puts "Ouch!"; exit } - # # ... do some work ... + # Signal.trap('HUP') { puts 'Ouch!'; exit } + # # ... do some work ... # end # # ... - # Process.kill("HUP", pid) + # Process.kill('HUP', pid) # Process.wait # - # *produces:* + # Output: # # Ouch! # - # If *signal* is an integer but wrong for signal, Errno::EINVAL or RangeError - # will be raised. Otherwise unless *signal* is a String or a Symbol, and a - # known signal name, ArgumentError will be raised. + # Exceptions: # - # Also, Errno::ESRCH or RangeError for invalid *pid*, Errno::EPERM when failed - # because of no privilege, will be raised. In these cases, signals may have - # been sent to preceding processes. + # * Raises Errno::EINVAL or RangeError if `signal` is an integer but invalid. + # * Raises ArgumentError if `signal` is a string or symbol but invalid. + # * Raises Errno::ESRCH or RangeError if one of `ids` is invalid. + # * Raises Errno::EPERM if needed permissions are not in force. + # + # + # In the last two cases, signals may have been sent to some processes. # def self.kill: (Integer | interned signal, *Integer pids) -> Integer # - # Returns the maximum number of GIDs allowed in the supplemental group access - # list. + # Returns the maximum number of group IDs allowed in the supplemental group + # access list: # - # Process.maxgroups #=> 32 + # Process.maxgroups # => 32 # def self.maxgroups: () -> Integer # - # Sets the maximum number of GIDs allowed in the supplemental group access list. + # Sets the maximum number of group IDs allowed in the supplemental group access + # list. # def self.maxgroups=: (Integer arg0) -> Integer # - # Returns the process id of this process. Not available on all platforms. + # Returns the process ID of the current process: # - # Process.pid #=> 27415 + # Process.pid # => 15668 # def self.pid: () -> Integer # - # Returns the process id of the parent of this process. Returns untrustworthy - # value on Win32/64. Not available on all platforms. + # Returns the process ID of the parent of the current process: # - # puts "I am #{Process.pid}" - # Process.fork { puts "Dad is #{Process.ppid}" } + # puts "Pid is #{Process.pid}." + # fork { puts "Parent pid is #{Process.ppid}." } # - # *produces:* + # Output: # - # I am 27417 - # Dad is 27417 + # Pid is 271290. + # Parent pid is 271290. + # + # May not return a trustworthy value on certain platforms. # def self.ppid: () -> Integer # - # Sets the process group ID of *pid* (0 indicates this process) to *integer*. + # Sets the process group ID for the process given by process ID `pid` to `pgid`. + # # Not available on all platforms. # def self.setpgid: (Integer pid, Integer arg0) -> Integer # # See Process.getpriority. # - # Process.setpriority(Process::PRIO_USER, 0, 19) #=> 0 - # Process.setpriority(Process::PRIO_PROCESS, 0, 19) #=> 0 - # Process.getpriority(Process::PRIO_USER, 0) #=> 19 - # Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19 + # Examples: + # + # Process.setpriority(Process::PRIO_USER, 0, 19) # => 0 + # Process.setpriority(Process::PRIO_PROCESS, 0, 19) # => 0 + # Process.getpriority(Process::PRIO_USER, 0) # => 19 + # Process.getpriority(Process::PRIO_PROCESS, 0) # => 19 + # + # Not available on all platforms. # def self.setpriority: (Integer kind, Integer arg0, Integer priority) -> Integer @@ -613,256 +999,426 @@ module Process # - # Sets the resource limit of the process. *cur_limit* means current (soft) limit - # and *max_limit* means maximum (hard) limit. - # - # If *max_limit* is not given, *cur_limit* is used. - # - # *resource* indicates the kind of resource to limit. It should be a symbol such - # as `:CORE`, a string such as `"CORE"` or a constant such as - # Process::RLIMIT_CORE. The available resources are OS dependent. Ruby may - # support following resources. - # - # AS - # : total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD but - # 4.4BSD-Lite) - # CORE - # : core size (bytes) (SUSv3) - # CPU - # : CPU time (seconds) (SUSv3) - # DATA - # : data segment (bytes) (SUSv3) - # FSIZE - # : file size (bytes) (SUSv3) - # MEMLOCK - # : total size for mlock(2) (bytes) (4.4BSD, GNU/Linux) - # MSGQUEUE - # : allocation for POSIX message queues (bytes) (GNU/Linux) - # NICE - # : ceiling on process's nice(2) value (number) (GNU/Linux) - # NOFILE - # : file descriptors (number) (SUSv3) - # NPROC - # : number of processes for the user (number) (4.4BSD, GNU/Linux) - # NPTS - # : number of pseudo terminals (number) (FreeBSD) - # RSS - # : resident memory size (bytes) (4.2BSD, GNU/Linux) - # RTPRIO - # : ceiling on the process's real-time priority (number) (GNU/Linux) - # RTTIME - # : CPU time for real-time process (us) (GNU/Linux) - # SBSIZE - # : all socket buffers (bytes) (NetBSD, FreeBSD) - # SIGPENDING - # : number of queued signals allowed (signals) (GNU/Linux) - # STACK - # : stack size (bytes) (SUSv3) - # - # - # *cur_limit* and *max_limit* may be `:INFINITY`, `"INFINITY"` or - # Process::RLIM_INFINITY, which means that the resource is not limited. They may - # be Process::RLIM_SAVED_MAX, Process::RLIM_SAVED_CUR and corresponding symbols - # and strings too. See system setrlimit(2) manual for details. - # - # The following example raises the soft limit of core size to the hard limit to - # try to make core dump possible. + # - Process.setrlimit(resource, cur_limit, max_limit = cur_limit) -> nil + # --> + # Sets limits for the current process for the given `resource` to `cur_limit` + # (soft limit) and `max_limit` (hard limit); returns `nil`. + # + # Argument `resource` specifies the resource whose limits are to be set; the + # argument may be given as a symbol, as a string, or as a constant beginning + # with `Process::RLIMIT_` (e.g., `:CORE`, `'CORE'`, or `Process::RLIMIT_CORE`. + # + # The resources available and supported are system-dependent, and may include + # (here expressed as symbols): + # + # * `:AS`: Total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD + # except 4.4BSD-Lite). + # * `:CORE`: Core size (bytes) (SUSv3). + # * `:CPU`: CPU time (seconds) (SUSv3). + # * `:DATA`: Data segment (bytes) (SUSv3). + # * `:FSIZE`: File size (bytes) (SUSv3). + # * `:MEMLOCK`: Total size for mlock(2) (bytes) (4.4BSD, GNU/Linux). + # * `:MSGQUEUE`: Allocation for POSIX message queues (bytes) (GNU/Linux). + # * `:NICE`: Ceiling on process's nice(2) value (number) (GNU/Linux). + # * `:NOFILE`: File descriptors (number) (SUSv3). + # * `:NPROC`: Number of processes for the user (number) (4.4BSD, GNU/Linux). + # * `:NPTS`: Number of pseudo terminals (number) (FreeBSD). + # * `:RSS`: Resident memory size (bytes) (4.2BSD, GNU/Linux). + # * `:RTPRIO`: Ceiling on the process's real-time priority (number) + # (GNU/Linux). + # * `:RTTIME`: CPU time for real-time process (us) (GNU/Linux). + # * `:SBSIZE`: All socket buffers (bytes) (NetBSD, FreeBSD). + # * `:SIGPENDING`: Number of queued signals allowed (signals) (GNU/Linux). + # * `:STACK`: Stack size (bytes) (SUSv3). + # + # + # Arguments `cur_limit` and `max_limit` may be: + # + # * Integers (`max_limit` should not be smaller than `cur_limit`). + # * Symbol `:SAVED_MAX`, string `'SAVED_MAX'`, or constant + # `Process::RLIM_SAVED_MAX`: saved maximum limit. + # * Symbol `:SAVED_CUR`, string `'SAVED_CUR'`, or constant + # `Process::RLIM_SAVED_CUR`: saved current limit. + # * Symbol `:INFINITY`, string `'INFINITY'`, or constant + # `Process::RLIM_INFINITY`: no limit on resource. + # + # + # This example raises the soft limit of core size to the hard limit to try to + # make core dump possible: # # Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1]) # + # Not available on all platforms. + # def self.setrlimit: (interned | Integer resource, Integer cur_limit, ?Integer max_limit) -> nil # - # Establishes this process as a new session and process group leader, with no - # controlling tty. Returns the session id. Not available on all platforms. + # Establishes the current process as a new session and process group leader, + # with no controlling tty; returns the session ID: + # + # Process.setsid # => 27422 # - # Process.setsid #=> 27422 + # Not available on all platforms. # def self.setsid: () -> Integer # - # Returns a `Tms` structure (see Process::Tms) that contains user and system CPU - # times for this process, and also for children processes. + # Returns a Process::Tms structure that contains user and system CPU times for + # the current process, and for its children processes: # - # t = Process.times - # [ t.utime, t.stime, t.cutime, t.cstime ] #=> [0.0, 0.02, 0.00, 0.00] + # Process.times + # # => # + # + # The precision is platform-defined. # def self.times: () -> Process::Tms # - # Returns the (real) user ID of this process. + # Returns the (real) user ID of the current process. # - # Process.uid #=> 501 + # Process.uid # => 1000 # def self.uid: () -> Integer # - # Sets the (user) user ID for this process. Not available on all platforms. + # Sets the (user) user ID for the current process to `new_uid`: + # + # Process.uid = 1000 # => 1000 + # + # Not available on all platforms. # def self.uid=: (Integer user) -> Integer # - # Waits for a child process to exit, returns its process id, and sets `$?` to a - # Process::Status object containing information on that process. Which child it - # waits on depends on the value of *pid*: - # - # > 0 - # : Waits for the child whose process ID equals *pid*. - # - # 0 - # : Waits for any child whose process group ID equals that of the calling - # process. + # - Process.wait(pid = -1, flags = 0) -> integer + # --> + # Waits for a suitable child process to exit, returns its process ID, and sets + # `$?` to a Process::Status object containing information on that process. Which + # child it waits for depends on the value of the given `pid`: + # + # * Positive integer: Waits for the child process whose process ID is `pid`: + # + # pid0 = Process.spawn('ruby', '-e', 'exit 13') # => 230866 + # pid1 = Process.spawn('ruby', '-e', 'exit 14') # => 230891 + # Process.wait(pid0) # => 230866 + # $? # => # + # Process.wait(pid1) # => 230891 + # $? # => # + # Process.wait(pid0) # Raises Errno::ECHILD + # + # * `0`: Waits for any child process whose group ID is the same as that of the + # current process: + # + # parent_pgpid = Process.getpgid(Process.pid) + # puts "Parent process group ID is #{parent_pgpid}." + # child0_pid = fork do + # puts "Child 0 pid is #{Process.pid}" + # child0_pgid = Process.getpgid(Process.pid) + # puts "Child 0 process group ID is #{child0_pgid} (same as parent's)." + # end + # child1_pid = fork do + # puts "Child 1 pid is #{Process.pid}" + # Process.setpgid(0, Process.pid) + # child1_pgid = Process.getpgid(Process.pid) + # puts "Child 1 process group ID is #{child1_pgid} (different from parent's)." + # end + # retrieved_pid = Process.wait(0) + # puts "Process.wait(0) returned pid #{retrieved_pid}, which is child 0 pid." + # begin + # Process.wait(0) + # rescue Errno::ECHILD => x + # puts "Raised #{x.class}, because child 1 process group ID differs from parent process group ID." + # end + # + # Output: + # + # Parent process group ID is 225764. + # Child 0 pid is 225788 + # Child 0 process group ID is 225764 (same as parent's). + # Child 1 pid is 225789 + # Child 1 process group ID is 225789 (different from parent's). + # Process.wait(0) returned pid 225788, which is child 0 pid. + # Raised Errno::ECHILD, because child 1 process group ID differs from parent process group ID. + # + # * `-1` (default): Waits for any child process: + # + # parent_pgpid = Process.getpgid(Process.pid) + # puts "Parent process group ID is #{parent_pgpid}." + # child0_pid = fork do + # puts "Child 0 pid is #{Process.pid}" + # child0_pgid = Process.getpgid(Process.pid) + # puts "Child 0 process group ID is #{child0_pgid} (same as parent's)." + # end + # child1_pid = fork do + # puts "Child 1 pid is #{Process.pid}" + # Process.setpgid(0, Process.pid) + # child1_pgid = Process.getpgid(Process.pid) + # puts "Child 1 process group ID is #{child1_pgid} (different from parent's)." + # sleep 3 # To force child 1 to exit later than child 0 exit. + # end + # child_pids = [child0_pid, child1_pid] + # retrieved_pid = Process.wait(-1) + # puts child_pids.include?(retrieved_pid) + # retrieved_pid = Process.wait(-1) + # puts child_pids.include?(retrieved_pid) + # + # Output: + # + # Parent process group ID is 228736. + # Child 0 pid is 228758 + # Child 0 process group ID is 228736 (same as parent's). + # Child 1 pid is 228759 + # Child 1 process group ID is 228759 (different from parent's). + # true + # true + # + # * Less than `-1`: Waits for any child whose process group ID is `-pid`: + # + # parent_pgpid = Process.getpgid(Process.pid) + # puts "Parent process group ID is #{parent_pgpid}." + # child0_pid = fork do + # puts "Child 0 pid is #{Process.pid}" + # child0_pgid = Process.getpgid(Process.pid) + # puts "Child 0 process group ID is #{child0_pgid} (same as parent's)." + # end + # child1_pid = fork do + # puts "Child 1 pid is #{Process.pid}" + # Process.setpgid(0, Process.pid) + # child1_pgid = Process.getpgid(Process.pid) + # puts "Child 1 process group ID is #{child1_pgid} (different from parent's)." + # end + # sleep 1 + # retrieved_pid = Process.wait(-child1_pid) + # puts "Process.wait(-child1_pid) returned pid #{retrieved_pid}, which is child 1 pid." + # begin + # Process.wait(-child1_pid) + # rescue Errno::ECHILD => x + # puts "Raised #{x.class}, because there's no longer a child with process group id #{child1_pid}." + # end + # + # Output: + # + # Parent process group ID is 230083. + # Child 0 pid is 230108 + # Child 0 process group ID is 230083 (same as parent's). + # Child 1 pid is 230109 + # Child 1 process group ID is 230109 (different from parent's). + # Process.wait(-child1_pid) returned pid 230109, which is child 1 pid. + # Raised Errno::ECHILD, because there's no longer a child with process group id 230109. + # + # + # Argument `flags` should be given as one of the following constants, or as the + # logical OR of both: + # + # * Process::WNOHANG: Does not block if no child process is available. + # * Process:WUNTRACED: May return a stopped child process, even if not yet + # reported. + # + # + # Not all flags are available on all platforms. + # + # Raises Errno::ECHILD if there is no suitable child process. # - # -1 - # : Waits for any child process (the default if no *pid* is given). - # - # < -1 - # : Waits for any child whose process group ID equals the absolute value of - # *pid*. - # - # - # The *flags* argument may be a logical or of the flag values Process::WNOHANG - # (do not block if no child available) or Process::WUNTRACED (return stopped - # children that haven't been reported). Not all flags are available on all - # platforms, but a flag value of zero will work on all platforms. - # - # Calling this method raises a SystemCallError if there are no child processes. # Not available on all platforms. # - # include Process - # fork { exit 99 } #=> 27429 - # wait #=> 27429 - # $?.exitstatus #=> 99 - # - # pid = fork { sleep 3 } #=> 27440 - # Time.now #=> 2008-03-08 19:56:16 +0900 - # waitpid(pid, Process::WNOHANG) #=> nil - # Time.now #=> 2008-03-08 19:56:16 +0900 - # waitpid(pid, 0) #=> 27440 - # Time.now #=> 2008-03-08 19:56:19 +0900 + # Process.waitpid is an alias for Process.wait. # def self.wait: (?Integer pid, ?Integer flags) -> Integer # - # Waits for a child process to exit (see Process::waitpid for exact semantics) - # and returns an array containing the process id and the exit status (a - # Process::Status object) of that child. Raises a SystemCallError if there are - # no child processes. + # Like Process.waitpid, but returns an array containing the child process `pid` + # and Process::Status `status`: + # + # pid = Process.spawn('ruby', '-e', 'exit 13') # => 309581 + # Process.wait2(pid) + # # => [309581, #] # - # Process.fork { exit 99 } #=> 27437 - # pid, status = Process.wait2 - # pid #=> 27437 - # status.exitstatus #=> 99 + # Process.waitpid2 is an alias for Process.waitpid. # def self.wait2: (?Integer pid, ?Integer flags) -> [ Integer, Process::Status ] # - # Waits for all children, returning an array of *pid*/*status* pairs (where - # *status* is a Process::Status object). - # - # fork { sleep 0.2; exit 2 } #=> 27432 - # fork { sleep 0.1; exit 1 } #=> 27433 - # fork { exit 0 } #=> 27434 - # p Process.waitall + # Waits for all children, returns an array of 2-element arrays; each subarray + # contains the integer pid and Process::Status status for one of the reaped + # child processes: # - # *produces*: - # - # [[30982, #], - # [30979, #], - # [30976, #]] + # pid0 = Process.spawn('ruby', '-e', 'exit 13') # => 325470 + # pid1 = Process.spawn('ruby', '-e', 'exit 14') # => 325495 + # Process.waitall + # # => [[325470, #], [325495, #]] # def self.waitall: () -> ::Array[[ Integer, Process::Status ]] # - # Waits for a child process to exit, returns its process id, and sets `$?` to a - # Process::Status object containing information on that process. Which child it - # waits on depends on the value of *pid*: - # - # > 0 - # : Waits for the child whose process ID equals *pid*. - # - # 0 - # : Waits for any child whose process group ID equals that of the calling - # process. - # - # -1 - # : Waits for any child process (the default if no *pid* is given). - # - # < -1 - # : Waits for any child whose process group ID equals the absolute value of - # *pid*. - # + # - Process.wait(pid = -1, flags = 0) -> integer + # --> + # Waits for a suitable child process to exit, returns its process ID, and sets + # `$?` to a Process::Status object containing information on that process. Which + # child it waits for depends on the value of the given `pid`: + # + # * Positive integer: Waits for the child process whose process ID is `pid`: + # + # pid0 = Process.spawn('ruby', '-e', 'exit 13') # => 230866 + # pid1 = Process.spawn('ruby', '-e', 'exit 14') # => 230891 + # Process.wait(pid0) # => 230866 + # $? # => # + # Process.wait(pid1) # => 230891 + # $? # => # + # Process.wait(pid0) # Raises Errno::ECHILD + # + # * `0`: Waits for any child process whose group ID is the same as that of the + # current process: + # + # parent_pgpid = Process.getpgid(Process.pid) + # puts "Parent process group ID is #{parent_pgpid}." + # child0_pid = fork do + # puts "Child 0 pid is #{Process.pid}" + # child0_pgid = Process.getpgid(Process.pid) + # puts "Child 0 process group ID is #{child0_pgid} (same as parent's)." + # end + # child1_pid = fork do + # puts "Child 1 pid is #{Process.pid}" + # Process.setpgid(0, Process.pid) + # child1_pgid = Process.getpgid(Process.pid) + # puts "Child 1 process group ID is #{child1_pgid} (different from parent's)." + # end + # retrieved_pid = Process.wait(0) + # puts "Process.wait(0) returned pid #{retrieved_pid}, which is child 0 pid." + # begin + # Process.wait(0) + # rescue Errno::ECHILD => x + # puts "Raised #{x.class}, because child 1 process group ID differs from parent process group ID." + # end + # + # Output: + # + # Parent process group ID is 225764. + # Child 0 pid is 225788 + # Child 0 process group ID is 225764 (same as parent's). + # Child 1 pid is 225789 + # Child 1 process group ID is 225789 (different from parent's). + # Process.wait(0) returned pid 225788, which is child 0 pid. + # Raised Errno::ECHILD, because child 1 process group ID differs from parent process group ID. + # + # * `-1` (default): Waits for any child process: + # + # parent_pgpid = Process.getpgid(Process.pid) + # puts "Parent process group ID is #{parent_pgpid}." + # child0_pid = fork do + # puts "Child 0 pid is #{Process.pid}" + # child0_pgid = Process.getpgid(Process.pid) + # puts "Child 0 process group ID is #{child0_pgid} (same as parent's)." + # end + # child1_pid = fork do + # puts "Child 1 pid is #{Process.pid}" + # Process.setpgid(0, Process.pid) + # child1_pgid = Process.getpgid(Process.pid) + # puts "Child 1 process group ID is #{child1_pgid} (different from parent's)." + # sleep 3 # To force child 1 to exit later than child 0 exit. + # end + # child_pids = [child0_pid, child1_pid] + # retrieved_pid = Process.wait(-1) + # puts child_pids.include?(retrieved_pid) + # retrieved_pid = Process.wait(-1) + # puts child_pids.include?(retrieved_pid) + # + # Output: + # + # Parent process group ID is 228736. + # Child 0 pid is 228758 + # Child 0 process group ID is 228736 (same as parent's). + # Child 1 pid is 228759 + # Child 1 process group ID is 228759 (different from parent's). + # true + # true + # + # * Less than `-1`: Waits for any child whose process group ID is `-pid`: + # + # parent_pgpid = Process.getpgid(Process.pid) + # puts "Parent process group ID is #{parent_pgpid}." + # child0_pid = fork do + # puts "Child 0 pid is #{Process.pid}" + # child0_pgid = Process.getpgid(Process.pid) + # puts "Child 0 process group ID is #{child0_pgid} (same as parent's)." + # end + # child1_pid = fork do + # puts "Child 1 pid is #{Process.pid}" + # Process.setpgid(0, Process.pid) + # child1_pgid = Process.getpgid(Process.pid) + # puts "Child 1 process group ID is #{child1_pgid} (different from parent's)." + # end + # sleep 1 + # retrieved_pid = Process.wait(-child1_pid) + # puts "Process.wait(-child1_pid) returned pid #{retrieved_pid}, which is child 1 pid." + # begin + # Process.wait(-child1_pid) + # rescue Errno::ECHILD => x + # puts "Raised #{x.class}, because there's no longer a child with process group id #{child1_pid}." + # end + # + # Output: + # + # Parent process group ID is 230083. + # Child 0 pid is 230108 + # Child 0 process group ID is 230083 (same as parent's). + # Child 1 pid is 230109 + # Child 1 process group ID is 230109 (different from parent's). + # Process.wait(-child1_pid) returned pid 230109, which is child 1 pid. + # Raised Errno::ECHILD, because there's no longer a child with process group id 230109. + # + # + # Argument `flags` should be given as one of the following constants, or as the + # logical OR of both: + # + # * Process::WNOHANG: Does not block if no child process is available. + # * Process:WUNTRACED: May return a stopped child process, even if not yet + # reported. + # + # + # Not all flags are available on all platforms. + # + # Raises Errno::ECHILD if there is no suitable child process. # - # The *flags* argument may be a logical or of the flag values Process::WNOHANG - # (do not block if no child available) or Process::WUNTRACED (return stopped - # children that haven't been reported). Not all flags are available on all - # platforms, but a flag value of zero will work on all platforms. - # - # Calling this method raises a SystemCallError if there are no child processes. # Not available on all platforms. # - # include Process - # fork { exit 99 } #=> 27429 - # wait #=> 27429 - # $?.exitstatus #=> 99 - # - # pid = fork { sleep 3 } #=> 27440 - # Time.now #=> 2008-03-08 19:56:16 +0900 - # waitpid(pid, Process::WNOHANG) #=> nil - # Time.now #=> 2008-03-08 19:56:16 +0900 - # waitpid(pid, 0) #=> 27440 - # Time.now #=> 2008-03-08 19:56:19 +0900 + # Process.waitpid is an alias for Process.wait. # def self.waitpid: (?Integer pid, ?Integer flags) -> Integer # - # Waits for a child process to exit (see Process::waitpid for exact semantics) - # and returns an array containing the process id and the exit status (a - # Process::Status object) of that child. Raises a SystemCallError if there are - # no child processes. + # Like Process.waitpid, but returns an array containing the child process `pid` + # and Process::Status `status`: # - # Process.fork { exit 99 } #=> 27437 - # pid, status = Process.wait2 - # pid #=> 27437 - # status.exitstatus #=> 99 + # pid = Process.spawn('ruby', '-e', 'exit 13') # => 309581 + # Process.wait2(pid) + # # => [309581, #] + # + # Process.waitpid2 is an alias for Process.waitpid. # def self.waitpid2: (?Integer pid, ?Integer flags) -> [ Integer, Process::Status ] end @@ -1097,14 +1653,15 @@ module Process::GID # - # Returns the effective group ID for this process. Not available on all - # platforms. + # Returns the effective group ID for the current process: # - # Process.egid #=> 500 + # Process.egid # => 500 + # + # Not available on all platforms. # def self.eid: () -> Integer @@ -1159,13 +1716,13 @@ module Process::GID # - # Returns the (real) group ID for this process. + # Returns the (real) group ID for the current process: # - # Process.gid #=> 500 + # Process.gid # => 1000 # def self.rid: () -> Integer @@ -1194,188 +1751,191 @@ module Process::GID end # -# Process::Status encapsulates the information on the status of a running or -# terminated system process. The built-in variable `$?` is either `nil` or a -# Process::Status object. -# -# fork { exit 99 } #=> 26557 -# Process.wait #=> 26557 -# $?.class #=> Process::Status -# $?.to_i #=> 25344 -# $? >> 8 #=> 99 -# $?.stopped? #=> false -# $?.exited? #=> true -# $?.exitstatus #=> 99 -# -# Posix systems record information on processes using a 16-bit integer. The -# lower bits record the process status (stopped, exited, signaled) and the upper -# bits possibly contain additional information (for example the program's return -# code in the case of exited processes). Pre Ruby 1.8, these bits were exposed -# directly to the Ruby program. Ruby now encapsulates these in a Process::Status -# object. To maximize compatibility, however, these objects retain a -# bit-oriented interface. In the descriptions that follow, when we talk about -# the integer value of *stat*, we're referring to this 16 bit value. +# A Process::Status contains information about a system process. +# +# Thread-local variable `$?` is initially `nil`. Some methods assign to it a +# Process::Status object that represents a system process (either running or +# terminated): +# +# `ruby -e "exit 99"` +# stat = $? # => # +# stat.class # => Process::Status +# stat.to_i # => 25344 +# stat >> 8 # => 99 +# stat.stopped? # => false +# stat.exited? # => true +# stat.exitstatus # => 99 # class Process::Status < Object # - # Logical AND of the bits in *stat* with *num*. + # This method is deprecated; use other attribute methods. # - # fork { exit 0x37 } - # Process.wait - # sprintf('%04x', $?.to_i) #=> "3700" - # sprintf('%04x', $? & 0x1e00) #=> "1600" + # Returns the logical AND of the value of #to_i with `mask`: + # + # `cat /nop` + # stat = $? # => # + # sprintf('%x', stat.to_i) # => "100" + # stat & 0x00 # => 0 + # + # ArgumentError is raised if `mask` is negative. # def &: (Integer num) -> Integer # - # Returns `true` if the integer value of *stat* equals *other*. + # Returns whether the value of #to_i == `other`: + # + # `cat /nop` + # stat = $? # => # + # sprintf('%x', stat.to_i) # => "100" + # stat == 0x100 # => true # def ==: (untyped other) -> bool # - # Shift the bits in *stat* right *num* places. + # This method is deprecated; use other predicate methods. + # + # Returns the value of #to_i, shifted `places` to the right: + # + # `cat /nop` + # stat = $? # => # + # stat.to_i # => 256 + # stat >> 1 # => 128 + # stat >> 2 # => 64 # - # fork { exit 99 } #=> 26563 - # Process.wait #=> 26563 - # $?.to_i #=> 25344 - # $? >> 8 #=> 99 + # ArgumentError is raised if `places` is negative. # def >>: (Integer num) -> Integer # - # Returns `true` if *stat* generated a coredump when it terminated. Not - # available on all platforms. + # Returns `true` if the process generated a coredump when it terminated, `false` + # if not. + # + # Not available on all platforms. # def coredump?: () -> bool # - # Returns `true` if *stat* exited normally (for example using an `exit()` call - # or finishing the program). + # Returns `true` if the process exited normally (for example using an `exit()` + # call or finishing the program), `false` if not. # def exited?: () -> bool # - # Returns the least significant eight bits of the return code of *stat*. Only - # available if #exited? is `true`. - # - # fork { } #=> 26572 - # Process.wait #=> 26572 - # $?.exited? #=> true - # $?.exitstatus #=> 0 + # Returns the least significant eight bits of the return code of the process if + # it has exited; `nil` otherwise: # - # fork { exit 99 } #=> 26573 - # Process.wait #=> 26573 - # $?.exited? #=> true - # $?.exitstatus #=> 99 + # `exit 99` + # $?.exitstatus # => 99 # def exitstatus: () -> Integer? # - # Override the inspection method. + # Returns a string representation of `self`: # # system("false") - # p $?.inspect #=> "#" + # $?.inspect # => "#" # def inspect: () -> String # - # Returns the process ID that this status object represents. + # Returns the process ID of the process: # - # fork { exit } #=> 26569 - # Process.wait #=> 26569 - # $?.pid #=> 26569 + # system("false") + # $?.pid # => 1247002 # def pid: () -> Integer # - # Returns `true` if *stat* terminated because of an uncaught signal. + # Returns `true` if the process terminated because of an uncaught signal, + # `false` otherwise. # def signaled?: () -> bool # - # Returns `true` if this process is stopped. This is only returned if the - # corresponding #wait call had the Process::WUNTRACED flag set. + # Returns `true` if this process is stopped, and if the corresponding #wait call + # had the Process::WUNTRACED flag set, `false` otherwise. # def stopped?: () -> bool # - # Returns the number of the signal that caused *stat* to stop (or `nil` if self - # is not stopped). + # Returns the number of the signal that caused the process to stop, or `nil` if + # the process is not stopped. # def stopsig: () -> Integer? # - # Returns `true` if *stat* is successful, `false` if not. Returns `nil` if - # #exited? is not `true`. + # Returns: + # + # * `true` if the process has completed successfully and exited. + # * `false` if the process has completed unsuccessfully and exited. + # * `nil` if the process has not exited. # def success?: () -> bool # - # Returns the number of the signal that caused *stat* to terminate (or `nil` if - # self was not terminated by an uncaught signal). + # Returns the number of the signal that caused the process to terminate or `nil` + # if the process was not terminated by an uncaught signal. # def termsig: () -> Integer? # - # Returns the bits in *stat* as an Integer. Poking around in these bits is - # platform dependent. + # Returns the system-dependent integer status of `self`: # - # fork { exit 0xab } #=> 26566 - # Process.wait #=> 26566 - # sprintf('%04x', $?.to_i) #=> "ab00" + # `cat /nop` + # $?.to_i # => 256 # def to_i: () -> Integer # - # Show pid and exit status as a string. + # Returns a string representation of `self`: # - # system("false") - # p $?.to_s #=> "pid 12766 exit 1" + # `cat /nop` + # $?.to_s # => "pid 1262141 exit 1" # def to_s: () -> String end @@ -1389,37 +1949,37 @@ end module Process::Sys # - # Returns the effective user ID for this process. + # Returns the effective user ID for the current process. # - # Process.euid #=> 501 + # Process.euid # => 501 # def self.geteuid: () -> Integer # - # Returns the (real) group ID for this process. + # Returns the (real) group ID for the current process: # - # Process.gid #=> 500 + # Process.gid # => 1000 # def self.getgid: () -> Integer # - # Returns the (real) user ID of this process. + # Returns the (real) user ID of the current process. # - # Process.uid #=> 501 + # Process.uid # => 1000 # def self.getuid: () -> Integer @@ -1550,13 +2110,13 @@ module Process::UID # - # Returns the effective user ID for this process. + # Returns the effective user ID for the current process. # - # Process.euid #=> 501 + # Process.euid # => 501 # def self.eid: () -> Integer @@ -1611,13 +2171,13 @@ module Process::UID # - # Returns the (real) user ID of this process. + # Returns the (real) user ID of the current process. # - # Process.uid #=> 501 + # Process.uid # => 1000 # def self.rid: () -> Integer diff --git a/core/ractor.rbs b/core/ractor.rbs index 64a5a6cf0..5e2ffb39b 100644 --- a/core/ractor.rbs +++ b/core/ractor.rbs @@ -2,41 +2,46 @@ # Ractor is an Actor-model abstraction for Ruby that provides thread-safe # parallel execution. # -# Ractor.new can make a new Ractor, and it will run in parallel. +# Ractor.new makes a new Ractor, which can run in parallel. # # # The simplest ractor # r = Ractor.new {puts "I am in Ractor!"} # r.take # wait for it to finish -# # here "I am in Ractor!" would be printed +# # Here, "I am in Ractor!" is printed # -# Ractors do not share usual objects, so the same kinds of thread-safety -# concerns such as data-race, race-conditions are not available on multi-ractor -# programming. +# Ractors do not share all objects with each other. There are two main benefits +# to this: across ractors, thread-safety concerns such as data-races and +# race-conditions are not possible. The other benefit is parallelism. # -# To achieve this, ractors severely limit object sharing between different -# ractors. For example, unlike threads, ractors can't access each other's -# objects, nor any objects through variables of the outer scope. +# To achieve this, object sharing is limited across ractors. For example, unlike +# in threads, ractors can't access all the objects available in other ractors. +# Even objects normally available through variables in the outer scope are +# prohibited from being used across ractors. # # a = 1 # r = Ractor.new {puts "I am in Ractor! a=#{a}"} # # fails immediately with # # ArgumentError (can not isolate a Proc because it accesses outer variables (a).) # +# The object must be explicitly shared: +# a = 1 +# r = Ractor.new(a) { |a1| puts "I am in Ractor! a=#{a1}"} +# # On CRuby (the default implementation), Global Virtual Machine Lock (GVL) is -# held per ractor, so ractors are performed in parallel without locking each -# other. +# held per ractor, so ractors can perform in parallel without locking each +# other. This is unlike the situation with threads on CRuby. # -# Instead of accessing the shared state, the objects should be passed to and -# from ractors via sending and receiving objects as messages. +# Instead of accessing shared state, objects should be passed to and from +# ractors by sending and receiving them as messages. # # a = 1 # r = Ractor.new do -# a_in_ractor = receive # receive blocks till somebody will pass message +# a_in_ractor = receive # receive blocks until somebody passes a message # puts "I am in Ractor! a=#{a_in_ractor}" # end # r.send(a) # pass it # r.take -# # here "I am in Ractor! a=1" would be printed +# # Here, "I am in Ractor! a=1" is printed # # There are two pairs of methods for sending/receiving messages: # @@ -46,13 +51,13 @@ # (pull); # # -# In addition to that, an argument to Ractor.new would be passed to block and -# available there as if received by Ractor.receive, and the last block value -# would be sent outside of the ractor as if sent by Ractor.yield. +# In addition to that, any arguments passed to Ractor.new are passed to the +# block and available there as if received by Ractor.receive, and the last block +# value is sent outside of the ractor as if sent by Ractor.yield. # -# A little demonstration on a classic ping-pong: +# A little demonstration of a classic ping-pong: # -# server = Ractor.new do +# server = Ractor.new(name: "server") do # puts "Server starts: #{self.inspect}" # puts "Server sends: ping" # Ractor.yield 'ping' # The server doesn't know the receiver and sends to whoever interested @@ -60,46 +65,49 @@ # puts "Server received: #{received}" # end # -# client = Ractor.new(server) do |srv| # The server is sent inside client, and available as srv +# client = Ractor.new(server) do |srv| # The server is sent to the client, and available as srv # puts "Client starts: #{self.inspect}" -# received = srv.take # The Client takes a message specifically from the server +# received = srv.take # The client takes a message from the server # puts "Client received from " \ # "#{srv.inspect}: #{received}" # puts "Client sends to " \ # "#{srv.inspect}: pong" -# srv.send 'pong' # The client sends a message specifically to the server +# srv.send 'pong' # The client sends a message to the server # end # -# [client, server].each(&:take) # Wait till they both finish +# [client, server].each(&:take) # Wait until they both finish # -# This will output: +# This will output something like: # -# Server starts: # +# Server starts: # # Server sends: ping # Client starts: # -# Client received from #: ping -# Client sends to #: pong +# Client received from #: ping +# Client sends to #: pong # Server received: pong # -# It is said that Ractor receives messages via the *incoming port*, and sends -# them to the *outgoing port*. Either one can be disabled with -# Ractor#close_incoming and Ractor#close_outgoing respectively. If a ractor -# terminated, its ports will be closed automatically. +# Ractors receive their messages via the *incoming port*, and send them to the +# *outgoing port*. Either one can be disabled with Ractor#close_incoming and +# Ractor#close_outgoing, respectively. When a ractor terminates, its ports are +# closed automatically. # # ## Shareable and unshareable objects # -# When the object is sent to and from the ractor, it is important to understand -# whether the object is shareable or unshareable. Most of objects are -# unshareable objects. +# When an object is sent to and from a ractor, it's important to understand +# whether the object is shareable or unshareable. Most Ruby objects are +# unshareable objects. Even frozen objects can be unshareable if they contain +# (through their instance variables) unfrozen objects. # -# Shareable objects are basically those which can be used by several threads -# without compromising thread-safety; e.g. immutable ones. Ractor.shareable? -# allows to check this, and Ractor.make_shareable tries to make object shareable -# if it is not. +# Shareable objects are those which can be used by several threads without +# compromising thread-safety, for example numbers, `true` and `false`. +# Ractor.shareable? allows you to check this, and Ractor.make_shareable tries to +# make the object shareable if it's not already, and gives an error if it can't +# do it. # -# Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are -# Ractor.shareable?('foo') #=> false, unless the string is frozen due to # freeze_string_literals: true +# Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are shareable +# Ractor.shareable?('foo') #=> false, unless the string is frozen due to # frozen_string_literal: true # Ractor.shareable?('foo'.freeze) #=> true +# Ractor.shareable?([Object.new].freeze) #=> false, inner object is unfrozen # # ary = ['hello', 'world'] # ary.frozen? #=> false @@ -110,9 +118,9 @@ # ary[1].frozen? #=> true # # When a shareable object is sent (via #send or Ractor.yield), no additional -# processing happens, and it just becomes usable by both ractors. When an +# processing occurs on it. It just becomes usable by both ractors. When an # unshareable object is sent, it can be either *copied* or *moved*. The first is -# the default, and it makes the object's full copy by deep cloning of +# the default, and it copies the object fully by deep cloning (Object#clone) the # non-shareable parts of its structure. # # data = ['foo', 'bar'.freeze] @@ -124,18 +132,19 @@ # r.take # puts "Outside : #{data.object_id}, #{data[0].object_id}, #{data[1].object_id}" # -# This will output: +# This will output something like: # # In ractor: 340, 360, 320 # Outside : 380, 400, 320 # -# (Note that object id of both array and non-frozen string inside array have -# changed inside the ractor, showing it is different objects. But the second -# array's element, which is a shareable frozen string, has the same object_id.) +# Note that the object ids of the array and the non-frozen string inside the +# array have changed in the ractor because they are different objects. The +# second array's element, which is a shareable frozen string, is the same +# object. # -# Deep cloning of the objects may be slow, and sometimes impossible. -# Alternatively, `move: true` may be used on sending. This will *move* the -# object to the receiving ractor, making it inaccessible for a sending ractor. +# Deep cloning of objects may be slow, and sometimes impossible. Alternatively, +# `move: true` may be used during sending. This will *move* the unshareable +# object to the receiving ractor, making it inaccessible to the sending ractor. # # data = ['foo', 'bar'] # r = Ractor.new do @@ -156,15 +165,17 @@ # Notice that even `inspect` (and more basic methods like `__id__`) is # inaccessible on a moved object. # -# Besides frozen objects, there are shareable objects. Class and Module objects -# are shareable so the Class/Module definitions are shared between ractors. -# Ractor objects are also shareable objects. All operations for the shareable -# mutable objects are thread-safe, so the thread-safety property will be kept. +# Class and Module objects are shareable so the class/module definitions are +# shared between ractors. Ractor objects are also shareable. All operations on +# shareable objects are thread-safe, so the thread-safety property will be kept. # We can not define mutable shareable objects in Ruby, but C extensions can # introduce them. # -# It is prohibited to access instance variables of mutable shareable objects -# (especially Modules and classes) from ractors other than main: +# It is prohibited to access (get) instance variables of shareable objects in +# other ractors if the values of the variables aren't shareable. This can occur +# because modules/classes are shareable, but they can have instance variables +# whose values are not. In non-main ractors, it's also prohibited to set +# instance variables on classes/modules (even if the value is shareable). # # class C # class << self @@ -172,11 +183,12 @@ # end # end # -# C.tricky = 'test' +# C.tricky = "unshareable".dup # # r = Ractor.new(C) do |cls| # puts "I see #{cls}" # puts "I can't see #{cls.tricky}" +# cls.tricky = true # doesn't get here, but this would also raise an error # end # r.take # # I see C @@ -186,7 +198,7 @@ # only one that can access non-shareable constants. # # GOOD = 'good'.freeze -# BAD = 'bad' +# BAD = 'bad'.dup # # r = Ractor.new do # puts "GOOD=#{GOOD}" @@ -211,8 +223,8 @@ # # ## Ractors vs threads # -# Each ractor creates its own thread. New threads can be created from inside -# ractor (and, on CRuby, sharing GVL with other threads of this ractor). +# Each ractor has its own main Thread. New threads can be created from inside +# ractors (and, on CRuby, they share the GVL with other threads of this ractor). # # r = Ractor.new do # a = 1 @@ -223,16 +235,15 @@ # # ## Note on code examples # -# In examples below, sometimes we use the following method to wait till ractors -# that are not currently blocked will finish (or process till next blocking) -# method. +# In the examples below, sometimes we use the following method to wait for +# ractors that are not currently blocked to finish (or to make progress). # # def wait # sleep(0.1) # end # # It is **only for demonstration purposes** and shouldn't be used in a real -# code. Most of the times, just #take is used to wait till ractor will finish. +# code. Most of the time, #take is used to wait for ractors to finish. # # ## Reference # @@ -243,13 +254,13 @@ class Ractor # rdoc-file=ractor.rb # - count() # --> - # Returns total count of Ractors currently running. + # Returns the number of Ractors currently running or blocking (waiting). # # Ractor.count #=> 1 # r = Ractor.new(name: 'example') { Ractor.yield(1) } # Ractor.count #=> 2 (main + example ractor) # r.take # wait for Ractor.yield(1) - # r.take # wait till r will finish + # r.take # wait until r will finish # Ractor.count #=> 1 # def self.count: () -> Integer @@ -281,8 +292,8 @@ class Ractor # `obj` and all the objects it refers to will be frozen, unless they are already # shareable. # - # If `copy` keyword is `true`, the method will copy objects before freezing them - # This is safer option but it can take be slower. + # If `copy` keyword is `true`, it will copy objects before freezing them, and + # will not modify `obj` or its internal objects. # # Note that the specification and implementation of this method are not mature # and may be changed in the future. @@ -317,16 +328,16 @@ class Ractor # --> # Create a new Ractor with args and a block. # - # A block (Proc) will be isolated (can't access to outer variables). `self` - # inside the block will refer to the current Ractor. + # The given block (Proc) will be isolated (can't access any outer variables). + # `self` inside the block will refer to the current Ractor. # # r = Ractor.new { puts "Hi, I am #{self.inspect}" } # r.take # # Prints "Hi, I am #" # - # `args` passed to the method would be propagated to block args by the same - # rules as objects passed through #send/Ractor.receive: if `args` are not - # shareable, they will be copied (via deep cloning, which might be inefficient). + # Any `args` passed are propagated to the block arguments by the same rules as + # objects sent via #send/Ractor.receive. If an argument in `args` is not + # shareable, it will be copied (via deep cloning, which might be inefficient). # # arg = [1, 2, 3] # puts "Passing: #{arg} (##{arg.object_id})" @@ -340,7 +351,7 @@ class Ractor # # Ractor's `name` can be set for debugging purposes: # - # r = Ractor.new(name: 'my ractor') {} + # r = Ractor.new(name: 'my ractor') {}; r.take # p r # #=> # # @@ -350,8 +361,8 @@ class Ractor # rdoc-file=ractor.rb # - Ractor.receive -> msg # --> - # Receive an incoming message from the current Ractor's incoming port's queue, - # which was sent there by #send. + # Receive a message from the incoming port of the current ractor (which was sent + # there by #send from another ractor). # # r = Ractor.new do # v1 = Ractor.receive @@ -361,7 +372,7 @@ class Ractor # r.take # # Here will be printed: "Received: message1" # - # Alternatively, private instance method `receive` may be used: + # Alternatively, the private instance method `receive` may be used: # # r = Ractor.new do # v1 = receive @@ -369,7 +380,7 @@ class Ractor # end # r.send('message1') # r.take - # # Here will be printed: "Received: message1" + # # This prints: "Received: message1" # # The method blocks if the queue is empty. # @@ -397,7 +408,7 @@ class Ractor # Received: message2 # # If close_incoming was called on the ractor, the method raises - # Ractor::ClosedError if there are no more messages in incoming queue: + # Ractor::ClosedError if there are no more messages in the incoming queue: # # Ractor.new do # close_incoming @@ -414,8 +425,9 @@ class Ractor # --> # Receive only a specific message. # - # Instead of Ractor.receive, Ractor.receive_if can provide a pattern by a block - # and you can choose the receiving message. + # Instead of Ractor.receive, Ractor.receive_if can be given a pattern (or any + # filter) in a block and you can choose the messages to accept that are + # available in your ractor's incoming queue. # # r = Ractor.new do # p Ractor.receive_if{|msg| msg.match?(/foo/)} #=> "foo3" @@ -433,9 +445,9 @@ class Ractor # bar1 # baz2 # - # If the block returns a truthy value, the message will be removed from the - # incoming queue and returned. Otherwise, the message remains in the incoming - # queue and the following received messages are checked by the given block. + # If the block returns a truthy value, the message is removed from the incoming + # queue and returned. Otherwise, the message remains in the incoming queue and + # the next messages are checked by the given block. # # If there are no messages left in the incoming queue, the method will block # until new messages arrive. @@ -461,7 +473,7 @@ class Ractor # Received successfully: [1, 2, 3] # # Note that you can not call receive/receive_if in the given block recursively. - # It means that you should not do any tasks in the block. + # You should not do any tasks in the block other than message filtration. # # Ractor.current << true # Ractor.receive_if{|msg| Ractor.receive} @@ -480,8 +492,8 @@ class Ractor # rdoc-file=ractor.rb # - Ractor.select(*ractors, [yield_value:, move: false]) -> [ractor or symbol, obj] # --> - # Waits for the first ractor to have something in its outgoing port, reads from - # this ractor, and returns that ractor and the object received. + # Wait for any ractor to have something in its outgoing port, read from this + # ractor, and then return that ractor and the object received. # # r1 = Ractor.new {Ractor.yield 'from 1'} # r2 = Ractor.new {Ractor.yield 'from 2'} @@ -490,9 +502,10 @@ class Ractor # # puts "received #{obj.inspect} from #{r.inspect}" # # Prints: received "from 1" from # + # # But could just as well print "from r2" here, either prints could be first. # - # If one of the given ractors is the current ractor, and it would be selected, - # `r` will contain `:receive` symbol instead of the ractor object. + # If one of the given ractors is the current ractor, and it is selected, `r` + # will contain the `:receive` symbol instead of the ractor object. # # r1 = Ractor.new(Ractor.current) do |main| # main.send 'to main' @@ -504,10 +517,10 @@ class Ractor # # r, obj = Ractor.select(r1, r2, Ractor.current) # puts "received #{obj.inspect} from #{r.inspect}" - # # Prints: received "to main" from :receive + # # Could print: received "to main" from :receive # - # If `yield_value` is provided, that value may be yielded if another Ractor is - # calling #take. In this case, the pair `[:yield, nil]` would be returned: + # If `yield_value` is provided, that value may be yielded if another ractor is + # calling #take. In this case, the pair `[:yield, nil]` is returned: # # r1 = Ractor.new(Ractor.current) do |main| # puts "Received from main: #{main.take}" @@ -524,8 +537,8 @@ class Ractor # Received from main: 123 # Received nil from :yield # - # `move` boolean flag defines whether yielded value should be copied (default) - # or moved. + # `move` boolean flag defines whether yielded value will be copied (default) or + # moved. # def self.select: (*Ractor ractors, ?move: boolish, ?yield_value: untyped) -> [ Ractor | Symbol, untyped ] @@ -536,7 +549,7 @@ class Ractor # Checks if the object is shareable by ractors. # # Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are frozen - # Ractor.shareable?('foo') #=> false, unless the string is frozen due to # freeze_string_literals: true + # Ractor.shareable?('foo') #=> false, unless the string is frozen due to # frozen_string_literal: true # Ractor.shareable?('foo'.freeze) #=> true # # See also the "Shareable and unshareable objects" section in the Ractor class @@ -548,13 +561,13 @@ class Ractor # rdoc-file=ractor.rb # - Ractor.yield(msg, move: false) -> nil # --> - # Send a message to the current ractor's outgoing port to be consumed by #take. + # Send a message to the current ractor's outgoing port to be accepted by #take. # # r = Ractor.new {Ractor.yield 'Hello from ractor'} # puts r.take # # Prints: "Hello from ractor" # - # The method is blocking, and will return only when somebody consumes the sent + # This method is blocking, and will return only when somebody consumes the sent # message. # # r = Ractor.new do @@ -580,7 +593,7 @@ class Ractor # wait # # `yield': The outgoing-port is already closed (Ractor::ClosedError) # - # The meaning of `move` argument is the same as for #send. + # The meaning of the `move` argument is the same as for #send. # def self.yield: (untyped obj, ?move: boolish) -> untyped @@ -613,9 +626,9 @@ class Ractor # rdoc-file=ractor.rb # - ractor.close_incoming -> true | false # --> - # Closes the incoming port and returns its previous state. All further attempts - # to Ractor.receive in the ractor, and #send to the ractor will fail with - # Ractor::ClosedError. + # Closes the incoming port and returns whether it was already closed. All + # further attempts to Ractor.receive in the ractor, and #send to the ractor will + # fail with Ractor::ClosedError. # # r = Ractor.new {sleep(500)} # r.close_incoming #=> false @@ -629,9 +642,9 @@ class Ractor # rdoc-file=ractor.rb # - ractor.close_outgoing -> true | false # --> - # Closes the outgoing port and returns its previous state. All further attempts - # to Ractor.yield in the ractor, and #take from the ractor will fail with - # Ractor::ClosedError. + # Closes the outgoing port and returns whether it was already closed. All + # further attempts to Ractor.yield in the ractor, and #take from the ractor will + # fail with Ractor::ClosedError. # # r = Ractor.new {sleep(500)} # r.close_outgoing #=> false @@ -660,7 +673,7 @@ class Ractor # rdoc-file=ractor.rb # - ractor.send(msg, move: false) -> self # --> - # Send a message to a Ractor's incoming queue to be consumed by Ractor.receive. + # Send a message to a Ractor's incoming queue to be accepted by Ractor.receive. # # r = Ractor.new do # value = Ractor.receive @@ -677,7 +690,7 @@ class Ractor # puts "Sent successfully" # # Prints: "Sent successfully" immediately # - # Attempt to send to ractor which already finished its execution will raise + # An attempt to send to a ractor which already finished its execution will raise # Ractor::ClosedError. # # r = Ractor.new {} @@ -697,11 +710,11 @@ class Ractor # r.close_incoming # r.send('test') # # Ractor::ClosedError (The incoming-port is already closed) - # # The error would be raised immediately, not when ractor will try to receive + # # The error is raised immediately, not when the ractor tries to receive # - # If the `obj` is unshareable, by default it would be copied into ractor by deep - # cloning. If the `move: true` is passed, object is *moved* into ractor and - # becomes inaccessible to sender. + # If the `obj` is unshareable, by default it will be copied into the receiving + # ractor by deep cloning. If `move: true` is passed, the object is *moved* into + # the receiving ractor and becomes inaccessible to the sender. # # r = Ractor.new {puts "Received: #{receive}"} # msg = 'message' @@ -714,7 +727,7 @@ class Ractor # Received: message # in `p': undefined method `inspect' for # # - # All references to the object and its parts will become invalid in sender. + # All references to the object and its parts will become invalid to the sender. # # r = Ractor.new {puts "Received: #{receive}"} # s = 'message' @@ -732,7 +745,7 @@ class Ractor # # Ractor::MovedError (can not send any methods to a moved object) # # ...but its item was still a reference to `s`, which was moved # - # If the object was shareable, `move: true` has no effect on it: + # If the object is shareable, `move: true` has no effect on it: # # r = Ractor.new {puts "Received: #{receive}"} # s = 'message'.freeze @@ -745,8 +758,8 @@ class Ractor # rdoc-file=ractor.rb # - ractor.take -> msg # --> - # Take a message from ractor's outgoing port, which was put there by - # Ractor.yield or at ractor's finalization. + # Get a message from the ractor's outgoing port, which was put there by + # Ractor.yield or at ractor's termination. # # r = Ractor.new do # Ractor.yield 'explicit yield' @@ -756,10 +769,10 @@ class Ractor # puts r.take #=> 'last value' # puts r.take # Ractor::ClosedError (The outgoing-port is already closed) # - # The fact that the last value is also put to outgoing port means that `take` - # can be used as some analog of Thread#join ("just wait till ractor finishes"), - # but don't forget it will raise if somebody had already consumed everything - # ractor have produced. + # The fact that the last value is also sent to the outgoing port means that + # `take` can be used as an analog of Thread#join ("just wait until ractor + # finishes"). However, it will raise if somebody has already consumed that + # message. # # If the outgoing port was closed with #close_outgoing, the method will raise # Ractor::ClosedError. @@ -773,7 +786,7 @@ class Ractor # # Ractor::ClosedError (The outgoing-port is already closed) # # The error would be raised immediately, not when ractor will try to receive # - # If an uncaught exception is raised in the Ractor, it is propagated on take as + # If an uncaught exception is raised in the Ractor, it is propagated by take as # a Ractor::RemoteError. # # r = Ractor.new {raise "Something weird happened"} @@ -786,8 +799,9 @@ class Ractor # p e.cause # => # # end # - # Ractor::ClosedError is a descendant of StopIteration, so the closing of the - # ractor will break the loops without propagating the error: + # Ractor::ClosedError is a descendant of StopIteration, so the termination of + # the ractor will break out of any loops that receive this message without + # propagating the error: # # r = Ractor.new do # 3.times {|i| Ractor.yield "message #{i}"} @@ -828,6 +842,7 @@ class Ractor # rdoc-file=ractor.rb # - receive_if(&b) # --> + # same as Ractor.receive_if # def receive_if: () { (untyped) -> boolish } -> untyped diff --git a/core/range.rbs b/core/range.rbs index 6fe4ea16d..10b97934d 100644 --- a/core/range.rbs +++ b/core/range.rbs @@ -556,8 +556,6 @@ class Range[out Elem] < Object # # Related: Range#cover?. # - # Range#member? is an alias for Range#include?. - # def include?: (untyped obj) -> bool # - # ENV.store is an alias for ENV.[]=. - # # Creates, updates, or deletes the named environment variable, returning the # value. Both `name` and `value` may be instances of String. See [Valid Names # and Values](rdoc-ref:ENV@Valid+Names+and+Values). @@ -294,8 +292,6 @@ module RBS # - ENV[name] = value -> value # - ENV.store(name, value) -> value # --> - # ENV.store is an alias for ENV.[]=. - # # Creates, updates, or deletes the named environment variable, returning the # value. Both `name` and `value` may be instances of String. See [Valid Names # and Values](rdoc-ref:ENV@Valid+Names+and+Values). @@ -601,8 +597,6 @@ module RBS # - ENV.filter { |name, value| block } -> hash of name/value pairs # - ENV.filter -> an_enumerator # --> - # ENV.filter is an alias for ENV.select. - # # Yields each environment variable name and its value as a 2-element Array, # returning a Hash of the names and values for which the block returns a truthy # value: @@ -627,8 +621,6 @@ module RBS # - ENV.filter { |name, value| block } -> hash of name/value pairs # - ENV.filter -> an_enumerator # --> - # ENV.filter is an alias for ENV.select. - # # Yields each environment variable name and its value as a 2-element Array, # returning a Hash of the names and values for which the block returns a truthy # value: @@ -652,8 +644,6 @@ module RBS # - ENV.filter! { |name, value| block } -> ENV or nil # - ENV.filter! -> an_enumerator # --> - # ENV.filter! is an alias for ENV.select!. - # # Yields each environment variable name and its value as a 2-element Array, # deleting each entry for which the block returns `false` or `nil`, and # returning ENV if any deletions made, or `nil` otherwise: @@ -693,8 +683,6 @@ module RBS # - ENV.filter! { |name, value| block } -> ENV or nil # - ENV.filter! -> an_enumerator # --> - # ENV.filter! is an alias for ENV.select!. - # # Yields each environment variable name and its value as a 2-element Array, # deleting each entry for which the block returns `false` or `nil`, and # returning ENV if any deletions made, or `nil` otherwise: @@ -794,8 +782,6 @@ module RBS # - ENV.merge!(*hashes) -> ENV # - ENV.merge!(*hashes) { |name, env_val, hash_val| block } -> ENV # --> - # ENV.update is an alias for ENV.merge!. - # # Adds to ENV each key/value pair in the given `hash`; returns ENV: # ENV.replace('foo' => '0', 'bar' => '1') # ENV.merge!('baz' => '2', 'bat' => '3') # => {"bar"=>"1", "bat"=>"3", "baz"=>"2", "foo"=>"0"} @@ -839,8 +825,6 @@ module RBS # - ENV.merge!(*hashes) -> ENV # - ENV.merge!(*hashes) { |name, env_val, hash_val| block } -> ENV # --> - # ENV.update is an alias for ENV.merge!. - # # Adds to ENV each key/value pair in the given `hash`; returns ENV: # ENV.replace('foo' => '0', 'bar' => '1') # ENV.merge!('baz' => '2', 'bat' => '3') # => {"bar"=>"1", "bat"=>"3", "baz"=>"2", "foo"=>"0"} @@ -1026,8 +1010,6 @@ module RBS # - ENV.member?(name) -> true or false # - ENV.key?(name) -> true or false # --> - # ENV.has_key?, ENV.member?, and ENV.key? are aliases for ENV.include?. - # # Returns `true` if there is an environment variable with the given `name`: # ENV.replace('foo' => '0', 'bar' => '1') # ENV.include?('foo') # => true @@ -1061,8 +1043,6 @@ module RBS # - ENV.member?(name) -> true or false # - ENV.key?(name) -> true or false # --> - # ENV.has_key?, ENV.member?, and ENV.key? are aliases for ENV.include?. - # # Returns `true` if there is an environment variable with the given `name`: # ENV.replace('foo' => '0', 'bar' => '1') # ENV.include?('foo') # => true @@ -1096,8 +1076,6 @@ module RBS # - ENV.member?(name) -> true or false # - ENV.key?(name) -> true or false # --> - # ENV.has_key?, ENV.member?, and ENV.key? are aliases for ENV.include?. - # # Returns `true` if there is an environment variable with the given `name`: # ENV.replace('foo' => '0', 'bar' => '1') # ENV.include?('foo') # => true @@ -1163,8 +1141,6 @@ module RBS # - ENV.member?(name) -> true or false # - ENV.key?(name) -> true or false # --> - # ENV.has_key?, ENV.member?, and ENV.key? are aliases for ENV.include?. - # # Returns `true` if there is an environment variable with the given `name`: # ENV.replace('foo' => '0', 'bar' => '1') # ENV.include?('foo') # => true diff --git a/core/regexp.rbs b/core/regexp.rbs index 5c7a708f2..2be37a252 100644 --- a/core/regexp.rbs +++ b/core/regexp.rbs @@ -1,116 +1,275 @@ # -# Regular expressions (*regexp*s) are patterns which describe the contents of a -# string. They're used for testing whether a string contains a given pattern, or -# extracting the portions that match. They are created with the `/`*pat*`/` and -# `%r{`*pat*`}` literals or the `Regexp.new` constructor. +# A [regular expression](https://en.wikipedia.org/wiki/Regular_expression) (also +# called a *regexp*) is a *match pattern* (also simply called a *pattern*). # -# A regexp is usually delimited with forward slashes (`/`). For example: +# A common notation for a regexp uses enclosing slash characters: # -# /hay/ =~ 'haystack' #=> 0 -# /y/.match('haystack') #=> # +# /foo/ # -# If a string contains the pattern it is said to *match*. A literal string -# matches itself. +# A regexp may be applied to a *target string*; The part of the string (if any) +# that matches the pattern is called a *match*, and may be said *to match*: # -# Here 'haystack' does not contain the pattern 'needle', so it doesn't match: +# re = /red/ +# re.match?('redirect') # => true # Match at beginning of target. +# re.match?('bored') # => true # Match at end of target. +# re.match?('credit') # => true # Match within target. +# re.match?('foo') # => false # No match. # -# /needle/.match('haystack') #=> nil +# ## Regexp Uses # -# Here 'haystack' contains the pattern 'hay', so it matches: +# A regexp may be used: # -# /hay/.match('haystack') #=> # +# * To extract substrings based on a given pattern: # -# Specifically, `/st/` requires that the string contains the letter *s* followed -# by the letter *t*, so it matches *haystack*, also. +# re = /foo/ # => /foo/ +# re.match('food') # => # +# re.match('good') # => nil # -# Note that any Regexp matching will raise a RuntimeError if timeout is set and -# exceeded. See ["Timeout"](#label-Timeout) section in detail. +# See sections [Method match](rdoc-ref:regexp.rdoc@Method+match) and +# [Operator =~](rdoc-ref:regexp.rdoc@Operator+-3D~). # -# ## Regexp Interpolation +# * To determine whether a string matches a given pattern: # -# A regexp may contain interpolated strings; trivially: +# re.match?('food') # => true +# re.match?('good') # => false # -# foo = 'bar' -# /#{foo}/ # => /bar/ +# See section [Method match?](rdoc-ref:regexp.rdoc@Method+match-3F). # -# ## `=~` and Regexp#match +# * As an argument for calls to certain methods in other classes and modules; +# most such methods accept an argument that may be either a string or the +# (much more powerful) regexp. # -# Pattern matching may be achieved by using `=~` operator or Regexp#match -# method. +# See [Regexp Methods](./Regexp/methods_rdoc.html). # -# ### `=~` Operator # -# `=~` is Ruby's basic pattern-matching operator. When one operand is a regular -# expression and the other is a string then the regular expression is used as a -# pattern to match against the string. (This operator is equivalently defined -# by Regexp and String so the order of String and Regexp do not matter. Other -# classes may have different implementations of `=~`.) If a match is found, the -# operator returns index of first match in string, otherwise it returns `nil`. +# ## Regexp Objects # -# /hay/ =~ 'haystack' #=> 0 -# 'haystack' =~ /hay/ #=> 0 -# /a/ =~ 'haystack' #=> 1 -# /u/ =~ 'haystack' #=> nil +# A regexp object has: # -# Using `=~` operator with a String and Regexp the `$~` global variable is set -# after a successful match. `$~` holds a MatchData object. Regexp.last_match is -# equivalent to `$~`. +# * A source; see [Sources](rdoc-ref:regexp.rdoc@Sources). # -# ### Regexp#match Method +# * Several modes; see [Modes](rdoc-ref:regexp.rdoc@Modes). # -# The #match method returns a MatchData object: +# * A timeout; see [Timeouts](rdoc-ref:regexp.rdoc@Timeouts). # -# /st/.match('haystack') #=> # +# * An encoding; see [Encodings](rdoc-ref:regexp.rdoc@Encodings). # -# ## Metacharacters and Escapes # -# The following are *metacharacters* `(`, `)`, `[`, `]`, `{`, `}`, `.`, `?`, -# `+`, `*`. They have a specific meaning when appearing in a pattern. To match -# them literally they must be backslash-escaped. To match a backslash literally, -# backslash-escape it: `\\\`. +# ## Creating a Regexp # -# /1 \+ 2 = 3\?/.match('Does 1 + 2 = 3?') #=> # -# /a\\\\b/.match('a\\\\b') #=> # +# A regular expression may be created with: # -# Patterns behave like double-quoted strings and can contain the same backslash -# escapes (the meaning of `\s` is different, however, see -# [below](#label-Character+Classes)). +# * A regexp literal using slash characters (see [Regexp +# Literals](https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#l +# abel-Regexp+Literals)): # -# /\s\u{6771 4eac 90fd}/.match("Go to 東京都") -# #=> # +# # This is a very common usage. +# /foo/ # => /foo/ # -# Arbitrary Ruby expressions can be embedded into patterns with the `#{...}` -# construct. +# * A `%r` regexp literal (see [%r: Regexp +# Literals](https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#l +# abel-25r-3A+Regexp+Literals)): # -# place = "東京都" -# /#{place}/.match("Go to 東京都") -# #=> # +# # Same delimiter character at beginning and end; +# # useful for avoiding escaping characters +# %r/name\/value pair/ # => /name\/value pair/ +# %r:name/value pair: # => /name\/value pair/ +# %r|name/value pair| # => /name\/value pair/ # -# ## Character Classes +# # Certain "paired" characters can be delimiters. +# %r[foo] # => /foo/ +# %r{foo} # => /foo/ +# %r(foo) # => /foo/ +# %r # => /foo/ # -# A *character class* is delimited with square brackets (`[`, `]`) and lists -# characters that may appear at that point in the match. `/[ab]/` means *a* or -# *b*, as opposed to `/ab/` which means *a* followed by *b*. +# * Method Regexp.new. # -# /W[aeiou]rd/.match("Word") #=> # # -# Within a character class the hyphen (`-`) is a metacharacter denoting an -# inclusive range of characters. `[abcd]` is equivalent to `[a-d]`. A range can -# be followed by another range, so `[abcdwxyz]` is equivalent to `[a-dw-z]`. The -# order in which ranges or individual characters appear inside a character class -# is irrelevant. +# ## Method `match` # -# /[0-9a-f]/.match('9f') #=> # -# /[9f]/.match('9f') #=> # +# Each of the methods Regexp#match, String#match, and Symbol#match returns a +# MatchData object if a match was found, `nil` otherwise; each also sets [global +# variables](rdoc-ref:regexp.rdoc@Global+Variables): # -# If the first character of a character class is a caret (`^`) the class is -# inverted: it matches any character *except* those named. +# 'food'.match(/foo/) # => # +# 'food'.match(/bar/) # => nil # -# /[^a-eg-z]/.match('f') #=> # +# ## Operator `=~` +# +# Each of the operators Regexp#=~, String#=~, and Symbol#=~ returns an integer +# offset if a match was found, `nil` otherwise; each also sets [global +# variables](rdoc-ref:regexp.rdoc@Global+Variables): +# +# /bar/ =~ 'foo bar' # => 4 +# 'foo bar' =~ /bar/ # => 4 +# /baz/ =~ 'foo bar' # => nil +# +# ## Method `match?` +# +# Each of the methods Regexp#match?, String#match?, and Symbol#match? returns +# `true` if a match was found, `false` otherwise; none sets [global +# variables](rdoc-ref:regexp.rdoc@Global+Variables): +# +# 'food'.match?(/foo/) # => true +# 'food'.match?(/bar/) # => false +# +# ## Global Variables +# +# Certain regexp-oriented methods assign values to global variables: +# +# * `#match`: see [Method match](rdoc-ref:regexp.rdoc@Method+match). +# * `#=~`: see [Operator =~](rdoc-ref:regexp.rdoc@Operator+-3D~). +# +# +# The affected global variables are: +# +# * `$~`: Returns a MatchData object, or `nil`. +# * `$&`: Returns the matched part of the string, or `nil`. +# * `$``: Returns the part of the string to the left of the match, or `nil`. +# * `$'`: Returns the part of the string to the right of the match, or `nil`. +# * `$+`: Returns the last group matched, or `nil`. +# * `$1`, `$2`, etc.: Returns the first, second, etc., matched group, or +# `nil`. Note that `$0` is quite different; it returns the name of the +# currently executing program. +# +# +# Examples: +# +# # Matched string, but no matched groups. +# 'foo bar bar baz'.match('bar') +# $~ # => # +# $& # => "bar" +# $` # => "foo " +# $' # => " bar baz" +# $+ # => nil +# $1 # => nil +# +# # Matched groups. +# /s(\w{2}).*(c)/.match('haystack') +# $~ # => # +# $& # => "stac" +# $` # => "hay" +# $' # => "k" +# $+ # => "c" +# $1 # => "ta" +# $2 # => "c" +# $3 # => nil +# +# # No match. +# 'foo'.match('bar') +# $~ # => nil +# $& # => nil +# $` # => nil +# $' # => nil +# $+ # => nil +# $1 # => nil +# +# Note that Regexp#match?, String#match?, and Symbol#match? do not set global +# variables. +# +# ## Sources +# +# As seen above, the simplest regexp uses a literal expression as its source: +# +# re = /foo/ # => /foo/ +# re.match('food') # => # +# re.match('good') # => nil +# +# A rich collection of available *subexpressions* gives the regexp great power +# and flexibility: +# +# * [Special characters](rdoc-ref:regexp.rdoc@Special+Characters) +# * [Source literals](rdoc-ref:regexp.rdoc@Source+Literals) +# * [Character classes](rdoc-ref:regexp.rdoc@Character+Classes) +# * [Shorthand character +# classes](rdoc-ref:regexp.rdoc@Shorthand+Character+Classes) +# * [Anchors](rdoc-ref:regexp.rdoc@Anchors) +# * [Alternation](rdoc-ref:regexp.rdoc@Alternation) +# * [Quantifiers](rdoc-ref:regexp.rdoc@Quantifiers) +# * [Groups and captures](rdoc-ref:regexp.rdoc@Groups+and+Captures) +# * [Unicode](rdoc-ref:regexp.rdoc@Unicode) +# * [POSIX Bracket +# Expressions](rdoc-ref:regexp.rdoc@POSIX+Bracket+Expressions) +# * [Comments](rdoc-ref:regexp.rdoc@Comments) +# +# +# ### Special Characters +# +# Regexp special characters, called *metacharacters*, have special meanings in +# certain contexts; depending on the context, these are sometimes +# metacharacters: +# +# . ? - + * ^ \ | $ ( ) [ ] { } +# +# To match a metacharacter literally, backslash-escape it: +# +# # Matches one or more 'o' characters. +# /o+/.match('foo') # => # +# # Would match 'o+'. +# /o\+/.match('foo') # => nil +# +# To match a backslash literally, backslash-escape it: +# +# /\./.match('\.') # => # +# /\\./.match('\.') # => # +# +# Method Regexp.escape returns an escaped string: +# +# Regexp.escape('.?-+*^\|$()[]{}') +# # => "\\.\\?\\-\\+\\*\\^\\\\\\|\\$\\(\\)\\[\\]\\{\\}" +# +# ### Source Literals +# +# The source literal largely behaves like a double-quoted string; see [String +# Literals](rdoc-ref:syntax/literals.rdoc@String+Literals). +# +# In particular, a source literal may contain interpolated expressions: +# +# s = 'foo' # => "foo" +# /#{s}/ # => /foo/ +# /#{s.capitalize}/ # => /Foo/ +# /#{2 + 2}/ # => /4/ +# +# There are differences between an ordinary string literal and a source literal; +# see [Shorthand Character +# Classes](rdoc-ref:regexp.rdoc@Shorthand+Character+Classes). +# +# * `\s` in an ordinary string literal is equivalent to a space character; in +# a source literal, it's shorthand for matching a whitespace character. +# * In an ordinary string literal, these are (needlessly) escaped characters; +# in a source literal, they are shorthands for various matching characters: +# +# \w \W \d \D \h \H \S \R +# +# +# ### Character Classes +# +# A *character class* is delimited by square brackets; it specifies that certain +# characters match at a given point in the target string: +# +# # This character class will match any vowel. +# re = /B[aeiou]rd/ +# re.match('Bird') # => # +# re.match('Bard') # => # +# re.match('Byrd') # => nil +# +# A character class may contain hyphen characters to specify ranges of +# characters: +# +# # These regexps have the same effect. +# /[abcdef]/.match('foo') # => # +# /[a-f]/.match('foo') # => # +# /[a-cd-f]/.match('foo') # => # +# +# When the first character of a character class is a caret (`^`), the sense of +# the class is inverted: it matches any character *except* those specified. +# +# /[^a-eg-z]/.match('f') # => # # # A character class may contain another character class. By itself this isn't -# useful because `[a-z[0-9]]` describes the same set as `[a-z0-9]`. However, -# character classes also support the `&&` operator which performs set +# useful because `[a-z[0-9]]` describes the same set as `[a-z0-9]`. +# +# However, character classes also support the `&&` operator, which performs set # intersection on its arguments. The two can be combined as follows: # # /[a-w&&[^c-g]z]/ # ([a-w] AND ([^c-g] OR z)) @@ -119,238 +278,481 @@ # # /[abh-w]/ # -# The following metacharacters also behave like character classes: -# -# * `/./` - Any character except a newline. -# * `/./m` - Any character (the `m` modifier enables multiline mode) -# * `/\w/` - A word character (`[a-zA-Z0-9_]`) -# * `/\W/` - A non-word character (`[^a-zA-Z0-9_]`). Please take a look at -# [Bug #4044](https://bugs.ruby-lang.org/issues/4044) if using `/\W/` with -# the `/i` modifier. -# * `/\d/` - A digit character (`[0-9]`) -# * `/\D/` - A non-digit character (`[^0-9]`) -# * `/\h/` - A hexdigit character (`[0-9a-fA-F]`) -# * `/\H/` - A non-hexdigit character (`[^0-9a-fA-F]`) -# * `/\s/` - A whitespace character: `/[ \t\r\n\f\v]/` -# * `/\S/` - A non-whitespace character: `/[^ \t\r\n\f\v]/` -# * `/\R/` - A linebreak: `\n`, `\v`, `\f`, `\r` `\u0085` (NEXT LINE), -# `\u2028` (LINE SEPARATOR), `\u2029` (PARAGRAPH SEPARATOR) or `\r\n`. -# -# -# POSIX *bracket expressions* are also similar to character classes. They -# provide a portable alternative to the above, with the added benefit that they -# encompass non-ASCII characters. For instance, `/\d/` matches only the ASCII -# decimal digits (0-9); whereas `/[[:digit:]]/` matches any character in the -# Unicode *Nd* category. -# -# * `/[[:alnum:]]/` - Alphabetic and numeric character -# * `/[[:alpha:]]/` - Alphabetic character -# * `/[[:blank:]]/` - Space or tab -# * `/[[:cntrl:]]/` - Control character -# * `/[[:digit:]]/` - Digit -# * `/[[:graph:]]/` - Non-blank character (excludes spaces, control -# characters, and similar) -# * `/[[:lower:]]/` - Lowercase alphabetical character -# * `/[[:print:]]/` - Like [:graph:], but includes the space character -# * `/[[:punct:]]/` - Punctuation character -# * `/[[:space:]]/` - Whitespace character (`[:blank:]`, newline, carriage -# return, etc.) -# * `/[[:upper:]]/` - Uppercase alphabetical -# * `/[[:xdigit:]]/` - Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F) +# ### Shorthand Character Classes # +# Each of the following metacharacters serves as a shorthand for a character +# class: # -# Ruby also supports the following non-POSIX character classes: +# * `/./`: Matches any character except a newline: # -# * `/[[:word:]]/` - A character in one of the following Unicode general -# categories *Letter*, *Mark*, *Number*, *Connector_Punctuation* -# * `/[[:ascii:]]/` - A character in the ASCII character set +# /./.match('foo') # => # +# /./.match("\n") # => nil # -# # U+06F2 is "EXTENDED ARABIC-INDIC DIGIT TWO" -# /[[:digit:]]/.match("\u06F2") #=> # -# /[[:upper:]][[:lower:]]/.match("Hello") #=> # -# /[[:xdigit:]][[:xdigit:]]/.match("A6") #=> # +# * `/./m`: Matches any character, including a newline; see {Multiline +# Mode}[regexp.rdoc@Multiline+Mode}: # +# /./m.match("\n") # => # # -# ## Repetition +# * `/\w/`: Matches a word character: equivalent to `[a-zA-Z0-9_]`: # -# The constructs described so far match a single character. They can be followed -# by a repetition metacharacter to specify how many times they need to occur. -# Such metacharacters are called *quantifiers*. +# /\w/.match(' foo') # => # +# /\w/.match(' _') # => # +# /\w/.match(' ') # => nil # -# * `*` - Zero or more times -# * `+` - One or more times -# * `?` - Zero or one times (optional) -# * `{`*n*`}` - Exactly *n* times -# * `{`*n*`,}` - *n* or more times -# * `{,`*m*`}` - *m* or less times -# * `{`*n*`,`*m*`}` - At least *n* and at most *m* times +# * `/\W/`: Matches a non-word character: equivalent to `[^a-zA-Z0-9_]`: # +# /\W/.match(' ') # => # +# /\W/.match('_') # => nil # -# At least one uppercase character ('H'), at least one lowercase character -# ('e'), two 'l' characters, then one 'o': +# * `/\d/`: Matches a digit character: equivalent to `[0-9]`: # -# "Hello".match(/[[:upper:]]+[[:lower:]]+l{2}o/) #=> # +# /\d/.match('THX1138') # => # +# /\d/.match('foo') # => nil # -# ### Greedy Match +# * `/\D/`: Matches a non-digit character: equivalent to `[^0-9]`: # -# Repetition is *greedy* by default: as many occurrences as possible are matched -# while still allowing the overall match to succeed. By contrast, *lazy* -# matching makes the minimal amount of matches necessary for overall success. -# Most greedy metacharacters can be made lazy by following them with `?`. For -# the `{n}` pattern, because it specifies an exact number of characters to match -# and not a variable number of characters, the `?` metacharacter instead makes -# the repeated pattern optional. +# /\D/.match('123Jump!') # => # +# /\D/.match('123') # => nil # -# Both patterns below match the string. The first uses a greedy quantifier so -# '.+' matches ''; the second uses a lazy quantifier so '.+?' matches -# '': +# * `/\h/`: Matches a hexdigit character: equivalent to `[0-9a-fA-F]`: # -# /<.+>/.match("") #=> #"> -# /<.+?>/.match("") #=> #"> +# /\h/.match('xyz fedcba9876543210') # => # +# /\h/.match('xyz') # => nil # -# ### Possessive Match +# * `/\H/`: Matches a non-hexdigit character: equivalent to `[^0-9a-fA-F]`: # -# A quantifier followed by `+` matches *possessively*: once it has matched it -# does not backtrack. They behave like greedy quantifiers, but having matched -# they refuse to "give up" their match even if this jeopardises the overall -# match. +# /\H/.match('fedcba9876543210xyz') # => # +# /\H/.match('fedcba9876543210') # => nil # -# /<.*><.+>/.match("") #=> #"> -# /<.*+><.+>/.match("") #=> nil -# /<.*><.++>/.match("") #=> nil +# * `/\s/`: Matches a whitespace character: equivalent to `/[ \t\r\n\f\v]/`: # -# ## Capturing +# /\s/.match('foo bar') # => # +# /\s/.match('foo') # => nil # -# Parentheses can be used for *capturing*. The text enclosed by the *n*th group -# of parentheses can be subsequently referred to with *n*. Within a pattern use -# the *backreference* `\n` (e.g. `\1`); outside of the pattern use -# `MatchData[n]` (e.g. `MatchData[1]`). +# * `/\S/`: Matches a non-whitespace character: equivalent to `/[^ +# \t\r\n\f\v]/`: # -# In this example, `'at'` is captured by the first group of parentheses, then -# referred to later with `\1`: +# /\S/.match(" \t\r\n\f\v foo") # => # +# /\S/.match(" \t\r\n\f\v") # => nil # -# /[csh](..) [csh]\1 in/.match("The cat sat in the hat") -# #=> # +# * `/\R/`: Matches a linebreak, platform-independently: # -# Regexp#match returns a MatchData object which makes the captured text -# available with its #[] method: +# /\R/.match("\r") # => # # Carriage return (CR) +# /\R/.match("\n") # => # # Newline (LF) +# /\R/.match("\f") # => # # Formfeed (FF) +# /\R/.match("\v") # => # # Vertical tab (VT) +# /\R/.match("\r\n") # => # # CRLF +# /\R/.match("\u0085") # => # # Next line (NEL) +# /\R/.match("\u2028") # => # # Line separator (LSEP) +# /\R/.match("\u2029") # => # # Paragraph separator (PSEP) # -# /[csh](..) [csh]\1 in/.match("The cat sat in the hat")[1] #=> 'at' # -# While Ruby supports an arbitrary number of numbered captured groups, only -# groups 1-9 are supported using the `\n` backreference syntax. +# ### Anchors # -# Ruby also supports `\0` as a special backreference, which references the -# entire matched string. This is also available at `MatchData[0]`. Note that -# the `\0` backreference cannot be used inside the regexp, as backreferences can -# only be used after the end of the capture group, and the `\0` backreference -# uses the implicit capture group of the entire match. However, you can use -# this backreference when doing substitution: +# An anchor is a metasequence that matches a zero-width position between +# characters in the target string. # -# "The cat sat in the hat".gsub(/[csh]at/, '\0s') -# # => "The cats sats in the hats" +# For a subexpression with no anchor, matching may begin anywhere in the target +# string: # -# ### Named Captures +# /real/.match('surrealist') # => # # -# Capture groups can be referred to by name when defined with the -# `(?<`*name*`>)` or `(?'`*name*`')` constructs. +# For a subexpression with an anchor, matching must begin at the matched anchor. # -# /\$(?\d+)\.(?\d+)/.match("$3.67") -# #=> # -# /\$(?\d+)\.(?\d+)/.match("$3.67")[:dollars] #=> "3" +# #### Boundary Anchors # -# Named groups can be backreferenced with `\k<`*name*`>`, where *name* is the -# group name. +# Each of these anchors matches a boundary: # -# /(?[aeiou]).\k.\k/.match('ototomy') -# #=> # +# * `^`: Matches the beginning of a line: +# +# /^bar/.match("foo\nbar") # => # +# /^ar/.match("foo\nbar") # => nil +# +# * `$`: Matches the end of a line: +# +# /bar$/.match("foo\nbar") # => # +# /ba$/.match("foo\nbar") # => nil +# +# * `\A`: Matches the beginning of the string: +# +# /\Afoo/.match('foo bar') # => # +# /\Afoo/.match(' foo bar') # => nil +# +# * `\Z`: Matches the end of the string; if string ends with a single newline, +# it matches just before the ending newline: +# +# /foo\Z/.match('bar foo') # => # +# /foo\Z/.match('foo bar') # => nil +# /foo\Z/.match("bar foo\n") # => # +# /foo\Z/.match("bar foo\n\n") # => nil +# +# * `\z`: Matches the end of the string: +# +# /foo\z/.match('bar foo') # => # +# /foo\z/.match('foo bar') # => nil +# /foo\z/.match("bar foo\n") # => nil +# +# * `\b`: Matches word boundary when not inside brackets; matches backspace +# (`"0x08"`) when inside brackets: +# +# /foo\b/.match('foo bar') # => # +# /foo\b/.match('foobar') # => nil +# +# * `\B`: Matches non-word boundary: +# +# /foo\B/.match('foobar') # => # +# /foo\B/.match('foo bar') # => nil +# +# * `\G`: Matches first matching position: +# +# In methods like String#gsub and String#scan, it changes on each iteration. +# It initially matches the beginning of subject, and in each following +# iteration it matches where the last match finished. +# +# " a b c".gsub(/ /, '_') # => "____a_b_c" +# " a b c".gsub(/\G /, '_') # => "____a b c" +# +# In methods like Regexp#match and String#match that take an optional +# offset, it matches where the search begins. +# +# "hello, world".match(/,/, 3) # => # +# "hello, world".match(/\G,/, 3) # => nil +# +# +# #### Lookaround Anchors +# +# Lookahead anchors: +# +# * `(?=*pat*)`: Positive lookahead assertion: ensures that the following +# characters match *pat*, but doesn't include those characters in the +# matched substring. +# +# * `(?!*pat*)`: Negative lookahead assertion: ensures that the following +# characters *do not* match *pat*, but doesn't include those characters in +# the matched substring. +# +# +# Lookbehind anchors: +# +# * `(?<=*pat*)`: Positive lookbehind assertion: ensures that the preceding +# characters match *pat*, but doesn't include those characters in the +# matched substring. +# +# * `(?)\w+(?=<\/b>)/.match("Fortune favors the bold.") +# # => # +# +# #### Match-Reset Anchor +# +# * `\K`: Match reset: the matched content preceding `\K` in the regexp is +# excluded from the result. For example, the following two regexps are +# almost equivalent: +# +# /ab\Kc/.match('abc') # => # +# /(?<=ab)c/.match('abc') # => # +# +# These match same string and `$&` equals `'c'`, while the matched position +# is different. +# +# As are the following two regexps: +# +# /(a)\K(b)\Kc/ +# /(?<=(?<=(a))(b))c/ +# +# +# ### Alternation +# +# The vertical bar metacharacter (`|`) may be used within parentheses to express +# alternation: two or more subexpressions any of which may match the target +# string. +# +# Two alternatives: +# +# re = /(a|b)/ +# re.match('foo') # => nil +# re.match('bar') # => # +# +# Four alternatives: +# +# re = /(a|b|c|d)/ +# re.match('shazam') # => # +# re.match('cold') # => # +# +# Each alternative is a subexpression, and may be composed of other +# subexpressions: +# +# re = /([a-c]|[x-z])/ +# re.match('bar') # => # +# re.match('ooz') # => # +# +# Method Regexp.union provides a convenient way to construct a regexp with +# alternatives. +# +# ### Quantifiers +# +# A simple regexp matches one character: +# +# /\w/.match('Hello') # => # +# +# An added *quantifier* specifies how many matches are required or allowed: +# +# * `*` - Matches zero or more times: +# +# /\w*/.match('') +# # => # +# /\w*/.match('x') +# # => # +# /\w*/.match('xyz') +# # => # +# +# * `+` - Matches one or more times: +# +# /\w+/.match('') # => nil +# /\w+/.match('x') # => # +# /\w+/.match('xyz') # => # +# +# * `?` - Matches zero or one times: +# +# /\w?/.match('') # => # +# /\w?/.match('x') # => # +# /\w?/.match('xyz') # => # +# +# * `{`*n*`}` - Matches exactly *n* times: +# +# /\w{2}/.match('') # => nil +# /\w{2}/.match('x') # => nil +# /\w{2}/.match('xyz') # => # +# +# * `{`*min*`,}` - Matches *min* or more times: +# +# /\w{2,}/.match('') # => nil +# /\w{2,}/.match('x') # => nil +# /\w{2,}/.match('xy') # => # +# /\w{2,}/.match('xyz') # => # +# +# * `{,`*max*`}` - Matches *max* or fewer times: +# +# /\w{,2}/.match('') # => # +# /\w{,2}/.match('x') # => # +# /\w{,2}/.match('xyz') # => # +# +# * `{`*min*`,`*max*`}` - Matches at least *min* times and at most *max* +# times: +# +# /\w{1,2}/.match('') # => nil +# /\w{1,2}/.match('x') # => # +# /\w{1,2}/.match('xyz') # => # +# +# +# #### Greedy, Lazy, or Possessive Matching +# +# Quantifier matching may be greedy, lazy, or possessive: +# +# * In *greedy* matching, as many occurrences as possible are matched while +# still allowing the overall match to succeed. Greedy quantifiers: `*`, `+`, +# `?`, `{min, max}` and its variants. +# * In *lazy* matching, the minimum number of occurrences are matched. Lazy +# quantifiers: `*?`, `+?`, `??`, `{min, max}?` and its variants. +# * In *possessive* matching, once a match is found, there is no backtracking; +# that match is retained, even if it jeopardises the overall match. +# Possessive quantifiers: `*+`, `++`, `?+`. Note that `{min, max}` and its +# variants do *not* support possessive matching. +# +# +# More: +# +# * About greedy and lazy matching, see [Choosing Minimal or Maximal +# Repetition](https://doc.lagout.org/programmation/Regular%20Expressions/Reg +# ular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Progr +# amming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%20201 +# 2-09-06%5D.pdf#tutorial-backtrack). +# * About possessive matching, see [Eliminate Needless +# Backtracking](https://doc.lagout.org/programmation/Regular%20Expressions/R +# egular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Pro +# gramming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202 +# 012-09-06%5D.pdf#tutorial-backtrack). +# +# +# ### Groups and Captures +# +# A simple regexp has (at most) one match: +# +# re = /\d\d\d\d-\d\d-\d\d/ +# re.match('1943-02-04') # => # +# re.match('1943-02-04').size # => 1 +# re.match('foo') # => nil +# +# Adding one or more pairs of parentheses, `(*subexpression*)`, defines +# *groups*, which may result in multiple matched substrings, called *captures*: +# +# re = /(\d\d\d\d)-(\d\d)-(\d\d)/ +# re.match('1943-02-04') # => # +# re.match('1943-02-04').size # => 4 +# +# The first capture is the entire matched string; the other captures are the +# matched substrings from the groups. +# +# A group may have a [quantifier](rdoc-ref:regexp.rdoc@Quantifiers): +# +# re = /July 4(th)?/ +# re.match('July 4') # => # +# re.match('July 4th') # => # +# +# re = /(foo)*/ +# re.match('') # => # +# re.match('foo') # => # +# re.match('foofoo') # => # # -# **Note**: A regexp can't use named backreferences and numbered backreferences -# simultaneously. Also, if a named capture is used in a regexp, then parentheses -# used for grouping which would otherwise result in a unnamed capture are -# treated as non-capturing. +# re = /(foo)+/ +# re.match('') # => nil +# re.match('foo') # => # +# re.match('foofoo') # => # # -# /(\w)(\w)/.match("ab").captures # => ["a", "b"] -# /(\w)(\w)/.match("ab").named_captures # => {} +# The returned MatchData object gives access to the matched substrings: # -# /(?\w)(\w)/.match("ab").captures # => ["a"] -# /(?\w)(\w)/.match("ab").named_captures # => {"c"=>"a"} +# re = /(\d\d\d\d)-(\d\d)-(\d\d)/ +# md = re.match('1943-02-04') +# # => # +# md[0] # => "1943-02-04" +# md[1] # => "1943" +# md[2] # => "02" +# md[3] # => "04" # -# When named capture groups are used with a literal regexp on the left-hand side -# of an expression and the `=~` operator, the captured text is also assigned to -# local variables with corresponding names. +# #### Non-Capturing Groups # -# /\$(?\d+)\.(?\d+)/ =~ "$3.67" #=> 0 -# dollars #=> "3" +# A group may be made non-capturing; it is still a group (and, for example, can +# have a quantifier), but its matching substring is not included among the +# captures. # -# ## Grouping +# A non-capturing group begins with `?:` (inside the parentheses): # -# Parentheses also *group* the terms they enclose, allowing them to be -# quantified as one *atomic* whole. +# # Don't capture the year. +# re = /(?:\d\d\d\d)-(\d\d)-(\d\d)/ +# md = re.match('1943-02-04') # => # # -# The pattern below matches a vowel followed by 2 word characters: +# #### Backreferences # -# /[aeiou]\w{2}/.match("Caenorhabditis elegans") #=> # +# A group match may also be referenced within the regexp itself; such a +# reference is called a `backreference`: # -# Whereas the following pattern matches a vowel followed by a word character, -# twice, i.e. `[aeiou]\w[aeiou]\w`: 'enor'. +# /[csh](..) [csh]\1 in/.match('The cat sat in the hat') +# # => # # -# /([aeiou]\w){2}/.match("Caenorhabditis elegans") -# #=> # +# This table shows how each subexpression in the regexp above matches a +# substring in the target string: # -# The `(?:`...`)` construct provides grouping without capturing. That is, it -# combines the terms it contains into an atomic whole without creating a -# backreference. This benefits performance at the slight expense of readability. +# | Subexpression in Regexp | Matching Substring in Target String | +# |---------------------------|-------------------------------------| +# | First '[csh]' | Character 'c' | +# | '(..)' | First substring 'at' | +# | First space ' ' | First space character ' ' | +# | Second '[csh]' | Character 's' | +# | '\1' (backreference 'at') | Second substring 'at' | +# | ' in' | Substring ' in' | # -# The first group of parentheses captures 'n' and the second 'ti'. The second -# group is referred to later with the backreference `\2`: +# A regexp may contain any number of groups: # -# /I(n)ves(ti)ga\2ons/.match("Investigations") -# #=> # +# * For a large number of groups: # -# The first group of parentheses is now made non-capturing with '?:', so it -# still matches 'n', but doesn't create the backreference. Thus, the -# backreference `\1` now refers to 'ti'. +# * The ordinary `\*n`* notation applies only for *n* in range (1..9). +# * The `MatchData[*n*]` notation applies for any non-negative *n*. # -# /I(?:n)ves(ti)ga\1ons/.match("Investigations") -# #=> # # -# ### Atomic Grouping +# * `\0` is a special backreference, referring to the entire matched string; +# it may not be used within the regexp itself, but may be used outside it +# (for example, in a substitution method call): # -# Grouping can be made *atomic* with `(?>`*pat*`)`. This causes the -# subexpression *pat* to be matched independently of the rest of the expression -# such that what it matches becomes fixed for the remainder of the match, unless -# the entire subexpression must be abandoned and subsequently revisited. In this -# way *pat* is treated as a non-divisible whole. Atomic grouping is typically -# used to optimise patterns so as to prevent the regular expression engine from -# backtracking needlessly. +# 'The cat sat in the hat'.gsub(/[csh]at/, '\0s') +# # => "The cats sats in the hats" # -# The `"` in the pattern below matches the first character of the string, then -# `.*` matches *Quote"*. This causes the overall match to fail, so the text -# matched by `.*` is backtracked by one position, which leaves the final -# character of the string available to match `"` # -# /".*"/.match('"Quote"') #=> # +# #### Named Captures # -# If `.*` is grouped atomically, it refuses to backtrack *Quote"*, even though -# this means that the overall match fails +# As seen above, a capture can be referred to by its number. A capture can also +# have a name, prefixed as `?<*name*>` or `?'*name*'`, and the name (symbolized) +# may be used as an index in `MatchData[]`: # -# /"(?>.*)"/.match('"Quote"') #=> nil +# md = /\$(?\d+)\.(?'cents'\d+)/.match("$3.67") +# # => # +# md[:dollars] # => "3" +# md[:cents] # => "67" +# # The capture numbers are still valid. +# md[2] # => "67" # -# ## Subexpression Calls +# When a regexp contains a named capture, there are no unnamed captures: # -# The `\g<`*name*`>` syntax matches the previous subexpression named *name*, -# which can be a group name or number, again. This differs from backreferences -# in that it re-executes the group rather than simply trying to re-match the -# same text. +# /\$(?\d+)\.(\d+)/.match("$3.67") +# # => # # -# This pattern matches a *(* character and assigns it to the `paren` group, -# tries to call that the `paren` sub-expression again but fails, then matches a -# literal *)*: +# A named group may be backreferenced as `\k<*name*>`: # -# /\A(?\(\g*\))*\z/ =~ '()' +# /(?[aeiou]).\k.\k/.match('ototomy') +# # => # +# +# When (and only when) a regexp contains named capture groups and appears before +# the `=~` operator, the captured substrings are assigned to local variables +# with corresponding names: +# +# /\$(?\d+)\.(?\d+)/ =~ '$3.67' +# dollars # => "3" +# cents # => "67" +# +# Method Regexp#named_captures returns a hash of the capture names and +# substrings; method Regexp#names returns an array of the capture names. +# +# #### Atomic Grouping +# +# A group may be made *atomic* with `(?>`*subexpression*`)`. +# +# This causes the subexpression to be matched independently of the rest of the +# expression, so that the matched substring becomes fixed for the remainder of +# the match, unless the entire subexpression must be abandoned and subsequently +# revisited. +# +# In this way *subexpression* is treated as a non-divisible whole. Atomic +# grouping is typically used to optimise patterns to prevent needless +# backtracking . +# +# Example (without atomic grouping): +# +# /".*"/.match('"Quote"') # => # +# +# Analysis: +# +# 1. The leading subexpression `"` in the pattern matches the first character +# `"` in the target string. +# 2. The next subexpression `.*` matches the next substring `Quote“` (including +# the trailing double-quote). +# 3. Now there is nothing left in the target string to match the trailing +# subexpression `"` in the pattern; this would cause the overall match to +# fail. +# 4. The matched substring is backtracked by one position: `Quote`. +# 5. The final subexpression `"` now matches the final substring `"`, and the +# overall match succeeds. +# +# +# If subexpression `.*` is grouped atomically, the backtracking is disabled, and +# the overall match fails: +# +# /"(?>.*)"/.match('"Quote"') # => nil +# +# Atomic grouping can affect performance; see [Atomic +# Group](https://www.regular-expressions.info/atomic.html). +# +# #### Subexpression Calls +# +# As seen above, a backreference number (`\*n`*) or name (`\k<*name*>`) gives +# access to a captured *substring*; the corresponding regexp *subexpression* may +# also be accessed, via the number (`\\g*n`*) or name (`\g<*name*>`): # -# /\A(?\(\g*\))*\z/ =~ '(())' #=> 0 +# /\A(?\(\g*\))*\z/.match('(())') # # ^1 # # ^2 # # ^3 @@ -362,415 +764,566 @@ # # ^9 # # ^10 # +# The pattern: +# # 1. Matches at the beginning of the string, i.e. before the first character. -# 2. Enters a named capture group called `paren` -# 3. Matches a literal *(*, the first character in the string -# 4. Calls the `paren` group again, i.e. recurses back to the second step -# 5. Re-enters the `paren` group -# 6. Matches a literal *(*, the second character in the string -# 7. Try to call `paren` a third time, but fail because doing so would prevent -# an overall successful match -# 8. Match a literal *)*, the third character in the string. Marks the end of -# the second recursive call -# 9. Match a literal *)*, the fourth character in the string -# 10. Match the end of the string -# -# -# ## Alternation -# -# The vertical bar metacharacter (`|`) combines several expressions into a -# single one that matches any of the expressions. Each expression is an -# *alternative*. -# -# /\w(and|or)\w/.match("Feliformia") #=> # -# /\w(and|or)\w/.match("furandi") #=> # -# /\w(and|or)\w/.match("dissemblance") #=> nil -# -# ## Character Properties -# -# The `\p{}` construct matches characters with the named property, much like -# POSIX bracket classes. -# -# * `/\p{Alnum}/` - Alphabetic and numeric character -# * `/\p{Alpha}/` - Alphabetic character -# * `/\p{Blank}/` - Space or tab -# * `/\p{Cntrl}/` - Control character -# * `/\p{Digit}/` - Digit -# * `/\p{Emoji}/` - Unicode emoji -# * `/\p{Graph}/` - Non-blank character (excludes spaces, control characters, -# and similar) -# * `/\p{Lower}/` - Lowercase alphabetical character -# * `/\p{Print}/` - Like `\p{Graph}`, but includes the space character -# * `/\p{Punct}/` - Punctuation character -# * `/\p{Space}/` - Whitespace character (`[:blank:]`, newline, carriage +# 2. Enters a named group `paren`. +# 3. Matches the first character in the string, `'('`. +# 4. Calls the `paren` group again, i.e. recurses back to the second step. +# 5. Re-enters the `paren` group. +# 6. Matches the second character in the string, `'('`. +# 7. Attempts to call `paren` a third time, but fails because doing so would +# prevent an overall successful match. +# 8. Matches the third character in the string, `')'`; marks the end of the +# second recursive call +# 9. Matches the fourth character in the string, `')'`. +# 10. Matches the end of the string. +# +# +# See [Subexpression +# calls](https://learnbyexample.github.io/Ruby_Regexp/groupings-and-backreferenc +# es.html?highlight=subexpression#subexpression-calls). +# +# #### Conditionals +# +# The conditional construct takes the form `(?(*cond*)*yes*|*no*)`, where: +# +# * *cond* may be a capture number or name. +# * The match to be applied is *yes* if *cond* is captured; otherwise the +# match to be applied is *no*. +# * If not needed, `|*no`* may be omitted. +# +# +# Examples: +# +# re = /\A(foo)?(?(1)(T)|(F))\z/ +# re.match('fooT') # => # +# re.match('F') # => # +# re.match('fooF') # => nil +# re.match('T') # => nil +# +# re = /\A(?foo)?(?()(T)|(F))\z/ +# re.match('fooT') # => # +# re.match('F') # => # +# re.match('fooF') # => nil +# re.match('T') # => nil +# +# #### Absence Operator +# +# The absence operator is a special group that matches anything which does *not* +# match the contained subexpressions. +# +# /(?~real)/.match('surrealist') # => # +# /(?~real)ist/.match('surrealist') # => # +# /sur(?~real)ist/.match('surrealist') # => nil +# +# ### Unicode +# +# #### Unicode Properties +# +# The `/\p{*property_name*}/` construct (with lowercase `p`) matches characters +# using a Unicode property name, much like a character class; property `Alpha` +# specifies alphabetic characters: +# +# /\p{Alpha}/.match('a') # => # +# /\p{Alpha}/.match('1') # => nil +# +# A property can be inverted by prefixing the name with a caret character (`^`): +# +# /\p{^Alpha}/.match('1') # => # +# /\p{^Alpha}/.match('a') # => nil +# +# Or by using `\P` (uppercase `P`): +# +# /\P{Alpha}/.match('1') # => # +# /\P{Alpha}/.match('a') # => nil +# +# See [Unicode Properties](./Regexp/unicode_properties_rdoc.html) for regexps +# based on the numerous properties. +# +# Some commonly-used properties correspond to POSIX bracket expressions: +# +# * `/\p{Alnum}/`: Alphabetic and numeric character +# * `/\p{Alpha}/`: Alphabetic character +# * `/\p{Blank}/`: Space or tab +# * `/\p{Cntrl}/`: Control character +# * `/\p{Digit}/`: Digit characters, and similar) +# * `/\p{Lower}/`: Lowercase alphabetical character +# * `/\p{Print}/`: Like `\p{Graph}`, but includes the space character +# * `/\p{Punct}/`: Punctuation character +# * `/\p{Space}/`: Whitespace character (`[:blank:]`, newline, carriage # return, etc.) -# * `/\p{Upper}/` - Uppercase alphabetical -# * `/\p{XDigit}/` - Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F) -# * `/\p{Word}/` - A member of one of the following Unicode general category -# *Letter*, *Mark*, *Number*, *Connector_Punctuation* -# * `/\p{ASCII}/` - A character in the ASCII character set -# * `/\p{Any}/` - Any Unicode character (including unassigned characters) -# * `/\p{Assigned}/` - An assigned character -# -# -# A Unicode character's *General Category* value can also be matched with -# `\p{`*Ab*`}` where *Ab* is the category's abbreviation as described below: -# -# * `/\p{L}/` - 'Letter' -# * `/\p{Ll}/` - 'Letter: Lowercase' -# * `/\p{Lm}/` - 'Letter: Mark' -# * `/\p{Lo}/` - 'Letter: Other' -# * `/\p{Lt}/` - 'Letter: Titlecase' -# * `/\p{Lu}/` - 'Letter: Uppercase -# * `/\p{Lo}/` - 'Letter: Other' -# * `/\p{M}/` - 'Mark' -# * `/\p{Mn}/` - 'Mark: Nonspacing' -# * `/\p{Mc}/` - 'Mark: Spacing Combining' -# * `/\p{Me}/` - 'Mark: Enclosing' -# * `/\p{N}/` - 'Number' -# * `/\p{Nd}/` - 'Number: Decimal Digit' -# * `/\p{Nl}/` - 'Number: Letter' -# * `/\p{No}/` - 'Number: Other' -# * `/\p{P}/` - 'Punctuation' -# * `/\p{Pc}/` - 'Punctuation: Connector' -# * `/\p{Pd}/` - 'Punctuation: Dash' -# * `/\p{Ps}/` - 'Punctuation: Open' -# * `/\p{Pe}/` - 'Punctuation: Close' -# * `/\p{Pi}/` - 'Punctuation: Initial Quote' -# * `/\p{Pf}/` - 'Punctuation: Final Quote' -# * `/\p{Po}/` - 'Punctuation: Other' -# * `/\p{S}/` - 'Symbol' -# * `/\p{Sm}/` - 'Symbol: Math' -# * `/\p{Sc}/` - 'Symbol: Currency' -# * `/\p{Sc}/` - 'Symbol: Currency' -# * `/\p{Sk}/` - 'Symbol: Modifier' -# * `/\p{So}/` - 'Symbol: Other' -# * `/\p{Z}/` - 'Separator' -# * `/\p{Zs}/` - 'Separator: Space' -# * `/\p{Zl}/` - 'Separator: Line' -# * `/\p{Zp}/` - 'Separator: Paragraph' -# * `/\p{C}/` - 'Other' -# * `/\p{Cc}/` - 'Other: Control' -# * `/\p{Cf}/` - 'Other: Format' -# * `/\p{Cn}/` - 'Other: Not Assigned' -# * `/\p{Co}/` - 'Other: Private Use' -# * `/\p{Cs}/` - 'Other: Surrogate' -# -# -# Lastly, `\p{}` matches a character's Unicode *script*. The following scripts -# are supported: *Arabic*, *Armenian*, *Balinese*, *Bengali*, *Bopomofo*, -# *Braille*, *Buginese*, *Buhid*, *Canadian_Aboriginal*, *Carian*, *Cham*, -# *Cherokee*, *Common*, *Coptic*, *Cuneiform*, *Cypriot*, *Cyrillic*, *Deseret*, -# *Devanagari*, *Ethiopic*, *Georgian*, *Glagolitic*, *Gothic*, *Greek*, -# *Gujarati*, *Gurmukhi*, *Han*, *Hangul*, *Hanunoo*, *Hebrew*, *Hiragana*, -# *Inherited*, *Kannada*, *Katakana*, *Kayah_Li*, *Kharoshthi*, *Khmer*, *Lao*, -# *Latin*, *Lepcha*, *Limbu*, *Linear_B*, *Lycian*, *Lydian*, *Malayalam*, -# *Mongolian*, *Myanmar*, *New_Tai_Lue*, *Nko*, *Ogham*, *Ol_Chiki*, -# *Old_Italic*, *Old_Persian*, *Oriya*, *Osmanya*, *Phags_Pa*, *Phoenician*, -# *Rejang*, *Runic*, *Saurashtra*, *Shavian*, *Sinhala*, *Sundanese*, -# *Syloti_Nagri*, *Syriac*, *Tagalog*, *Tagbanwa*, *Tai_Le*, *Tamil*, *Telugu*, -# *Thaana*, *Thai*, *Tibetan*, *Tifinagh*, *Ugaritic*, *Vai*, and *Yi*. -# -# Unicode codepoint U+06E9 is named "ARABIC PLACE OF SAJDAH" and belongs to the -# Arabic script: -# -# /\p{Arabic}/.match("\u06E9") #=> # -# -# All character properties can be inverted by prefixing their name with a caret -# (`^`). -# -# Letter 'A' is not in the Unicode Ll (Letter; Lowercase) category, so this -# match succeeds: -# -# /\p{^Ll}/.match("A") #=> # -# -# ## Anchors -# -# Anchors are metacharacter that match the zero-width positions between -# characters, *anchoring* the match to a specific position. -# -# * `^` - Matches beginning of line -# * `$` - Matches end of line -# * `\A` - Matches beginning of string. -# * `\Z` - Matches end of string. If string ends with a newline, it matches -# just before newline -# * `\z` - Matches end of string -# * `\G` - Matches first matching position: -# -# In methods like `String#gsub` and `String#scan`, it changes on each -# iteration. It initially matches the beginning of subject, and in each -# following iteration it matches where the last match finished. -# -# " a b c".gsub(/ /, '_') #=> "____a_b_c" -# " a b c".gsub(/\G /, '_') #=> "____a b c" -# -# In methods like `Regexp#match` and `String#match` that take an (optional) -# offset, it matches where the search begins. +# * `/\p{Upper}/`: Uppercase alphabetical +# * `/\p{XDigit}/`: Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F) # -# "hello, world".match(/,/, 3) #=> # -# "hello, world".match(/\G,/, 3) #=> nil # -# * `\b` - Matches word boundaries when outside brackets; backspace (0x08) -# when inside brackets -# * `\B` - Matches non-word boundaries -# * `(?=`*pat*`)` - *Positive lookahead* assertion: ensures that the following -# characters match *pat*, but doesn't include those characters in the -# matched text -# * `(?!`*pat*`)` - *Negative lookahead* assertion: ensures that the following -# characters do not match *pat*, but doesn't include those characters in the -# matched text -# * `(?<=`*pat*`)` - *Positive lookbehind* assertion: ensures that the -# preceding characters match *pat*, but doesn't include those characters in -# the matched text -# * `(? 0 -# /(?<=ab)c/ =~ "abc" #=> 2 +# * `/\p{Emoji}/`: Unicode emoji. +# * `/\p{Graph}/`: Non-blank character (excludes spaces, control characters, +# and similar). +# * `/\p{Word}/`: A member of one of the following Unicode character +# categories (see below): # -# These match same string and *$&* equals `"c"`, while the matched position -# is different. +# * `Mark` (`M`). +# * `Letter` (`L`). +# * `Number` (`N`) +# * `Connector Punctuation` (`Pc`). # -# As are the following two regexps: # -# /(a)\K(b)\Kc/ -# /(?<=(?<=(a))(b))c/ +# * `/\p{ASCII}/`: A character in the ASCII character set. +# * `/\p{Any}/`: Any Unicode character (including unassigned characters). +# * `/\p{Assigned}/`: An assigned character. # # -# If a pattern isn't anchored it can begin at any point in the string: +# #### Unicode Character Categories # -# /real/.match("surrealist") #=> # +# A Unicode character category name: # -# Anchoring the pattern to the beginning of the string forces the match to start -# there. 'real' doesn't occur at the beginning of the string, so now the match -# fails: +# * May be either its full name or its abbreviated name. +# * Is case-insensitive. +# * Treats a space, a hyphen, and an underscore as equivalent. # -# /\Areal/.match("surrealist") #=> nil # -# The match below fails because although 'Demand' contains 'and', the pattern -# does not occur at a word boundary. +# Examples: # -# /\band/.match("Demand") +# /\p{lu}/ # => /\p{lu}/ +# /\p{LU}/ # => /\p{LU}/ +# /\p{Uppercase Letter}/ # => /\p{Uppercase Letter}/ +# /\p{Uppercase_Letter}/ # => /\p{Uppercase_Letter}/ +# /\p{UPPERCASE-LETTER}/ # => /\p{UPPERCASE-LETTER}/ # -# Whereas in the following example 'and' has been anchored to a non-word -# boundary so instead of matching the first 'and' it matches from the fourth -# letter of 'demand' instead: +# Below are the Unicode character category abbreviations and names. Enumerations +# of characters in each category are at the links. # -# /\Band.+/.match("Supply and demand curve") #=> # +# Letters: # -# The pattern below uses positive lookahead and positive lookbehind to match -# text appearing in tags without including the tags in the match: +# * `L`, `Letter`: `LC`, `Lm`, or `Lo`. +# * `LC`, `Cased_Letter`: `Ll`, `Lt`, or `Lu`. +# * [Lu, Lowercase_Letter](https://www.compart.com/en/unicode/category/Ll). +# * [Lu, Modifier_Letter](https://www.compart.com/en/unicode/category/Lm). +# * [Lu, Other_Letter](https://www.compart.com/en/unicode/category/Lo). +# * [Lu, Titlecase_Letter](https://www.compart.com/en/unicode/category/Lt). +# * [Lu, Uppercase_Letter](https://www.compart.com/en/unicode/category/Lu). # -# /(?<=)\w+(?=<\/b>)/.match("Fortune favours the bold") -# #=> # # -# ## Options +# Marks: # -# The end delimiter for a regexp can be followed by one or more single-letter -# options which control how the pattern can match. +# * `M`, `Mark`: `Mc`, `Me`, or `Mn`. +# * [Mc, Spacing_Mark](https://www.compart.com/en/unicode/category/Mc). +# * [Me, Enclosing_Mark](https://www.compart.com/en/unicode/category/Me). +# * [Mn, Nonapacing_Mark](https://www.compart.com/en/unicode/category/Mn). # -# * `/pat/i` - Ignore case -# * `/pat/m` - Treat a newline as a character matched by `.` -# * `/pat/x` - Ignore whitespace and comments in the pattern -# * `/pat/o` - Perform `#{}` interpolation only once # +# Numbers: # -# `i`, `m`, and `x` can also be applied on the subexpression level with the -# `(?`*on*`-`*off*`)` construct, which enables options *on*, and disables -# options *off* for the expression enclosed by the parentheses: +# * `N`, `Number`: `Nd`, `Nl`, or `No`. +# * [Nd, Decimal_Number](https://www.compart.com/en/unicode/category/Nd). +# * [Nl, Letter_Number](https://www.compart.com/en/unicode/category/Nl). +# * [No, Other_Number](https://www.compart.com/en/unicode/category/No). # -# /a(?i:b)c/.match('aBc') #=> # -# /a(?-i:b)c/i.match('ABC') #=> nil # -# Additionally, these options can also be toggled for the remainder of the -# pattern: +# Punctation: # -# /a(?i)bc/.match('abC') #=> # +# * `P`, `Punctuation`: `Pc`, `Pd`, `Pe`, `Pf`, `Pi`, `Po`, or `Ps`. +# * [Pc, +# Connector_Punctuation](https://www.compart.com/en/unicode/category/Pc). +# * [Pd, Dash_Punctuation](https://www.compart.com/en/unicode/category/Pd). +# * [Pe, Close_Punctuation](https://www.compart.com/en/unicode/category/Pe). +# * [Pf, Final_Punctuation](https://www.compart.com/en/unicode/category/Pf). +# * [Pi, Initial_Punctuation](https://www.compart.com/en/unicode/category/Pi). +# * [Po, Other_Punctuation](https://www.compart.com/en/unicode/category/Po). +# * [Ps, Open_Punctuation](https://www.compart.com/en/unicode/category/Ps). # -# Options may also be used with `Regexp.new`: +# * `S`, `Symbol`: `Sc`, `Sk`, `Sm`, or `So`. +# * [Sc, Currency_Symbol](https://www.compart.com/en/unicode/category/Sc). +# * [Sk, Modifier_Symbol](https://www.compart.com/en/unicode/category/Sk). +# * [Sm, Math_Symbol](https://www.compart.com/en/unicode/category/Sm). +# * [So, Other_Symbol](https://www.compart.com/en/unicode/category/So). # -# Regexp.new("abc", Regexp::IGNORECASE) #=> /abc/i -# Regexp.new("abc", Regexp::MULTILINE) #=> /abc/m -# Regexp.new("abc # Comment", Regexp::EXTENDED) #=> /abc # Comment/x -# Regexp.new("abc", Regexp::IGNORECASE | Regexp::MULTILINE) #=> /abc/mi +# * `Z`, `Separator`: `Zl`, `Zp`, or `Zs`. +# * [Zl, Line_Separator](https://www.compart.com/en/unicode/category/Zl). +# * [Zp, Paragraph_Separator](https://www.compart.com/en/unicode/category/Zp). +# * [Zs, Space_Separator](https://www.compart.com/en/unicode/category/Zs). # -# Regexp.new("abc", "i") #=> /abc/i -# Regexp.new("abc", "m") #=> /abc/m -# Regexp.new("abc # Comment", "x") #=> /abc # Comment/x -# Regexp.new("abc", "im") #=> /abc/mi +# * `C`, `Other`: `Cc`, `Cf`, `Cn`, `Co`, or `Cs`. +# * [Cc, Control](https://www.compart.com/en/unicode/category/Cc). +# * [Cf, Format](https://www.compart.com/en/unicode/category/Cf). +# * [Cn, Unassigned](https://www.compart.com/en/unicode/category/Cn). +# * [Co, Private_Use](https://www.compart.com/en/unicode/category/Co). +# * [Cs, Surrogate](https://www.compart.com/en/unicode/category/Cs). # -# ## Free-Spacing Mode and Comments # -# As mentioned above, the `x` option enables *free-spacing* mode. Literal white -# space inside the pattern is ignored, and the octothorpe (`#`) character -# introduces a comment until the end of the line. This allows the components of -# the pattern to be organized in a potentially more readable fashion. +# #### Unicode Scripts and Blocks # -# A contrived pattern to match a number with optional decimal places: +# Among the Unicode properties are: # -# float_pat = /\A -# [[:digit:]]+ # 1 or more digits before the decimal point -# (\. # Decimal point -# [[:digit:]]+ # 1 or more digits after the decimal point -# )? # The decimal point and following digits are optional -# \Z/x -# float_pat.match('3.14') #=> # +# * [Unicode scripts](https://en.wikipedia.org/wiki/Script_(Unicode)); see +# [supported scripts](https://www.unicode.org/standard/supported.html). +# * [Unicode blocks](https://en.wikipedia.org/wiki/Unicode_block); see +# [supported blocks](http://www.unicode.org/Public/UNIDATA/Blocks.txt). # -# There are a number of strategies for matching whitespace: # -# * Use a pattern such as `\s` or `\p{Space}`. -# * Use escaped whitespace such as `\ `, i.e. a space preceded by a backslash. -# * Use a character class such as `[ ]`. +# ### POSIX Bracket Expressions # +# A POSIX *bracket expression* is also similar to a character class. These +# expressions provide a portable alternative to the above, with the added +# benefit of encompassing non-ASCII characters: # -# Comments can be included in a non-`x` pattern with the `(?#`*comment*`)` -# construct, where *comment* is arbitrary text ignored by the regexp engine. +# * `/\d/` matches only ASCII decimal digits `0` through `9`. +# * `/[[:digit:]]/` matches any character in the Unicode `Decimal Number` +# (`Nd`) category; see below. # -# Comments in regexp literals cannot include unescaped terminator characters. # -# ## Encoding +# The POSIX bracket expressions: # -# Regular expressions are assumed to use the source encoding. This can be -# overridden with one of the following modifiers. +# * `/[[:digit:]]/`: Matches a [Unicode +# digit](https://www.compart.com/en/unicode/category/Nd): # -# * `/`*pat*`/u` - UTF-8 -# * `/`*pat*`/e` - EUC-JP -# * `/`*pat*`/s` - Windows-31J -# * `/`*pat*`/n` - ASCII-8BIT +# /[[:digit:]]/.match('9') # => # +# /[[:digit:]]/.match("\u1fbf9") # => # # +# * `/[[:xdigit:]]/`: Matches a digit allowed in a hexadecimal number; +# equivalent to `[0-9a-fA-F]`. # -# A regexp can be matched against a string when they either share an encoding, -# or the regexp's encoding is *US-ASCII* and the string's encoding is -# ASCII-compatible. +# * `/[[:upper:]]/`: Matches a [Unicode uppercase +# letter](https://www.compart.com/en/unicode/category/Lu): +# +# /[[:upper:]]/.match('A') # => # +# /[[:upper:]]/.match("\u00c6") # => # +# +# * `/[[:lower:]]/`: Matches a [Unicode lowercase +# letter](https://www.compart.com/en/unicode/category/Ll): +# +# /[[:lower:]]/.match('a') # => # +# /[[:lower:]]/.match("\u01fd") # => # +# +# * `/[[:alpha:]]/`: Matches `/[[:upper:]]/` or `/[[:lower:]]/`. +# +# * `/[[:alnum:]]/`: Matches `/[[:alpha:]]/` or `/[[:digit:]]/`. +# +# * `/[[:space:]]/`: Matches [Unicode space +# character](https://www.compart.com/en/unicode/category/Zs): +# +# /[[:space:]]/.match(' ') # => # +# /[[:space:]]/.match("\u2005") # => # +# +# * `/[[:blank:]]/`: Matches `/[[:space:]]/` or tab character: +# +# /[[:blank:]]/.match(' ') # => # +# /[[:blank:]]/.match("\u2005") # => # +# /[[:blank:]]/.match("\t") # => # +# +# * `/[[:cntrl:]]/`: Matches [Unicode control +# character](https://www.compart.com/en/unicode/category/Cc): +# +# /[[:cntrl:]]/.match("\u0000") # => # +# /[[:cntrl:]]/.match("\u009f") # => # +# +# * `/[[:graph:]]/`: Matches any character except `/[[:space:]]/` or +# `/[[:cntrl:]]/`. +# +# * `/[[:print:]]/`: Matches `/[[:graph:]]/` or space character. +# +# * `/[[:punct:]]/`: Matches any (Unicode punctuation +# character}[https://www.compart.com/en/unicode/category/Po]: +# +# +# Ruby also supports these (non-POSIX) bracket expressions: +# +# * `/[[:ascii:]]/`: Matches a character in the ASCII character set. +# * `/[[:word:]]/`: Matches a character in one of these Unicode character +# categories (see below): +# +# * `Mark` (`M`). +# * `Letter` (`L`). +# * `Number` (`N`) +# * `Connector Punctuation` (`Pc`). # -# If a match between incompatible encodings is attempted an -# `Encoding::CompatibilityError` exception is raised. # -# The `Regexp#fixed_encoding?` predicate indicates whether the regexp has a -# *fixed* encoding, that is one incompatible with ASCII. A regexp's encoding can -# be explicitly fixed by supplying `Regexp::FIXEDENCODING` as the second -# argument of `Regexp.new`: # -# r = Regexp.new("a".force_encoding("iso-8859-1"),Regexp::FIXEDENCODING) -# r =~ "a\u3042" -# # raises Encoding::CompatibilityError: incompatible encoding regexp match -# # (ISO-8859-1 regexp with UTF-8 string) +# ### Comments # -# ## Regexp Global Variables +# A comment may be included in a regexp pattern using the `(?#`*comment*`)` +# construct, where *comment* is a substring that is to be ignored. arbitrary +# text ignored by the regexp engine: # -# Pattern matching sets some global variables : +# /foo(?#Ignore me)bar/.match('foobar') # => # # -# * `$~` is equivalent to Regexp.last_match; -# * `$&` contains the complete matched text; -# * `$`` contains string before match; -# * `$'` contains string after match; -# * `$1`, `$2` and so on contain text matching first, second, etc capture -# group; -# * `$+` contains last capture group. +# The comment may not include an unescaped terminator character. # +# See also [Extended Mode](rdoc-ref:regexp.rdoc@Extended+Mode). +# +# ## Modes +# +# Each of these modifiers sets a mode for the regexp: +# +# * `i`: `/*pattern*/i` sets [Case-Insensitive +# Mode](rdoc-ref:regexp.rdoc@Case-Insensitive+Mode). +# * `m`: `/*pattern*/m` sets [Multiline +# Mode](rdoc-ref:regexp.rdoc@Multiline+Mode). +# * `x`: `/*pattern*/x` sets [Extended +# Mode](rdoc-ref:regexp.rdoc@Extended+Mode). +# * `o`: `/*pattern*/o` sets [Interpolation +# Mode](rdoc-ref:regexp.rdoc@Interpolation+Mode). +# +# +# Any, all, or none of these may be applied. +# +# Modifiers `i`, `m`, and `x` may be applied to subexpressions: +# +# * `(?*modifier*)` turns the mode "on" for ensuing subexpressions +# * `(?-*modifier*)` turns the mode "off" for ensuing subexpressions +# * `(?*modifier*:*subexp*)` turns the mode "on" for *subexp* within the group +# * `(?-*modifier*:*subexp*)` turns the mode "off" for *subexp* within the +# group +# +# +# Example: +# +# re = /(?i)te(?-i)st/ +# re.match('test') # => # +# re.match('TEst') # => # +# re.match('TEST') # => nil +# re.match('teST') # => nil +# +# re = /t(?i:e)st/ +# re.match('test') # => # +# re.match('tEst') # => # +# re.match('tEST') # => nil +# +# Method Regexp#options returns an integer whose value showing the settings for +# case-insensitivity mode, multiline mode, and extended mode. +# +# ### Case-Insensitive Mode +# +# By default, a regexp is case-sensitive: +# +# /foo/.match('FOO') # => nil +# +# Modifier `i` enables case-insensitive mode: +# +# /foo/i.match('FOO') +# # => # +# +# Method Regexp#casefold? returns whether the mode is case-insensitive. +# +# ### Multiline Mode +# +# The multiline-mode in Ruby is what is commonly called a "dot-all mode": +# +# * Without the `m` modifier, the subexpression `.` does not match newlines: +# +# /a.c/.match("a\nc") # => nil +# +# * With the modifier, it does match: +# +# /a.c/m.match("a\nc") # => # +# +# +# Unlike other languages, the modifier `m` does not affect the anchors `^` and +# `$`. These anchors always match at line-boundaries in Ruby. +# +# ### Extended Mode +# +# Modifier `x` enables extended mode, which means that: +# +# * Literal white space in the pattern is to be ignored. +# * Character `#` marks the remainder of its containing line as a comment, +# which is also to be ignored for matching purposes. +# +# +# In extended mode, whitespace and comments may be used to form a +# self-documented regexp. +# +# Regexp not in extended mode (matches some Roman numerals): +# +# pattern = '^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$' +# re = /#{pattern}/ +# re.match('MCMXLIII') # => # +# +# Regexp in extended mode: +# +# pattern = <<-EOT +# ^ # beginning of string +# M{0,3} # thousands - 0 to 3 Ms +# (CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 Cs), +# # or 500-800 (D, followed by 0 to 3 Cs) +# (XC|XL|L?X{0,3}) # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 Xs), +# # or 50-80 (L, followed by 0 to 3 Xs) +# (IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 Is), +# # or 5-8 (V, followed by 0 to 3 Is) +# $ # end of string +# EOT +# re = /#{pattern}/x +# re.match('MCMXLIII') # => # +# +# ### Interpolation Mode +# +# Modifier `o` means that the first time a literal regexp with interpolations is +# encountered, the generated Regexp object is saved and used for all future +# evaluations of that literal regexp. Without modifier `o`, the generated Regexp +# is not saved, so each evaluation of the literal regexp generates a new Regexp +# object. +# +# Without modifier `o`: +# +# def letters; sleep 5; /[A-Z][a-z]/; end +# words = %w[abc def xyz] +# start = Time.now +# words.each {|word| word.match(/\A[#{letters}]+\z/) } +# Time.now - start # => 15.0174892 +# +# With modifier `o`: +# +# start = Time.now +# words.each {|word| word.match(/\A[#{letters}]+\z/o) } +# Time.now - start # => 5.0010866 +# +# Note that if the literal regexp does not have interpolations, the `o` behavior +# is the default. +# +# ## Encodings +# +# By default, a regexp with only US-ASCII characters has US-ASCII encoding: +# +# re = /foo/ +# re.source.encoding # => # +# re.encoding # => # +# +# A regular expression containing non-US-ASCII characters is assumed to use the +# source encoding. This can be overridden with one of the following modifiers. +# +# * `/*pat*/n`: US-ASCII if only containing US-ASCII characters, otherwise +# ASCII-8BIT: +# +# /foo/n.encoding # => # +# /foo\xff/n.encoding # => # +# /foo\x7f/n.encoding # => # +# +# * `/*pat*/u`: UTF-8 +# +# /foo/u.encoding # => # +# +# * `/*pat*/e`: EUC-JP +# +# /foo/e.encoding # => # +# +# * `/*pat*/s`: Windows-31J +# +# /foo/s.encoding # => # +# +# +# A regexp can be matched against a target string when either: +# +# * They have the same encoding. +# * The regexp's encoding is a fixed encoding and the string contains only +# ASCII characters. Method Regexp#fixed_encoding? returns whether the regexp +# has a *fixed* encoding. +# +# +# If a match between incompatible encodings is attempted an +# `Encoding::CompatibilityError` exception is raised. # # Example: # -# m = /s(\w{2}).*(c)/.match('haystack') #=> # -# $~ #=> # -# Regexp.last_match #=> # +# re = eval("# encoding: ISO-8859-1\n/foo\\xff?/") +# re.encoding # => # +# re =~ "foo".encode("UTF-8") # => 0 +# re =~ "foo\u0100" # Raises Encoding::CompatibilityError # -# $& #=> "stac" -# # same as m[0] -# $` #=> "hay" -# # same as m.pre_match -# $' #=> "k" -# # same as m.post_match -# $1 #=> "ta" -# # same as m[1] -# $2 #=> "c" -# # same as m[2] -# $3 #=> nil -# # no third group in pattern -# $+ #=> "c" -# # same as m[-1] +# The encoding may be explicitly fixed by including Regexp::FIXEDENCODING in the +# second argument for Regexp.new: # -# These global variables are thread-local and method-local variables. +# # Regexp with encoding ISO-8859-1. +# re = Regexp.new("a".force_encoding('iso-8859-1'), Regexp::FIXEDENCODING) +# re.encoding # => # +# # Target string with encoding UTF-8. +# s = "a\u3042" +# s.encoding # => # +# re.match(s) # Raises Encoding::CompatibilityError. # -# ## Performance +# ## Timeouts # -# Certain pathological combinations of constructs can lead to abysmally bad -# performance. +# When either a regexp source or a target string comes from untrusted input, +# malicious values could become a denial-of-service attack; to prevent such an +# attack, it is wise to set a timeout. # -# Consider a string of 25 *a*s, a *d*, 4 *a*s, and a *c*. +# Regexp has two timeout values: # -# s = 'a' * 25 + 'd' + 'a' * 4 + 'c' -# #=> "aaaaaaaaaaaaaaaaaaaaaaaaadaaaac" +# * A class default timeout, used for a regexp whose instance timeout is +# `nil`; this default is initially `nil`, and may be set by method +# Regexp.timeout=: # -# The following patterns match instantly as you would expect: +# Regexp.timeout # => nil +# Regexp.timeout = 3.0 +# Regexp.timeout # => 3.0 # -# /(b|a)/ =~ s #=> 0 -# /(b|a+)/ =~ s #=> 0 -# /(b|a+)*/ =~ s #=> 0 +# * An instance timeout, which defaults to `nil` and may be set in Regexp.new: # -# However, the following pattern takes appreciably longer: +# re = Regexp.new('foo', timeout: 5.0) +# re.timeout # => 5.0 # -# /(b|a+)*c/ =~ s #=> 26 # -# This happens because an atom in the regexp is quantified by both an immediate -# `+` and an enclosing `*` with nothing to differentiate which is in control of -# any particular character. The nondeterminism that results produces -# super-linear performance. (Consult *Mastering Regular Expressions* (3rd ed.), -# pp 222, by *Jeffery Friedl*, for an in-depth analysis). This particular case -# can be fixed by use of atomic grouping, which prevents the unnecessary -# backtracking: +# When regexp.timeout is `nil`, the timeout "falls through" to Regexp.timeout; +# when regexp.timeout is non-`nil`, that value controls timing out: # -# (start = Time.now) && /(b|a+)*c/ =~ s && (Time.now - start) -# #=> 24.702736882 -# (start = Time.now) && /(?>b|a+)*c/ =~ s && (Time.now - start) -# #=> 0.000166571 +# | regexp.timeout Value | Regexp.timeout Value | Result | +# |----------------------|----------------------|-----------------------------| +# | nil | nil | Never times out. | +# | nil | Float | Times out in Float seconds. | +# | Float | Any | Times out in Float seconds. | # -# A similar case is typified by the following example, which takes approximately -# 60 seconds to execute for me: +# ## Optimization # -# Match a string of 29 *a*s against a pattern of 29 optional *a*s followed by 29 -# mandatory *a*s: +# For certain values of the pattern and target string, matching time can grow +# polynomially or exponentially in relation to the input size; the potential +# vulnerability arising from this is the [regular expression +# denial-of-service](https://en.wikipedia.org/wiki/ReDoS) (ReDoS) attack. # -# Regexp.new('a?' * 29 + 'a' * 29) =~ 'a' * 29 +# Regexp matching can apply an optimization to prevent ReDoS attacks. When the +# optimization is applied, matching time increases linearly (not polynomially or +# exponentially) in relation to the input size, and a ReDoS attach is not +# possible. # -# The 29 optional *a*s match the string, but this prevents the 29 mandatory *a*s -# that follow from matching. Ruby must then backtrack repeatedly so as to -# satisfy as many of the optional matches as it can while still matching the -# mandatory 29. It is plain to us that none of the optional matches can succeed, -# but this fact unfortunately eludes Ruby. +# This optimization is applied if the pattern meets these criteria: # -# The best way to improve performance is to significantly reduce the amount of -# backtracking needed. For this case, instead of individually matching 29 -# optional *a*s, a range of optional *a*s can be matched all at once with -# *a{0,29}*: +# * No backreferences. +# * No subexpression calls. +# * No nested lookaround anchors or atomic groups. +# * No nested quantifiers with counting (i.e. no nested `{n}`, `{min,}`, +# `{,max}`, or `{min,max}` style quantifiers) # -# Regexp.new('a{0,29}' + 'a' * 29) =~ 'a' * 29 # -# ## Timeout +# You can use method Regexp.linear_time? to determine whether a pattern meets +# these criteria: # -# There are two APIs to set timeout. One is Regexp.timeout=, which is -# process-global configuration of timeout for Regexp matching. +# Regexp.linear_time?(/a*/) # => true +# Regexp.linear_time?('a*') # => true +# Regexp.linear_time?(/(a*)\1/) # => false # -# Regexp.timeout = 3 -# s = 'a' * 25 + 'd' + 'a' * 4 + 'c' -# /(b|a+)*c/ =~ s #=> This raises an exception in three seconds +# However, an untrusted source may not be safe even if the method returns +# `true`, because the optimization uses memoization (which may invoke large +# memory consumption). # -# The other is timeout keyword of Regexp.new. +# ## References # -# re = Regexp.new("(b|a+)*c", timeout: 3) -# s = 'a' * 25 + 'd' + 'a' * 4 + 'c' -# /(b|a+)*c/ =~ s #=> This raises an exception in three seconds +# Read (online PDF books): # -# When using Regexps to process untrusted input, you should use the timeout -# feature to avoid excessive backtracking. Otherwise, a malicious user can -# provide input to Regexp causing Denial-of-Service attack. Note that the -# timeout is not set by default because an appropriate limit highly depends on -# an application requirement and context. +# * [Mastering Regular +# Expressions](https://ia902508.us.archive.org/10/items/allitebooks-02/Maste +# ring%20Regular%20Expressions%2C%203rd%20Edition.pdf) by Jeffrey E.F. +# Friedl. +# * [Regular Expressions +# Cookbook](https://doc.lagout.org/programmation/Regular%20Expressions/Regul +# ar%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Program +# ming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012- +# 09-06%5D.pdf) by Jan Goyvaerts & Steven Levithan. +# +# +# Explore, test (interactive online editor): +# +# * [Rubular](https://rubular.com/). # class Regexp # # With no argument, returns the value of `$!`, which is the result of the most - # recent pattern match (see [Regexp Global - # Variables](rdoc-ref:Regexp@Regexp+Global+Variables)): + # recent pattern match (see [Regexp global + # variables](rdoc-ref:Regexp@Global+Variables)): # # /c(.)t/ =~ 'cat' # => 0 # Regexp.last_match # => # @@ -926,8 +1476,6 @@ class Regexp # r = Regexp.new(Regexp.escape(s)) # => /\\\\\\\*\\\?\\\{\\\}\\\./ # r.match(s) # => # # - # Regexp.quote is an alias for Regexp.escape. - # def self.quote: (interned str) -> String # # Returns the integer index (in characters) of the first match for `self` and - # `string`, or `nil` if none; also sets the [rdoc-ref:Regexp Global - # Variables](rdoc-ref:Regexp@Regexp+Global+Variables): + # `string`, or `nil` if none; also sets the [rdoc-ref:Regexp global + # variables](rdoc-ref:Regexp@Global+Variables): # # /at/ =~ 'input data' # => 7 # $~ # => # @@ -1062,7 +1608,7 @@ class Regexp # * Is a regexp literal; see [Regexp # Literals](rdoc-ref:literals.rdoc@Regexp+Literals). # * Does not contain interpolations; see [Regexp - # Interpolation](rdoc-ref:Regexp@Regexp+Interpolation). + # interpolation](rdoc-ref:Regexp@Interpolation+Mode). # * Is at the left of the expression. # # @@ -1131,8 +1677,6 @@ class Regexp # /foo/ == Regexp.new('food') # => false # /foo/ == Regexp.new("abc".force_encoding("euc-jp")) # => false # - # Regexp#eql? is an alias for Regexp#==. - # def eql?: (untyped other) -> bool # # Parses the given *string* into an abstract syntax tree, returning the root # node of that tree. @@ -106,13 +106,13 @@ module RubyVM::AbstractSyntaxTree # # (ERROR@1:7-1:11), # # (LASGN@1:12-1:15 :y (LIT@1:14-1:15 2))] # - # Note that parsing continues even after the errored expresion. + # Note that parsing continues even after the errored expression. # def self.parse: (String string, ?keep_script_lines: bool, ?error_tolerant: bool, ?keep_tokens: bool) -> Node # # Reads the file from *pathname*, then parses it like ::parse, returning the # root node of the abstract syntax tree. @@ -128,8 +128,8 @@ module RubyVM::AbstractSyntaxTree # # Returns AST nodes of the given *proc* or *method*. # diff --git a/core/rubygems/rubygems.rbs b/core/rubygems/rubygems.rbs index b3951b82f..91c157146 100644 --- a/core/rubygems/rubygems.rbs +++ b/core/rubygems/rubygems.rbs @@ -156,7 +156,7 @@ module Gem # - activated_gem_paths() # --> # The number of paths in the +$LOAD_PATH+ from activated gems. Used to - # prioritize `-I` and +[ENV]('RUBYLIB')+ entries during `require`. + # prioritize `-I` and `ENV['RUBYLIB']` entries during `require`. # def self.activated_gem_paths: () -> Integer diff --git a/core/rubygems/version.rbs b/core/rubygems/version.rbs index 1e44454f2..a38625702 100644 --- a/core/rubygems/version.rbs +++ b/core/rubygems/version.rbs @@ -138,7 +138,9 @@ module Gem # # ## Preventing Version Catastrophe: # - # From: http://blog.zenspider.com/2008/10/rubygems-howto-preventing-cata.html + # From: + # https://www.zenspider.com/ruby/2008/10/rubygems-how-to-preventing-catastrophe. + # html # # Let's say you're depending on the fnord gem version 2.y.z. If you specify your # dependency as ">= 2.0.0" then, you're good, right? What happens if fnord 3.0 @@ -225,6 +227,8 @@ module Gem # rdoc-file=lib/rubygems/version.rb # - canonical_segments() # --> + # remove trailing zeros segments before first letter or at the end of the + # version # def canonical_segments: () -> Array[Integer | String] diff --git a/core/set.rbs b/core/set.rbs index 60104c8e4..036de0669 100644 --- a/core/set.rbs +++ b/core/set.rbs @@ -1,11 +1,8 @@ # -# This library provides the Set class, which deals with a collection +# This library provides the Set class, which implements a collection # of unordered values with no duplicates. It is a hybrid of Array's # intuitive inter-operation facilities and Hash's fast lookup. # The method `to_set` is added to Enumerable for convenience. -# Set implements a collection of unordered values with no duplicates. -# This is a hybrid of Array's intuitive inter-operation facilities and -# Hash's fast lookup. # Set is easy to use with Enumerable objects (implementing `each`). # Most of the initializer methods and binary operators accept generic # Enumerable objects besides sets and arrays. An Enumerable object @@ -60,7 +57,7 @@ # # ### Methods for Creating a Set # * ::[]: -# Returns a new set containing the given objects. +# Returns a new set containing the given objects. # * ::new: # Returns a new set containing either the given objects # (if no block given) or the return values from the called block @@ -89,13 +86,13 @@ # as determined by Object#eql?. # * #compare_by_identity?: # Returns whether the set considers only identity -# when comparing elements. +# when comparing elements. # # ### Methods for Querying # * #length (aliased as #size): -# Returns the count of elements. +# Returns the count of elements. # * #empty?: -# Returns whether the set has no elements. +# Returns whether the set has no elements. # * #include? (aliased as #member? and #===): # Returns whether a given object is an element in the set. # * #subset? (aliased as [<=](#method-i-3C-3D)): @@ -114,37 +111,38 @@ # have any common elements, `false` otherwise. # * #compare_by_identity?: # Returns whether the set considers only identity -# when comparing elements. +# when comparing elements. # # ### Methods for Assigning # * #add (aliased as #<<): -# Adds a given object to the set; returns `self`. +# Adds a given object to the set; returns `self`. # * #add?: # If the given object is not an element in the set, # adds it and returns `self`; otherwise, returns `nil`. # * #merge: -# Adds each given object to the set; returns `self`. +# Merges the elements of each given enumerable object to the set; returns +# `self`. # * #replace: # Replaces the contents of the set with the contents # of a given enumerable. # # ### Methods for Deleting # * #clear: -# Removes all elements in the set; returns `self`. +# Removes all elements in the set; returns `self`. # * #delete: -# Removes a given object from the set; returns `self`. +# Removes a given object from the set; returns `self`. # * #delete?: # If the given object is an element in the set, # removes it and returns `self`; otherwise, returns `nil`. # * #subtract: -# Removes each given object from the set; returns `self`. +# Removes each given object from the set; returns `self`. # * #delete_if - Removes elements specified by a given block. # * #select! (aliased as #filter!): # Removes elements not specified by a given block. # * #keep_if: -# Removes elements not specified by a given block. +# Removes elements not specified by a given block. # * #reject! -# Removes elements specified by a given block. +# Removes elements specified by a given block. # # ### Methods for Converting # * #classify: @@ -162,20 +160,20 @@ # #flatten!: # Replaces each nested set in `self` with the elements from that set. # * #inspect (aliased as #to_s): -# Returns a string displaying the elements. +# Returns a string displaying the elements. # * #join: # Returns a string containing all elements, converted to strings # as needed, and joined by the given record separator. # * #to_a: -# Returns an array containing all set elements. +# Returns an array containing all set elements. # * #to_set: # Returns `self` if given no arguments and no block; # with a block given, returns a new set consisting of block -# return values. +# return values. # # ### Methods for Iterating # * #each: -# Calls the block with each successive element; returns `self`. +# Calls the block with each successive element; returns `self`. # # ### Other Methods # * #reset: @@ -531,9 +529,9 @@ class Set[unchecked out A] # - # Merges the elements of the given enumerable object to the set and + # Merges the elements of the given enumerable objects to the set and # returns self. # def merge: (_Each[A]) -> self diff --git a/core/signal.rbs b/core/signal.rbs index 9dda17505..8a6cbaace 100644 --- a/core/signal.rbs +++ b/core/signal.rbs @@ -26,9 +26,9 @@ # # ... # Process.kill("TERM", pid) # -# produces: -# Debug now: true -# Debug now: false +# *produces:* +# Debug now: true +# Debug now: false # Terminating... # # The list of available signal names and their interpretation is system @@ -84,7 +84,7 @@ module Signal # Signal.trap("CLD") { puts "Child died" } # fork && Process.wait # - # produces: + # *produces:* # Terminating: 27461 # Child died # Terminating: 27460 diff --git a/core/string.rbs b/core/string.rbs index c956034bb..c51b7c475 100644 --- a/core/string.rbs +++ b/core/string.rbs @@ -92,7 +92,7 @@ # text. # * `\'` corresponds to `$'`, which contains string after match. # * `\`` corresponds to `$``, which contains string before match. -# * `+` corresponds to `$+`, which contains last capture group. +# * `\+` corresponds to `$+`, which contains last capture group. # # # See regexp.rdoc for details. @@ -279,7 +279,7 @@ # # If argument `capture` is given and not `0`, it should be either an capture # group index (integer) or a capture group name (string or symbol); the slice is -# the specified capture (see Regexp@Capturing): +# the specified capture (see Regexp@Groups+and+Captures): # # s = 'hello there' # s[/[aeiou](.)\1/, 1] # => "l" @@ -770,13 +770,21 @@ class String # # Returns a frozen, possibly pre-existing copy of the string. # # The returned String will be deduplicated as long as it does not have any # instance variables set on it and is not a String subclass. # - # String#dedup is an alias for String#-@. + # Note that `-string` variant is more convenient for defining constants: + # + # FILENAME = -'config/database.yml' + # + # while `dedup` is better suitable for using the method in chains of + # calculations: + # + # @url_list.concat(urls.map(&:dedup)) # def -@: () -> self @@ -874,7 +882,7 @@ class String # 'foo' =~ /o/ # => 1 # 'foo' =~ /x/ # => nil # - # Note: also updates Regexp@Special+global+variables. + # Note: also updates Regexp@Global+Variables. # # If the given `object` is not a Regexp, returns the value returned by `object # =~ self`. @@ -936,8 +944,6 @@ class String # s['lly'] = 'ncial' # => "ncial" # s # => "financial" # - # String#slice is an alias for String#[]. - # def []=: [T < _ToStr] (int index, T replacement) -> T | [T < _ToStr] (int start, int length, T replacement) -> T | [T < _ToStr] (range[int?] range, T replacement) -> T @@ -1159,16 +1165,25 @@ class String # # Replaces some or all of the content of `self` with `str`, and returns `self`. # The portion of the string affected is determined using the same criteria as # String#byteslice, except that `length` cannot be omitted. If the replacement # string is not the same length as the text it is replacing, the string will be - # adjusted accordingly. The form that take an Integer will raise an IndexError - # if the value is out of range; the Range form will raise a RangeError. If the - # beginning or ending offset does not land on character (codepoint) boundary, an - # IndexError will be raised. + # adjusted accordingly. + # + # If `str_index` and `str_length`, or `str_range` are given, the content of + # `self` is replaced by str.byteslice(str_index, str_length) or + # str.byteslice(str_range); however the substring of `str` is not allocated as a + # new string. + # + # The form that take an Integer will raise an IndexError if the value is out of + # range; the Range form will raise a RangeError. If the beginning or ending + # offset does not land on character (codepoint) boundary, an IndexError will be + # raised. # def bytesplice: (int start, int length, string str) -> String | (int start, int length, string str, int str_start, int str_length) -> String @@ -1530,7 +1545,14 @@ class String # The returned String will be deduplicated as long as it does not have any # instance variables set on it and is not a String subclass. # - # String#dedup is an alias for String#-@. + # Note that `-string` variant is more convenient for defining constants: + # + # FILENAME = -'config/database.yml' + # + # while `dedup` is better suitable for using the method in chains of + # calculations: + # + # @url_list.concat(urls.map(&:dedup)) # alias dedup -@ @@ -1840,7 +1862,7 @@ class String def empty?: () -> bool # @@ -1886,6 +1908,12 @@ class String # Optional keyword arguments `enc_opts` specify encoding options; see [Encoding # Options](rdoc-ref:encodings.rdoc@Encoding+Options). # + # Please note that, unless `invalid: :replace` option is given, conversion from + # an encoding `enc` to the same encoding `enc` (independent of whether `enc` is + # given explicitly or implicitly) is a no-op, i.e. the string is simply copied + # without any changes, and no exceptions are raised, even if there are invalid + # bytes. + # def encode: ( ?encoding source_encoding, ?encoding? from_encoding, @@ -2227,8 +2255,6 @@ class String # 'тест'.bytesize # => 8 # 'こんにちは'.bytesize # => 15 # - # String#size is an alias for String#length. - # def length: () -> Integer # # Returns a MatchData object (or `nil`) based on `self` and the given `pattern`. # - # Note: also updates Regexp@Special+global+variables. + # Note: also updates Regexp@Global+Variables. # # * Computes `regexp` by converting `pattern` (if not already a Regexp). # regexp = Regexp.new(pattern) @@ -2338,7 +2364,7 @@ class String # Returns `true` or `false` based on whether a match is found for `self` and # `pattern`. # - # Note: does not update Regexp@Special+global+variables. + # Note: does not update Regexp@Global+Variables. # # Computes `regexp` by converting `pattern` (if not already a Regexp). # regexp = Regexp.new(pattern) @@ -2408,15 +2434,11 @@ class String # # ''.succ # => "" # - # String#next is an alias for String#succ. - # alias next succ # # Equivalent to String#succ, but modifies `self` in place; returns `self`. # - # String#next! is an alias for String#succ!. - # alias next! succ! # @@ -3072,8 +3092,6 @@ class String # # ''.succ # => "" # - # String#next is an alias for String#succ. - # def succ: () -> String # # Equivalent to String#succ, but modifies `self` in place; returns `self`. # - # String#next! is an alias for String#succ!. - # def succ!: () -> self # # Returns `self` if `self` is a String, or `self` converted to a String if # `self` is a subclass of String. # - # String#to_str is an alias for String#to_s. - # alias to_str to_s # diff --git a/core/string_io.rbs b/core/string_io.rbs index 5470a7e27..dc50404b8 100644 --- a/core/string_io.rbs +++ b/core/string_io.rbs @@ -131,8 +131,6 @@ class StringIO # Calls the block with each remaining line read from the stream; does nothing if # already at end-of-file; returns `self`. See [Line IO](rdoc-ref:IO@Line+IO). # - # StringIO#each is an alias for StringIO#each_line. - # def each: (?String sep, ?Integer limit, ?chomp: boolish) { (String) -> untyped } -> self | (?String sep, ?Integer limit, ?chomp: boolish) -> ::Enumerator[String, self] @@ -177,12 +175,10 @@ class StringIO # - eof? -> true or false # --> # Returns `true` if positioned at end-of-stream, `false` otherwise; see - # [Position](rdoc-ref:File@Position). + # [Position](rdoc-ref:IO@Position). # # Raises IOError if the stream is not opened for reading. # - # StreamIO#eof is an alias for StreamIO#eof?. - # def eof: () -> bool # # Returns the current position (in bytes); see [Position](rdoc-ref:IO@Position). # - # StringIO#tell is an alias for StringIO#pos. - # def pos: () -> Integer # # Returns the current position (in bytes); see [Position](rdoc-ref:IO@Position). # - # StringIO#tell is an alias for StringIO#pos. - # def tell: () -> Integer # # Returns `true` if positioned at end-of-stream, `false` otherwise; see - # [Position](rdoc-ref:File@Position). + # [Position](rdoc-ref:IO@Position). # # Raises IOError if the stream is not opened for reading. # - # StreamIO#eof is an alias for StreamIO#eof?. - # def eof?: () -> bool # This is a deprecated alias for #each_line. diff --git a/core/struct.rbs b/core/struct.rbs index 69ce9b4a0..0a7c069a7 100644 --- a/core/struct.rbs +++ b/core/struct.rbs @@ -122,8 +122,8 @@ class Struct[Elem] # @@ -206,8 +206,6 @@ class Struct[Elem] # Foo.new(foo: 0, bar: 1, baz: 2) # # Raises ArgumentError: unknown keywords: baz # - # Method `::[]` is an alias for method `::new`. - # # * Method `:inspect` returns a string representation of the subclass: # # Foo.inspect @@ -352,8 +350,6 @@ class Struct[Elem] # joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) # joe.inspect # => "#" # - # Struct#to_s is an alias for Struct#inspect. - # def inspect: () -> String # @@ -363,8 +359,6 @@ class Struct[Elem] # joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) # joe.inspect # => "#" # - # Struct#to_s is an alias for Struct#inspect. - # alias to_s inspect # @@ -441,8 +429,6 @@ class Struct[Elem] # joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) # joe.size #=> 3 # - # Struct#length is an alias for Struct#size. - # alias length size # # Returns `true` if `object` is the same object as `self`, `false` otherwise. # - # Symbol#=== is an alias for Symbol#==. - # def ==: (untyped obj) -> bool # # Returns `true` if `object` is the same object as `self`, `false` otherwise. # - # Symbol#=== is an alias for Symbol#==. - # def ===: (untyped obj) -> bool # # Equivalent to `self.to_s.end_with?`; see String#end_with?. # @@ -322,8 +318,6 @@ class Symbol # # :foo.to_s # => "foo" # - # Symbol#id2name is an alias for Symbol#to_s. - # # Related: Symbol#inspect, Symbol#name. # def id2name: () -> String @@ -353,8 +347,6 @@ class Symbol # --> # Equivalent to `self.to_s.length`; see String#length. # - # Symbol#size is an alias for Symbol#length. - # def length: () -> Integer # # Equivalent to `self.to_s.length`; see String#length. # - # Symbol#size is an alias for Symbol#length. - # alias size length # @@ -415,8 +403,6 @@ class Symbol # # :foo.succ # => :fop # - # Symbol#next is an alias for Symbol#succ. - # # Related: String#succ. # alias succ next @@ -456,8 +442,6 @@ class Symbol # # :foo.to_s # => "foo" # - # Symbol#id2name is an alias for Symbol#to_s. - # # Related: Symbol#inspect, Symbol#name. # alias to_s id2name @@ -468,8 +452,6 @@ class Symbol # --> # Returns `self`. # - # Symbol#intern is an alias for Symbol#to_sym. - # # Related: String#to_sym. # alias to_sym intern diff --git a/core/thread.rbs b/core/thread.rbs index abaf6988e..afce296f9 100644 --- a/core/thread.rbs +++ b/core/thread.rbs @@ -1520,8 +1520,8 @@ end # exchanged safely between multiple threads. The Thread::Queue class implements # all the required locking semantics. # -# The class implements FIFO type of queue. In a FIFO queue, the first tasks -# added are the first retrieved. +# The class implements FIFO (first in, first out) type of queue. In a FIFO +# queue, the first tasks added are the first retrieved. # # Example: # @@ -1529,17 +1529,17 @@ end # # producer = Thread.new do # 5.times do |i| -# sleep rand(i) # simulate expense -# queue << i -# puts "#{i} produced" +# sleep rand(i) # simulate expense +# queue << i +# puts "#{i} produced" # end # end # # consumer = Thread.new do # 5.times do |i| -# value = queue.pop -# sleep rand(i/2) # simulate expense -# puts "consumed #{value}" +# value = queue.pop +# sleep rand(i/2) # simulate expense +# puts "consumed #{value}" # end # end # diff --git a/core/time.rbs b/core/time.rbs index 19cd085fc..1c7fa3c63 100644 --- a/core/time.rbs +++ b/core/time.rbs @@ -381,8 +381,6 @@ class Time < Object # Raises an exception if the number of arguments is eight, nine, or greater than # ten. # - # Time.gm is an alias for Time.utc. - # # Related: Time.local. # def self.gm: (Integer year, ?Integer | String month, ?Integer day, ?Integer hour, ?Integer min, ?Numeric sec, ?Numeric usec_with_frac) -> Time @@ -515,8 +513,6 @@ class Time < Object # Raises an exception if the number of arguments is eight, nine, or greater than # ten. # - # Time.gm is an alias for Time.utc. - # # Related: Time.local. # def self.utc: (Integer year, ?Integer | String month, ?Integer day, ?Integer hour, ?Integer min, ?Numeric sec, ?Numeric usec_with_frac) -> Time @@ -549,7 +545,7 @@ class Time < Object # t - 0.5 # => 1999-12-31 23:59:59.5 -0600 # # When `other_time` is given, returns a Float whose value is the difference of - # the numeric values of `self` and `other_time`: + # the numeric values of `self` and `other_time` in seconds: # # t - t # => 0.0 # @@ -606,8 +602,6 @@ class Time < Object # t.strftime('%a %b %e %T %Y') # => "Sun Dec 31 23:59:59 2000" # t.strftime('%c') # => "Sun Dec 31 23:59:59 2000" # - # Time#asctime is an alias for Time#ctime. - # # Related: Time#to_s, Time#inspect: # # t.inspect # => "2000-12-31 23:59:59.5 +000001" @@ -628,8 +622,6 @@ class Time < Object # t.strftime('%a %b %e %T %Y') # => "Sun Dec 31 23:59:59 2000" # t.strftime('%c') # => "Sun Dec 31 23:59:59 2000" # - # Time#asctime is an alias for Time#ctime. - # # Related: Time#to_s, Time#inspect: # # t.inspect # => "2000-12-31 23:59:59.5 +000001" @@ -644,8 +636,6 @@ class Time < Object # # => 2000-01-02 03:04:05 +000006 # t.mday # => 2 # - # Time#day is an alias for Time#mday. - # # Related: Time#year, Time#hour, Time#min. # def day: () -> Integer @@ -695,8 +685,6 @@ class Time < Object # t.zone # => "Central Daylight Time" # t.dst? # => true # - # Time#isdst is an alias for Time#dst?. - # def dst?: () -> bool # @@ -778,8 +762,6 @@ class Time < Object # # => 2000-01-01 20:15:01 UTC # utc.utc? # => true # - # Time#gmt? is an alias for Time#utc?. - # # Related: Time.utc. # def gmt?: () -> bool @@ -790,8 +772,6 @@ class Time < Object # Time.utc(2000, 1, 1).utc_offset # => 0 # Time.local(2000, 1, 1).utc_offset # => -21600 # -6*3600, or minus six hours. # - # Time#gmt_offset and Time#gmtoff are aliases for Time#utc_offset. - # def gmt_offset: () -> Integer # @@ -1296,8 +1262,6 @@ class Time < Object # Time.utc(1950, 1, 1, 0, 0, 0).to_i # => -631152000 # Time.utc(1990, 1, 1, 0, 0, 0).to_i # => 631152000 # - # Time#tv_sec is an alias for Time#to_i. - # # Related: Time#to_f Time#to_r. # def tv_sec: () -> Integer @@ -1314,8 +1278,6 @@ class Time < Object # # Related: Time#subsec (returns exact subseconds). # - # Time#tv_usec is an alias for Time#usec. - # def tv_usec: () -> Integer # @@ -1327,8 +1289,6 @@ class Time < Object # # Related: Time#subsec (returns exact subseconds). # - # Time#tv_usec is an alias for Time#usec. - # def usec: () -> Integer # @@ -1339,8 +1299,6 @@ class Time < Object # t.utc # => 2000-01-01 06:00:00 UTC # t.utc? # => true # - # Time#gmtime is an alias for Time#utc. - # # Related: Time#getutc (returns a new converted Time object). # def utc: () -> Time @@ -1358,8 +1316,6 @@ class Time < Object # # => 2000-01-01 20:15:01 UTC # utc.utc? # => true # - # Time#gmt? is an alias for Time#utc?. - # # Related: Time.utc. # def utc?: () -> bool @@ -1370,8 +1326,6 @@ class Time < Object # Time.utc(2000, 1, 1).utc_offset # => 0 # Time.local(2000, 1, 1).utc_offset # => -21600 # -6*3600, or minus six hours. # - # Time#gmt_offset and Time#gmtoff are aliases for Time#utc_offset. - # def utc_offset: () -> Integer # @@ -1472,8 +1424,6 @@ class Time < Object # # => 2000-01-02 03:04:05 +000006 # t.mon # => 1 # - # Time#month is an alias for Time#mday. - # # Related: Time#year, Time#hour, Time#min. # def month: () -> Integer diff --git a/core/trace_point.rbs b/core/trace_point.rbs index 2295e9215..38bc8d802 100644 --- a/core/trace_point.rbs +++ b/core/trace_point.rbs @@ -1,6 +1,4 @@ # -# Document-class: TracePoint -# # A class that provides the functionality of Kernel#set_trace_func in a nice # Object-Oriented API. # @@ -207,9 +205,8 @@ class TracePoint < Object # --> # Return the generated binding object from event. # - # Note that for `c_call` and `c_return` events, the binding returned is the - # binding of the nearest Ruby method calling the C method, since C methods - # themselves do not have bindings. + # Note that for `c_call` and `c_return` events, the method will return `nil`, + # since C methods themselves do not have bindings. # def binding: () -> Binding? diff --git a/core/true_class.rbs b/core/true_class.rbs index 0886caf5d..c28882cde 100644 --- a/core/true_class.rbs +++ b/core/true_class.rbs @@ -1,66 +1,99 @@ # -# The global value `true` is the only instance of class TrueClass and represents -# a logically true value in boolean expressions. The class provides operators -# allowing `true` to be used in logical expressions. +# The class of the singleton object `true`. +# +# Several of its methods act as operators: +# +# * #& +# * #| +# * #=== +# * #^ +# +# +# One other method: +# +# * #to_s and its alias #inspect. # class TrueClass def !: () -> false # - # And---Returns `false` if *obj* is `nil` or `false`, `true` otherwise. + # Returns `false` if `object` is `false` or `nil`, `true` otherwise: + # + # true & Object.new # => true true & false # => false true & nil # + # => false # def &: (false | nil) -> false | (untyped obj) -> bool # - # Case Equality -- For class Object, effectively the same as calling `#==`, but - # typically overridden by descendants to provide meaningful semantics in `case` - # statements. + # Returns `true` or `false`. + # + # Like Object#==, if `object` is an instance of Object (and not an instance of + # one of its many subclasses). + # + # This method is commonly overridden by those subclasses, to provide meaningful + # semantics in `case` statements. # def ===: (true) -> true | (untyped obj) -> bool # - # Exclusive Or---Returns `true` if *obj* is `nil` or `false`, `false` otherwise. + # Returns `true` if `object` is `false` or `nil`, `false` otherwise: + # + # true ^ Object.new # => false + # true ^ false # => true + # true ^ nil # => true # def ^: (false | nil) -> true | (untyped obj) -> bool # - # The string representation of `true` is "true". + # Returns string `'true'`: + # + # true.to_s # => "true" + # + # TrueClass#inspect is an alias for TrueClass#to_s. # alias inspect to_s # - # The string representation of `true` is "true". + # Returns string `'true'`: + # + # true.to_s # => "true" + # + # TrueClass#inspect is an alias for TrueClass#to_s. # def to_s: () -> "true" # - # Or---Returns `true`. As *obj* is an argument to a method call, it is always - # evaluated; there is no short-circuit evaluation in this case. + # Returns `true`: # - # true | puts("or") - # true || puts("logical or") + # true | Object.new # => true + # true | false # => true + # true | nil # => true # - # *produces:* + # Argument `object` is evaluated. This is different from `true` with the + # short-circuit operator, whose operand is evaluated only if necessary: # - # or + # true | raise # => Raises RuntimeError. + # true || raise # => true # def |: (untyped obj) -> true end diff --git a/core/warning.rbs b/core/warning.rbs index c86ffedee..1ac2f4274 100644 --- a/core/warning.rbs +++ b/core/warning.rbs @@ -42,17 +42,19 @@ module Warning # # `:deprecated` # : deprecation warnings + # * assignment of non-nil value to `$,` and `$;` + # * keyword arguments # - # * assignment of non-nil value to `$,` and `$;` - # * keyword arguments - # * proc/lambda without block - # - # etc. + # etc. # # `:experimental` # : experimental features + # * Pattern matching + # # - # * Pattern matching + # `:performance` + # : performance hints + # * Shape variation limit # def self.[]: (category) -> bool diff --git a/stdlib/base64/0/base64.rbs b/stdlib/base64/0/base64.rbs index bc79d37dc..5f434b377 100644 --- a/stdlib/base64/0/base64.rbs +++ b/stdlib/base64/0/base64.rbs @@ -1,42 +1,215 @@ # -# The Base64 module provides for the encoding (#encode64, #strict_encode64, -# #urlsafe_encode64) and decoding (#decode64, #strict_decode64, -# #urlsafe_decode64) of binary data using a Base64 representation. +# Module Base64 provides methods for: # -# ## Example +# * Encoding a binary string (containing non-ASCII characters) as a string of +# printable ASCII characters. +# * Decoding such an encoded string. # -# A simple encoding and decoding. # -# require "base64" +# Base64 is commonly used in contexts where binary data is not allowed or +# supported: # -# enc = Base64.encode64('Send reinforcements') -# # -> "U2VuZCByZWluZm9yY2VtZW50cw==\n" -# plain = Base64.decode64(enc) -# # -> "Send reinforcements" +# * Images in HTML or CSS files, or in URLs. +# * Email attachments. # -# The purpose of using base64 to encode data is that it translates any binary -# data into purely printable characters. +# +# A Base64-encoded string is about one-third larger that its source. See the +# [Wikipedia article](https://en.wikipedia.org/wiki/Base64) for more +# information. +# +# This module provides three pairs of encode/decode methods. Your choices among +# these methods should depend on: +# +# * Which character set is to be used for encoding and decoding. +# * Whether "padding" is to be used. +# * Whether encoded strings are to contain newlines. +# +# +# Note: Examples on this page assume that the including program has executed: +# +# require 'base64' +# +# ## Encoding Character Sets +# +# A Base64-encoded string consists only of characters from a 64-character set: +# +# * `('A'..'Z')`. +# * `('a'..'z')`. +# * `('0'..'9')`. +# * `=`, the 'padding' character. +# * Either: +# * `%w[+ /]`: +# [RFC-2045-compliant](https://datatracker.ietf.org/doc/html/rfc2045); +# *not* safe for URLs. +# * `%w[- _]`: +# [RFC-4648-compliant](https://datatracker.ietf.org/doc/html/rfc4648); +# safe for URLs. +# +# +# +# If you are working with Base64-encoded strings that will come from or be put +# into URLs, you should choose this encoder-decoder pair of RFC-4648-compliant +# methods: +# +# * Base64.urlsafe_encode64 and Base64.urlsafe_decode64. +# +# +# Otherwise, you may choose any of the pairs in this module, including the pair +# above, or the RFC-2045-compliant pairs: +# +# * Base64.encode64 and Base64.decode64. +# * Base64.strict_encode64 and Base64.strict_decode64. +# +# +# ## Padding +# +# Base64-encoding changes a triplet of input bytes into a quartet of output +# characters. +# +# **Padding in Encode Methods** +# +# Padding -- extending an encoded string with zero, one, or two trailing `=` +# characters -- is performed by methods Base64.encode64, Base64.strict_encode64, +# and, by default, Base64.urlsafe_encode64: +# +# Base64.encode64('s') # => "cw==\n" +# Base64.strict_encode64('s') # => "cw==" +# Base64.urlsafe_encode64('s') # => "cw==" +# Base64.urlsafe_encode64('s', padding: false) # => "cw" +# +# When padding is performed, the encoded string is always of length *4n*, where +# `n` is a non-negative integer: +# +# * Input bytes of length *3n* generate unpadded output characters of length +# *4n*: +# +# # n = 1: 3 bytes => 4 characters. +# Base64.strict_encode64('123') # => "MDEy" +# # n = 2: 6 bytes => 8 characters. +# Base64.strict_encode64('123456') # => "MDEyMzQ1" +# +# * Input bytes of length *3n+1* generate padded output characters of length +# *4(n+1)*, with two padding characters at the end: +# +# # n = 1: 4 bytes => 8 characters. +# Base64.strict_encode64('1234') # => "MDEyMw==" +# # n = 2: 7 bytes => 12 characters. +# Base64.strict_encode64('1234567') # => "MDEyMzQ1Ng==" +# +# * Input bytes of length *3n+2* generate padded output characters of length +# *4(n+1)*, with one padding character at the end: +# +# # n = 1: 5 bytes => 8 characters. +# Base64.strict_encode64('12345') # => "MDEyMzQ=" +# # n = 2: 8 bytes => 12 characters. +# Base64.strict_encode64('12345678') # => "MDEyMzQ1Njc=" +# +# +# When padding is suppressed, for a positive integer *n*: +# +# * Input bytes of length *3n* generate unpadded output characters of length +# *4n*: +# +# # n = 1: 3 bytes => 4 characters. +# Base64.urlsafe_encode64('123', padding: false) # => "MDEy" +# # n = 2: 6 bytes => 8 characters. +# Base64.urlsafe_encode64('123456', padding: false) # => "MDEyMzQ1" +# +# * Input bytes of length *3n+1* generate unpadded output characters of length +# *4n+2*, with two padding characters at the end: +# +# # n = 1: 4 bytes => 6 characters. +# Base64.urlsafe_encode64('1234', padding: false) # => "MDEyMw" +# # n = 2: 7 bytes => 10 characters. +# Base64.urlsafe_encode64('1234567', padding: false) # => "MDEyMzQ1Ng" +# +# * Input bytes of length *3n+2* generate unpadded output characters of length +# *4n+3*, with one padding character at the end: +# +# # n = 1: 5 bytes => 7 characters. +# Base64.urlsafe_encode64('12345', padding: false) # => "MDEyMzQ" +# # m = 2: 8 bytes => 11 characters. +# Base64.urlsafe_encode64('12345678', padding: false) # => "MDEyMzQ1Njc" +# +# +# **Padding in Decode Methods** +# +# All of the Base64 decode methods support (but do not require) padding. +# +# Method Base64.decode64 does not check the size of the padding: +# +# Base64.decode64("MDEyMzQ1Njc") # => "01234567" +# Base64.decode64("MDEyMzQ1Njc=") # => "01234567" +# Base64.decode64("MDEyMzQ1Njc==") # => "01234567" +# +# Method Base64.strict_decode64 strictly enforces padding size: +# +# Base64.strict_decode64("MDEyMzQ1Njc") # Raises ArgumentError +# Base64.strict_decode64("MDEyMzQ1Njc=") # => "01234567" +# Base64.strict_decode64("MDEyMzQ1Njc==") # Raises ArgumentError +# +# Method Base64.urlsafe_decode64 allows padding in `str`, which if present, must +# be correct: see [Padding](Base64.html#module-Base64-label-Padding), above: +# +# Base64.urlsafe_decode64("MDEyMzQ1Njc") # => "01234567" +# Base64.urlsafe_decode64("MDEyMzQ1Njc=") # => "01234567" +# Base64.urlsafe_decode64("MDEyMzQ1Njc==") # Raises ArgumentError. +# +# ## Newlines +# +# An encoded string returned by Base64.encode64 or Base64.urlsafe_encode64 has +# an embedded newline character after each 60-character sequence, and, if +# non-empty, at the end: +# +# # No newline if empty. +# encoded = Base64.encode64("\x00" * 0) +# encoded.index("\n") # => nil +# +# # Newline at end of short output. +# encoded = Base64.encode64("\x00" * 1) +# encoded.size # => 4 +# encoded.index("\n") # => 4 +# +# # Newline at end of longer output. +# encoded = Base64.encode64("\x00" * 45) +# encoded.size # => 60 +# encoded.index("\n") # => 60 +# +# # Newlines embedded and at end of still longer output. +# encoded = Base64.encode64("\x00" * 46) +# encoded.size # => 65 +# encoded.rindex("\n") # => 65 +# encoded.split("\n").map {|s| s.size } # => [60, 4] +# +# The string to be encoded may itself contain newlines, which are encoded as +# Base64: +# +# # Base64.encode64("\n\n\n") # => "CgoK\n" +# s = "This is line 1\nThis is line 2\n" +# Base64.encode64(s) # => "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK\n" # module Base64 # - # Returns the Base64-decoded version of `str`. This method complies with RFC - # 2045. Characters outside the base alphabet are ignored. + # Returns a string containing the decoding of an RFC-2045-compliant + # Base64-encoded string `str`: # - # require 'base64' - # str = 'VGhpcyBpcyBsaW5lIG9uZQpUaGlzIG' + - # 'lzIGxpbmUgdHdvClRoaXMgaXMgbGlu' + - # 'ZSB0aHJlZQpBbmQgc28gb24uLi4K' - # puts Base64.decode64(str) + # s = "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK\n" + # Base64.decode64(s) # => "This is line 1\nThis is line 2\n" # - # *Generates:* + # Non-Base64 characters in `str` are ignored; see [Encoding Character + # Set](Base64.html#module-Base64-label-Encoding+Character+Sets) above: these + # include newline characters and characters `-` and `/`: # - # This is line one - # This is line two - # This is line three - # And so on... + # Base64.decode64("\x00\n-_") # => "" + # + # Padding in `str` (even if incorrect) is ignored: + # + # Base64.decode64("MDEyMzQ1Njc") # => "01234567" + # Base64.decode64("MDEyMzQ1Njc=") # => "01234567" + # Base64.decode64("MDEyMzQ1Njc==") # => "01234567" # def self?.decode64: (String str) -> String @@ -44,16 +217,34 @@ module Base64 # rdoc-file=lib/base64.rb # - encode64(bin) # --> - # Returns the Base64-encoded version of `bin`. This method complies with RFC - # 2045. Line feeds are added to every 60 encoded characters. + # Returns a string containing the RFC-2045-compliant Base64-encoding of `bin`. + # + # Per RFC 2045, the returned string may contain the URL-unsafe characters `+` or + # `/`; see [Encoding Character + # Set](Base64.html#module-Base64-label-Encoding+Character+Sets) above: + # + # Base64.encode64("\xFB\xEF\xBE") # => "++++\n" + # Base64.encode64("\xFF\xFF\xFF") # => "////\n" + # + # The returned string may include padding; see + # [Padding](Base64.html#module-Base64-label-Padding) above. # - # require 'base64' - # Base64.encode64("Now is the time for all good coders\nto learn Ruby") + # Base64.encode64('*') # => "Kg==\n" # - # *Generates:* + # The returned string ends with a newline character, and if sufficiently long + # will have one or more embedded newline characters; see + # [Newlines](Base64.html#module-Base64-label-Newlines) above: # - # Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g - # UnVieQ== + # Base64.encode64('*') # => "Kg==\n" + # Base64.encode64('*' * 46) + # # => "KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq\nKg==\n" + # + # The string to be encoded may itself contain newlines, which will be encoded as + # ordinary Base64: + # + # Base64.encode64("\n\n\n") # => "CgoK\n" + # s = "This is line 1\nThis is line 2\n" + # Base64.encode64(s) # => "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK\n" # def self?.encode64: (String bin) -> String @@ -61,9 +252,25 @@ module Base64 # rdoc-file=lib/base64.rb # - strict_decode64(str) # --> - # Returns the Base64-decoded version of `str`. This method complies with RFC - # 4648. ArgumentError is raised if `str` is incorrectly padded or contains - # non-alphabet characters. Note that CR or LF are also rejected. + # Returns a string containing the decoding of an RFC-2045-compliant + # Base64-encoded string `str`: + # + # s = "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK" + # Base64.strict_decode64(s) # => "This is line 1\nThis is line 2\n" + # + # Non-Base64 characters in `str` not allowed; see [Encoding Character + # Set](Base64.html#module-Base64-label-Encoding+Character+Sets) above: these + # include newline characters and characters `-` and `/`: + # + # Base64.strict_decode64("\n") # Raises ArgumentError + # Base64.strict_decode64('-') # Raises ArgumentError + # Base64.strict_decode64('_') # Raises ArgumentError + # + # Padding in `str`, if present, must be correct: + # + # Base64.strict_decode64("MDEyMzQ1Njc") # Raises ArgumentError + # Base64.strict_decode64("MDEyMzQ1Njc=") # => "01234567" + # Base64.strict_decode64("MDEyMzQ1Njc==") # Raises ArgumentError # def self?.strict_decode64: (String str) -> String @@ -71,8 +278,33 @@ module Base64 # rdoc-file=lib/base64.rb # - strict_encode64(bin) # --> - # Returns the Base64-encoded version of `bin`. This method complies with RFC - # 4648. No line feeds are added. + # Returns a string containing the RFC-2045-compliant Base64-encoding of `bin`. + # + # Per RFC 2045, the returned string may contain the URL-unsafe characters `+` or + # `/`; see [Encoding Character + # Set](Base64.html#module-Base64-label-Encoding+Character+Sets) above: + # + # Base64.strict_encode64("\xFB\xEF\xBE") # => "++++\n" + # Base64.strict_encode64("\xFF\xFF\xFF") # => "////\n" + # + # The returned string may include padding; see + # [Padding](Base64.html#module-Base64-label-Padding) above. + # + # Base64.strict_encode64('*') # => "Kg==\n" + # + # The returned string will have no newline characters, regardless of its length; + # see [Newlines](Base64.html#module-Base64-label-Newlines) above: + # + # Base64.strict_encode64('*') # => "Kg==" + # Base64.strict_encode64('*' * 46) + # # => "KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg==" + # + # The string to be encoded may itself contain newlines, which will be encoded as + # ordinary Base64: + # + # Base64.strict_encode64("\n\n\n") # => "CgoK" + # s = "This is line 1\nThis is line 2\n" + # Base64.strict_encode64(s) # => "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK" # def self?.strict_encode64: (String bin) -> String @@ -80,12 +312,21 @@ module Base64 # rdoc-file=lib/base64.rb # - urlsafe_decode64(str) # --> - # Returns the Base64-decoded version of `str`. This method complies with ``Base - # 64 Encoding with URL and Filename Safe Alphabet'' in RFC 4648. The alphabet - # uses '-' instead of '+' and '_' instead of '/'. + # Returns the decoding of an RFC-4648-compliant Base64-encoded string `str`: + # + # `str` may not contain non-Base64 characters; see [Encoding Character + # Set](Base64.html#module-Base64-label-Encoding+Character+Sets) above: # - # The padding character is optional. This method accepts both correctly-padded - # and unpadded input. Note that it still rejects incorrectly-padded input. + # Base64.urlsafe_decode64('+') # Raises ArgumentError. + # Base64.urlsafe_decode64('/') # Raises ArgumentError. + # Base64.urlsafe_decode64("\n") # Raises ArgumentError. + # + # Padding in `str`, if present, must be correct: see + # [Padding](Base64.html#module-Base64-label-Padding), above: + # + # Base64.urlsafe_decode64("MDEyMzQ1Njc") # => "01234567" + # Base64.urlsafe_decode64("MDEyMzQ1Njc=") # => "01234567" + # Base64.urlsafe_decode64("MDEyMzQ1Njc==") # Raises ArgumentError. # def self?.urlsafe_decode64: (String str) -> String @@ -93,10 +334,31 @@ module Base64 # rdoc-file=lib/base64.rb # - urlsafe_encode64(bin, padding: true) # --> - # Returns the Base64-encoded version of `bin`. This method complies with ``Base - # 64 Encoding with URL and Filename Safe Alphabet'' in RFC 4648. The alphabet - # uses '-' instead of '+' and '_' instead of '/'. Note that the result can still - # contain '='. You can remove the padding by setting `padding` as false. + # Returns the RFC-4648-compliant Base64-encoding of `bin`. + # + # Per RFC 4648, the returned string will not contain the URL-unsafe characters + # `+` or `/`, but instead may contain the URL-safe characters `-` and `_`; see + # [Encoding Character + # Set](Base64.html#module-Base64-label-Encoding+Character+Sets) above: + # + # Base64.urlsafe_encode64("\xFB\xEF\xBE") # => "----" + # Base64.urlsafe_encode64("\xFF\xFF\xFF") # => "____" + # + # By default, the returned string may have padding; see + # [Padding](Base64.html#module-Base64-label-Padding), above: + # + # Base64.urlsafe_encode64('*') # => "Kg==" + # + # Optionally, you can suppress padding: + # + # Base64.urlsafe_encode64('*', padding: false) # => "Kg" + # + # The returned string will have no newline characters, regardless of its length; + # see [Newlines](Base64.html#module-Base64-label-Newlines) above: + # + # Base64.urlsafe_encode64('*') # => "Kg==" + # Base64.urlsafe_encode64('*' * 46) + # # => "KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg==" # def self?.urlsafe_encode64: (String bin, ?padding: boolish) -> String end diff --git a/stdlib/bigdecimal/0/big_decimal.rbs b/stdlib/bigdecimal/0/big_decimal.rbs index aad791ed3..b199a7d2f 100644 --- a/stdlib/bigdecimal/0/big_decimal.rbs +++ b/stdlib/bigdecimal/0/big_decimal.rbs @@ -1135,7 +1135,7 @@ class BigDecimal < Numeric # A space at the start of s returns positive values with a leading space. # # If s contains a number, a space is inserted after each group of that many - # fractional digits. + # digits, starting from '.' and counting outwards. # # If s ends with an 'E', engineering notation (0.xxxxEnn) is used. # @@ -1143,14 +1143,14 @@ class BigDecimal < Numeric # # Examples: # - # BigDecimal('-123.45678901234567890').to_s('5F') - # #=> '-123.45678 90123 45678 9' + # BigDecimal('-1234567890123.45678901234567890').to_s('5F') + # #=> '-123 45678 90123.45678 90123 45678 9' # - # BigDecimal('123.45678901234567890').to_s('+8F') - # #=> '+123.45678901 23456789' + # BigDecimal('1234567890123.45678901234567890').to_s('+8F') + # #=> '+12345 67890123.45678901 23456789' # - # BigDecimal('123.45678901234567890').to_s(' F') - # #=> ' 123.4567890123456789' + # BigDecimal('1234567890123.45678901234567890').to_s(' F') + # #=> ' 1234567890123.4567890123456789' # def to_s: (?String | int s) -> String @@ -1383,7 +1383,7 @@ module Kernel # * Other type: # # * Raises an exception if keyword argument `exception` is `true`. - # * Returns `nil` if keyword argument `exception` is `true`. + # * Returns `nil` if keyword argument `exception` is `false`. # # # @@ -1406,7 +1406,7 @@ class Integer # # 42.to_d # => 0.42e2 # - # See also BigDecimal::new. + # See also Kernel.BigDecimal. # def to_d: () -> BigDecimal @@ -1498,7 +1498,7 @@ class Float # 1.234.to_d # => 0.1234e1 # 1.234.to_d(2) # => 0.12e1 # - # See also BigDecimal::new. + # See also Kernel.BigDecimal. # def to_d: (?Integer precision) -> BigDecimal @@ -1579,7 +1579,7 @@ class String # "123.45e1".to_d # => 0.12345e4 # "45.67 degrees".to_d # => 0.4567e2 # - # See also BigDecimal::new. + # See also Kernel.BigDecimal. # def to_d: () -> BigDecimal end @@ -1600,7 +1600,7 @@ class Rational # # Rational(22, 7).to_d(3) # => 0.314e1 # - # See also BigDecimal::new. + # See also Kernel.BigDecimal. # def to_d: (Integer precision) -> BigDecimal @@ -1685,7 +1685,7 @@ class Complex # Complex(0.1234567, 0).to_d(4) # => 0.1235e0 # Complex(Rational(22, 7), 0).to_d(3) # => 0.314e1 # - # See also BigDecimal::new. + # See also Kernel.BigDecimal. # def to_d: (*untyped args) -> BigDecimal diff --git a/stdlib/coverage/0/coverage.rbs b/stdlib/coverage/0/coverage.rbs index 701dc1caf..1e2d0483f 100644 --- a/stdlib/coverage/0/coverage.rbs +++ b/stdlib/coverage/0/coverage.rbs @@ -245,8 +245,8 @@ module Coverage # --> # Returns true if coverage measurement is supported for the given mode. # - # The mode should be one of the following symbols: `:lines`, `:branches`, - # `:methods`, `:eval`. + # The mode should be one of the following symbols: `:lines`, `:oneshot_lines`, + # `:branches`, `:methods`, `:eval`. # # Example: # diff --git a/stdlib/csv/0/csv.rbs b/stdlib/csv/0/csv.rbs index a2e9cac46..48028eecb 100644 --- a/stdlib/csv/0/csv.rbs +++ b/stdlib/csv/0/csv.rbs @@ -1,15 +1,6 @@ # # ## CSV # -# ### In a Hurry? -# -# If you are familiar with CSV data and have a particular task in mind, you may -# want to go directly to the: -# * [Recipes for CSV](doc/csv/recipes/recipes_rdoc.html). -# -# -# Otherwise, read on here, about the API: classes, methods, and constants. -# # ### CSV Data # # CSV (comma-separated values) data is a text representation of a table: @@ -380,15 +371,6 @@ # feature will be used as the line-ending translation can cause problems with # resetting the document position to where it was before the read ahead. # -# --- -# -# Raises an exception if the given value is not String-convertible: -# row_sep = BasicObject.new -# # Raises NoMethodError (undefined method `to_s' for #) -# CSV.generate(ary, row_sep: row_sep) -# # Raises NoMethodError (undefined method `to_s' for #) -# CSV.parse(str, row_sep: row_sep) -# # ###### Option `col_sep` # # Specifies the String field separator to be used for both parsing and @@ -445,13 +427,6 @@ # # Raises ArgumentError (:col_sep must be 1 or more characters: "") # CSV.parse("foo0\nbar1\nbaz2\n", col_sep: col_sep) # -# Raises an exception if the given value is not String-convertible: -# col_sep = BasicObject.new -# # Raises NoMethodError (undefined method `to_s' for #) -# CSV.generate(line, col_sep: col_sep) -# # Raises NoMethodError (undefined method `to_s' for #) -# CSV.parse(str, col_sep: col_sep) -# # ###### Option `quote_char` # # Specifies the character (String of length 1) used used to quote fields in both @@ -832,13 +807,14 @@ # # ###### Option `liberal_parsing` # -# Specifies the boolean value that determines whether CSV will attempt to parse -# input not conformant with RFC 4180, such as double quotes in unquoted fields. +# Specifies the boolean or hash value that determines whether CSV will attempt +# to parse input not conformant with RFC 4180, such as double quotes in unquoted +# fields. # # Default value: # CSV::DEFAULT_OPTIONS.fetch(:liberal_parsing) # => false # -# For examples in this section: +# For the next two examples: # str = 'is,this "three, or four",fields' # # Without `liberal_parsing`: @@ -849,6 +825,24 @@ # ary = CSV.parse_line(str, liberal_parsing: true) # ary # => ["is", "this \"three", " or four\"", "fields"] # +# Use the `backslash_quote` sub-option to parse values that use a backslash to +# escape a double-quote character. This causes the parser to treat `\"` as if +# it were `""`. +# +# For the next two examples: +# str = 'Show,"Harry \"Handcuff\" Houdini, the one and only","Tampa Theater"' +# +# With `liberal_parsing`, but without the `backslash_quote` sub-option: +# # Incorrect interpretation of backslash; incorrectly interprets the quoted comma as a field separator. +# ary = CSV.parse_line(str, liberal_parsing: true) +# ary # => ["Show", "\"Harry \\\"Handcuff\\\" Houdini", " the one and only\"", "Tampa Theater"] +# puts ary[1] # => "Harry \"Handcuff\" Houdini +# +# With `liberal_parsing` and its `backslash_quote` sub-option: +# ary = CSV.parse_line(str, liberal_parsing: { backslash_quote: true }) +# ary # => ["Show", "Harry \"Handcuff\" Houdini, the one and only", "Tampa Theater"] +# puts ary[1] # => Harry "Handcuff" Houdini, the one and only +# # ###### Option `nil_value` # # Specifies the object that is to be substituted for each null (no-text) field. @@ -988,15 +982,6 @@ # feature will be used as the line-ending translation can cause problems with # resetting the document position to where it was before the read ahead. # -# --- -# -# Raises an exception if the given value is not String-convertible: -# row_sep = BasicObject.new -# # Raises NoMethodError (undefined method `to_s' for #) -# CSV.generate(ary, row_sep: row_sep) -# # Raises NoMethodError (undefined method `to_s' for #) -# CSV.parse(str, row_sep: row_sep) -# # ###### Option `col_sep` # # Specifies the String field separator to be used for both parsing and @@ -1053,13 +1038,6 @@ # # Raises ArgumentError (:col_sep must be 1 or more characters: "") # CSV.parse("foo0\nbar1\nbaz2\n", col_sep: col_sep) # -# Raises an exception if the given value is not String-convertible: -# col_sep = BasicObject.new -# # Raises NoMethodError (undefined method `to_s' for #) -# CSV.generate(line, col_sep: col_sep) -# # Raises NoMethodError (undefined method `to_s' for #) -# CSV.parse(str, col_sep: col_sep) -# # ###### Option `quote_char` # # Specifies the character (String of length 1) used used to quote fields in both @@ -1124,7 +1102,7 @@ # # With `write_headers`": # CSV.open(file_path,'w', -# :write_headers=> true, +# :write_headers => true, # :headers => ['Name','Value'] # ) do |csv| # csv << ['foo', '0'] @@ -1192,14 +1170,6 @@ # # See also [Write Converters](#class-CSV-label-Write+Converters) # -# --- -# -# Raises an exception if the converter returns a value that is neither `nil` nor -# String-convertible: -# bad_converter = proc {|field| BasicObject.new } -# # Raises NoMethodError (undefined method `is_a?' for #) -# CSV.generate_line(['a', 'b', 'c'], write_converters: bad_converter)# -# # ###### Option `write_nil_value` # # Specifies the object that is to be substituted for each `nil`-valued field. @@ -1737,8 +1707,8 @@ class CSV < Object # # Arguments: # * Argument `path_or_io` must be a file path or an IO stream. - # * Argument `mode`, if given, must be a File mode See [Open - # Mode](https://ruby-doc.org/core/IO.html#method-c-new-label-Open+Mode). + # * Argument `mode`, if given, must be a File mode. See [Access + # Modes](rdoc-ref:File@Access+Modes). # * Arguments `**options` must be keyword options. See [Options for # Parsing](#class-CSV-label-Options+for+Parsing). # * This method optionally accepts an additional `:encoding` option that you diff --git a/stdlib/date/0/date.rbs b/stdlib/date/0/date.rbs index ebca2270d..93b48eeb6 100644 --- a/stdlib/date/0/date.rbs +++ b/stdlib/date/0/date.rbs @@ -92,8 +92,6 @@ class Date # # See argument [start](rdoc-ref:calendars.rdoc@Argument+start). # - # Date.civil is an alias for Date.new. - # # Related: Date.jd. # def initialize: (?Integer year, ?Integer month, ?Integer mday, ?Integer start) -> void @@ -192,8 +190,6 @@ class Date # # See argument [limit](rdoc-ref:Date@Argument+limit). # - # Date._rfc822 is an alias for Date._rfc2822. - # # Related: Date.rfc2822 (returns a Date object). # def self._rfc2822: (String str) -> Hash[Symbol, Integer | String] @@ -230,8 +226,6 @@ class Date # # See argument [limit](rdoc-ref:Date@Argument+limit). # - # Date._rfc822 is an alias for Date._rfc2822. - # # Related: Date.rfc2822 (returns a Date object). # def self._rfc822: (String str) -> Hash[Symbol, Integer | String] @@ -335,8 +329,6 @@ class Date # Date.gregorian_leap?(2000) # => true # Date.gregorian_leap?(2001) # => false # - # Date.leap? is an alias for Date.gregorian_leap?. - # # Related: Date.julian_leap?. # def self.gregorian_leap?: (Integer year) -> bool @@ -465,8 +457,6 @@ class Date # Date.gregorian_leap?(2000) # => true # Date.gregorian_leap?(2001) # => false # - # Date.leap? is an alias for Date.gregorian_leap?. - # # Related: Date.julian_leap?. # def self.leap?: (Integer year) -> bool @@ -553,8 +543,6 @@ class Date # * Argument [limit](rdoc-ref:Date@Argument+limit). # # - # Date.rfc822 is an alias for Date.rfc2822. - # # Related: Date._rfc2822 (returns a hash). # def self.rfc2822: (String str, ?Integer start) -> Date @@ -598,8 +586,6 @@ class Date # * Argument [limit](rdoc-ref:Date@Argument+limit). # # - # Date.rfc822 is an alias for Date.rfc2822. - # # Related: Date._rfc2822 (returns a hash). # def self.rfc822: (String str, ?Integer start) -> Date @@ -656,8 +642,6 @@ class Date # # See argument [start](rdoc-ref:calendars.rdoc@Argument+start). # - # Date.valid_date? is an alias for Date.valid_civil?. - # # Related: Date.jd, Date.new. # def self.valid_civil?: (Integer year, Integer month, Integer mday, ?Integer start) -> bool @@ -693,8 +677,6 @@ class Date # # See argument [start](rdoc-ref:calendars.rdoc@Argument+start). # - # Date.valid_date? is an alias for Date.valid_civil?. - # # Related: Date.jd, Date.new. # def self.valid_date?: (Integer year, Integer month, Integer mday, ?Integer start) -> bool @@ -962,8 +944,6 @@ class Date # # See [asctime](https://linux.die.net/man/3/asctime). # - # Date#ctime is an alias for Date#asctime. - # def asctime: () -> String # @@ -975,8 +955,6 @@ class Date # # See [asctime](https://linux.die.net/man/3/asctime). # - # Date#ctime is an alias for Date#asctime. - # def ctime: () -> String # @@ -477,8 +475,6 @@ class DateTime < Date # # DateTime.new(2001, 2, 3, 4, 5, 6).min # => 5 # - # Date#minute is an alias for Date#min. - # def minute: () -> Integer # @@ -545,8 +537,6 @@ class DateTime < Date # # DateTime.new(2001, 2, 3, 4, 5, 6).sec # => 6 # - # Date#second is an alias for Date#sec. - # def second: () -> Integer # @@ -555,8 +545,6 @@ class DateTime < Date # # DateTime.new(2001, 2, 3, 4, 5, 6.5).sec_fraction # => (1/2) # - # Date#second_fraction is an alias for Date#sec_fraction. - # def second_fraction: () -> Rational # - # TODO: Remove on 3.3: + # TODO: Remove on the 3.4 development start: # SPELL_CHECKERS: untyped diff --git a/stdlib/erb/0/erb.rbs b/stdlib/erb/0/erb.rbs index f46b0e5bc..294f84609 100644 --- a/stdlib/erb/0/erb.rbs +++ b/stdlib/erb/0/erb.rbs @@ -286,11 +286,11 @@ class ERB # def build # b = binding # # create and run templates, filling member data variables - # ERB.new(<<-'END_PRODUCT'.gsub(/^\s+/, ""), trim_mode: "", eoutvar: "@product").result b + # ERB.new(<<~'END_PRODUCT', trim_mode: "", eoutvar: "@product").result b # <%= PRODUCT[:name] %> # <%= PRODUCT[:desc] %> # END_PRODUCT - # ERB.new(<<-'END_PRICE'.gsub(/^\s+/, ""), trim_mode: "", eoutvar: "@price").result b + # ERB.new(<<~'END_PRICE', trim_mode: "", eoutvar: "@price").result b # <%= PRODUCT[:name] %> -- <%= PRODUCT[:cost] %> # <%= PRODUCT[:desc] %> # END_PRICE diff --git a/stdlib/fileutils/0/fileutils.rbs b/stdlib/fileutils/0/fileutils.rbs index acc413e13..ba922efc6 100644 --- a/stdlib/fileutils/0/fileutils.rbs +++ b/stdlib/fileutils/0/fileutils.rbs @@ -238,8 +238,6 @@ module FileUtils # cd fileutils # # - # FileUtils.chdir is an alias for FileUtils.cd. - # # Related: FileUtils.pwd. # def self?.cd: (path dir, ?verbose: boolish) -> void @@ -652,8 +650,6 @@ module FileUtils # # Raises an exception if `src` is a directory. # - # FileUtils.copy is an alias for FileUtils.cp. - # # Related: [methods for copying](rdoc-ref:FileUtils@Copying). # def self?.cp: (pathlist src, path dest, ?preserve: boolish, ?noop: boolish, ?verbose: boolish) -> void @@ -1066,8 +1062,6 @@ module FileUtils # Raises an exception if `dest` is the path to an existing file and keyword # argument `force` is not `true`. # - # FileUtils#link is an alias for FileUtils#ln. - # # Related: FileUtils.link_entry (has different options). # def self?.ln: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish) -> void @@ -1157,8 +1151,6 @@ module FileUtils # ln -s srcdir3/src0.txt srcdir3/src1.txt destdir3 # # - # FileUtils.symlink is an alias for FileUtils.ln_s. - # # Related: FileUtils.ln_sf. # def self?.ln_s: (pathlist src, path dest, ?force: boolish, ?relative: boolish, ?target_directory: boolish, ?noop: boolish, ?verbose: boolish) -> void @@ -1368,9 +1360,6 @@ module FileUtils # mv src0 dest0 # mv src1.txt src1 dest1 # - # - # FileUtils.move is an alias for FileUtils.mv. - # def self?.mv: (pathlist src, path dest, ?force: boolish, ?noop: boolish, ?verbose: boolish, ?secure: boolish) -> void # - # Deserializes JSON string by constructing new Range object with arguments `a` - # serialized by `to_json`. + # Returns a new Range object constructed from `object['a']`, which must be an + # array of values suitable for a call to Range.new: + # + # require 'json/add/range' + # Range.json_create({"a"=>[1, 4]}) # => 1..4 + # Range.json_create({"a"=>[1, 4, true]}) # => 1...4 + # Range.json_create({"a" => ['a', 'd']}) # => "a".."d" # def self.json_create: [A] (Hash[String, String | [ A, A, bool ]] object) -> Range[A] @@ -1471,8 +1476,12 @@ class Range[out Elem] # rdoc-file=ext/json/lib/json/add/range.rb # - as_json(*) # --> - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Returns a 2-element hash representing `self`: + # + # require 'json/add/range' + # (1..4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, false]} + # (1...4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, true]} + # ('a'..'d').as_json # => {"json_class"=>"Range", "a"=>["a", "d", false]} # def as_json: (*untyped) -> Hash[String, String | [ Elem, Elem, bool ]] @@ -1480,9 +1489,12 @@ class Range[out Elem] # rdoc-file=ext/json/lib/json/add/range.rb # - to_json(*args) # --> - # Stores class name (Range) with JSON array of arguments `a` which include - # `first` (integer), `last` (integer), and `exclude_end?` (boolean) as JSON - # string. + # Returns a JSON string representing `self`: + # + # require 'json/add/range' + # (1..4).to_json # => "{\"json_class\":\"Range\",\"a\":[1,4,false]}" + # (1...4).to_json # => "{\"json_class\":\"Range\",\"a\":[1,4,true]}" + # ('a'..'d').to_json # => "{\"json_class\":\"Range\",\"a\":[\"a\",\"d\",false]}" # def to_json: (?JSON::State state) -> String end diff --git a/stdlib/logger/0/logger.rbs b/stdlib/logger/0/logger.rbs index 1039bc511..80c54e3fd 100644 --- a/stdlib/logger/0/logger.rbs +++ b/stdlib/logger/0/logger.rbs @@ -245,8 +245,7 @@ # logger.error! # => 3 # logger.fatal! # => 4 # -# You can retrieve the log level with method -# [level](Logger.html#attribute-i-level): +# You can retrieve the log level with method #level. # # logger.level = Logger::ERROR # logger.level # => 3 @@ -619,7 +618,10 @@ class Logger # def info?: () -> bool - # + # # Logging severity threshold (e.g. `Logger::INFO`). # def level: () -> Integer @@ -689,8 +691,10 @@ class Logger def reopen: () -> self | (logdev?) -> self - # - # Logging severity threshold (e.g. `Logger::INFO`). + # # alias sev_threshold level diff --git a/stdlib/monitor/0/monitor.rbs b/stdlib/monitor/0/monitor.rbs index 7b647a6c4..128e1f22d 100644 --- a/stdlib/monitor/0/monitor.rbs +++ b/stdlib/monitor/0/monitor.rbs @@ -109,6 +109,84 @@ class Monitor def wait_for_cond: (::MonitorMixin::ConditionVariable, Numeric? timeout) -> untyped end +# +# In concurrent programming, a monitor is an object or module intended to be +# used safely by more than one thread. The defining characteristic of a monitor +# is that its methods are executed with mutual exclusion. That is, at each point +# in time, at most one thread may be executing any of its methods. This mutual +# exclusion greatly simplifies reasoning about the implementation of monitors +# compared to reasoning about parallel code that updates a data structure. +# +# You can read more about the general principles on the Wikipedia page for +# [Monitors](https://en.wikipedia.org/wiki/Monitor_%28synchronization%29). +# +# ## Examples +# +# ### Simple object.extend +# +# require 'monitor.rb' +# +# buf = [] +# buf.extend(MonitorMixin) +# empty_cond = buf.new_cond +# +# # consumer +# Thread.start do +# loop do +# buf.synchronize do +# empty_cond.wait_while { buf.empty? } +# print buf.shift +# end +# end +# end +# +# # producer +# while line = ARGF.gets +# buf.synchronize do +# buf.push(line) +# empty_cond.signal +# end +# end +# +# The consumer thread waits for the producer thread to push a line to buf while +# `buf.empty?`. The producer thread (main thread) reads a line from ARGF and +# pushes it into buf then calls `empty_cond.signal` to notify the consumer +# thread of new data. +# +# ### Simple Class include +# +# require 'monitor' +# +# class SynchronizedArray < Array +# +# include MonitorMixin +# +# def initialize(*args) +# super(*args) +# end +# +# alias :old_shift :shift +# alias :old_unshift :unshift +# +# def shift(n=1) +# self.synchronize do +# self.old_shift(n) +# end +# end +# +# def unshift(item) +# self.synchronize do +# self.old_unshift(item) +# end +# end +# +# # other methods ... +# end +# +# `SynchronizedArray` implements an Array with synchronized access to items. +# This Class is implemented as subclass of Array which includes the MonitorMixin +# module. +# module MonitorMixin # # Class Net::HTTP provides a rich library that implements the client in a # client-server model that uses the HTTP request-response protocol. For - # information about HTTP, see + # information about HTTP, see: # # * [Hypertext Transfer # Protocol](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol). @@ -17,63 +17,6 @@ module Net # cal_overview). # # - # Note: If you are performing only a few GET requests, consider using - # [OpenURI](rdoc-ref:OpenURI); otherwise, read on. - # - # ## Synopsis - # - # If you are already familiar with HTTP, this synopsis may be helpful. - # - # [Session](rdoc-ref:Net::HTTP@Sessions) with multiple requests for [HTTP - # methods](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_met - # hods): - # - # Net::HTTP.start(hostname) do |http| - # # Session started automatically before block execution. - # http.get(path_or_uri, headers = {}) - # http.head(path_or_uri, headers = {}) - # http.post(path_or_uri, data, headers = {}) # Can also have a block. - # http.put(path_or_uri, data, headers = {}) - # http.delete(path_or_uri, headers = {Depth: 'Infinity'}) - # http.options(path_or_uri, headers = {}) - # http.trace(path_or_uri, headers = {}) - # http.patch(path_or_uri, data, headers = {}) # Can also have a block. - # # Session finished automatically at block exit. - # end - # - # [Session](rdoc-ref:Net::HTTP@Sessions) with multiple requests for [WebDAV - # methods](https://en.wikipedia.org/wiki/WebDAV#Implementation): - # - # Net::HTTP.start(hostname) do |http| - # # Session started automatically before block execution. - # http.copy(path_or_uri, headers = {}) - # http.lock(path_or_uri, body, headers = {}) - # http.mkcol(path_or_uri, body = nil, headers = {}) - # http.move(path_or_uri, headers = {}) - # http.propfind(path_or_uri, body = nil, headers = {'Depth' => '0'}) - # http.proppatch(path_or_uri, body, headers = {}) - # http.unlock(path_or_uri, body, headers = {}) - # # Session finished automatically at block exit. - # end - # - # Each of the following methods automatically starts and finishes a - # [session](rdoc-ref:Net::HTTP@Sessions) that sends a single request: - # - # # Return string response body. - # Net::HTTP.get(hostname, path, port = 80) - # Net::HTTP.get(uri, headers = {}, port = 80) - # - # # Write string response body to $stdout. - # Net::HTTP.get_print(hostname, path_or_uri, port = 80) - # Net::HTTP.get_print(uri, headers = {}, port = 80) - # - # # Return response as Net::HTTPResponse object. - # Net::HTTP.get_response(hostname, path_or_uri, port = 80) - # Net::HTTP.get_response(uri, headers = {}, port = 80) - # - # Net::HTTP.post(uri, data, headers = {}) - # Net::HTTP.post_form(uri, params) - # # ## About the Examples # # Examples here assume that `net/http` has been required (which also requires @@ -89,9 +32,10 @@ module Net # # Some examples also assume these variables: # - # uri = URI('https://jsonplaceholder.typicode.com') + # uri = URI('https://jsonplaceholder.typicode.com/') # uri.freeze # Examples may not modify. # hostname = uri.hostname # => "jsonplaceholder.typicode.com" + # path = uri.path # => "/" # port = uri.port # => 443 # # So that example requests may be written as: @@ -109,6 +53,64 @@ module Net # _uri = uri.dup # _uri.path = '/todos/1' # + # ## Strategies + # + # * If you will make only a few GET requests, consider using + # [OpenURI](rdoc-ref:OpenURI). + # * If you will make only a few requests of all kinds, consider using the + # various singleton convenience methods in this class. Each of the following + # methods automatically starts and finishes a + # [session](rdoc-ref:Net::HTTP@Sessions) that sends a single request: + # + # # Return string response body. + # Net::HTTP.get(hostname, path) + # Net::HTTP.get(uri) + # + # # Write string response body to $stdout. + # Net::HTTP.get_print(hostname, path) + # Net::HTTP.get_print(uri) + # + # # Return response as Net::HTTPResponse object. + # Net::HTTP.get_response(hostname, path) + # Net::HTTP.get_response(uri) + # data = '{"title": "foo", "body": "bar", "userId": 1}' + # Net::HTTP.post(uri, data) + # params = {title: 'foo', body: 'bar', userId: 1} + # Net::HTTP.post_form(uri, params) + # + # * If performance is important, consider using sessions, which lower request + # overhead. This [session](rdoc-ref:Net::HTTP@Sessions) has multiple + # requests for [HTTP + # methods](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request + # _methods) and [WebDAV + # methods](https://en.wikipedia.org/wiki/WebDAV#Implementation): + # + # Net::HTTP.start(hostname) do |http| + # # Session started automatically before block execution. + # http.get(path) + # http.head(path) + # body = 'Some text' + # http.post(path, body) # Can also have a block. + # http.put(path, body) + # http.delete(path) + # http.options(path) + # http.trace(path) + # http.patch(path, body) # Can also have a block. + # http.copy(path) + # http.lock(path, body) + # http.mkcol(path, body) + # http.move(path) + # http.propfind(path, body) + # http.proppatch(path, body) + # http.unlock(path, body) + # # Session finished automatically at block exit. + # end + # + # + # The methods cited above are convenience methods that, via their few arguments, + # allow minimal control over the requests. For greater control, consider using + # [request objects](rdoc-ref:Net::HTTPRequest). + # # ## URIs # # On the internet, a URI ([Universal Resource @@ -184,7 +186,7 @@ module Net # Fields](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_field # s). A host may also accept other custom fields. # - # ## Sessions + # ## HTTP Sessions # # A *session* is a connection between a server (host) and a client that: # @@ -193,7 +195,7 @@ module Net # * Is ended by instance method Net::HTTP#finish. # # - # See example sessions at the [Synopsis](rdoc-ref:Net::HTTP@Synopsis). + # See example sessions at [Strategies](rdoc-ref:Net::HTTP@Strategies). # # ### Session Using Net::HTTP.start # @@ -284,49 +286,43 @@ module Net # # ## Following Redirection # - # Each Net::HTTPResponse object belongs to a class for its response code. - # - # For example, all 2XX responses are instances of a Net::HTTPSuccess subclass, a - # 3XX response is an instance of a Net::HTTPRedirection subclass and a 200 - # response is an instance of the Net::HTTPOK class. For details of response - # classes, see the section "HTTP Response Classes" below. + # Each returned response is an instance of a subclass of Net::HTTPResponse. See + # the [response class + # hierarchy](rdoc-ref:Net::HTTPResponse@Response+Subclasses). # - # Using a case statement you can handle various types of responses properly: + # In particular, class Net::HTTPRedirection is the parent of all redirection + # classes. This allows you to craft a case statement to handle redirections + # properly: # - # def fetch(uri_str, limit = 10) + # def fetch(uri, limit = 10) # # You should choose a better exception. - # raise ArgumentError, 'too many HTTP redirects' if limit == 0 - # - # response = Net::HTTP.get_response(URI(uri_str)) - # - # case response - # when Net::HTTPSuccess then - # response - # when Net::HTTPRedirection then - # location = response['location'] - # warn "redirected to #{location}" + # raise ArgumentError, 'Too many HTTP redirects' if limit == 0 + # + # res = Net::HTTP.get_response(URI(uri)) + # case res + # when Net::HTTPSuccess # Any success class. + # res + # when Net::HTTPRedirection # Any redirection class. + # location = res['Location'] + # warn "Redirected to #{location}" # fetch(location, limit - 1) - # else - # response.value + # else # Any other class. + # res.value # end # end # - # print fetch('http://www.ruby-lang.org') + # fetch(uri) # # ## Basic Authentication # # Basic authentication is performed according to - # [RFC2617](http://www.ietf.org/rfc/rfc2617.txt). - # - # uri = URI('http://example.com/index.html?key=value') + # [RFC2617](http://www.ietf.org/rfc/rfc2617.txt): # # req = Net::HTTP::Get.new(uri) - # req.basic_auth 'user', 'pass' - # - # res = Net::HTTP.start(uri.hostname, uri.port) {|http| + # req.basic_auth('user', 'pass') + # res = Net::HTTP.start(hostname) do |http| # http.request(req) - # } - # puts res.body + # end # # ## Streaming Response Bodies # @@ -334,15 +330,12 @@ module Net # handling large files or wish to implement a progress bar you can instead # stream the body directly to an IO. # - # uri = URI('http://example.com/large_file') - # - # Net::HTTP.start(uri.host, uri.port) do |http| - # request = Net::HTTP::Get.new uri - # - # http.request request do |response| - # open 'large_file', 'w' do |io| - # response.read_body do |chunk| - # io.write chunk + # Net::HTTP.start(hostname) do |http| + # req = Net::HTTP::Get.new(uri) + # http.request(req) do |res| + # open('t.tmp', 'w') do |f| + # res.read_body do |chunk| + # f.write chunk # end # end # end @@ -350,50 +343,393 @@ module Net # # ## HTTPS # - # HTTPS is enabled for an HTTP connection by Net::HTTP#use_ssl=. - # - # uri = URI('https://secure.example.com/some_path?query=string') + # HTTPS is enabled for an HTTP connection by Net::HTTP#use_ssl=: # - # Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http| - # request = Net::HTTP::Get.new uri - # response = http.request request # Net::HTTPResponse object + # Net::HTTP.start(hostname, :use_ssl => true) do |http| + # req = Net::HTTP::Get.new(uri) + # res = http.request(req) # end # - # Or if you simply want to make a GET request, you may pass in an URI object - # that has an HTTPS URL. Net::HTTP automatically turns on TLS verification if - # the URI object has a 'https' URI scheme. + # Or if you simply want to make a GET request, you may pass in a URI object that + # has an HTTPS URL. Net::HTTP automatically turns on TLS verification if the URI + # object has a 'https' URI scheme: # - # uri = URI('https://example.com/') - # Net::HTTP.get(uri) # => String + # uri # => # + # Net::HTTP.get(uri) + # + # ## Proxy Server + # + # An HTTP object can have a [proxy + # server](https://en.wikipedia.org/wiki/Proxy_server). + # + # You can create an HTTP object with a proxy server using method Net::HTTP.new + # or method Net::HTTP.start. + # + # The proxy may be defined either by argument `p_addr` or by environment + # variable `'http_proxy'`. + # + # ### Proxy Using Argument `p_addr` as a String + # + # When argument `p_addr` is a string hostname, the returned `http` has the given + # host as its proxy: + # + # http = Net::HTTP.new(hostname, nil, 'proxy.example') + # http.proxy? # => true + # http.proxy_from_env? # => false + # http.proxy_address # => "proxy.example" + # # These use default values. + # http.proxy_port # => 80 + # http.proxy_user # => nil + # http.proxy_pass # => nil + # + # The port, username, and password for the proxy may also be given: + # + # http = Net::HTTP.new(hostname, nil, 'proxy.example', 8000, 'pname', 'ppass') + # # => # + # http.proxy? # => true + # http.proxy_from_env? # => false + # http.proxy_address # => "proxy.example" + # http.proxy_port # => 8000 + # http.proxy_user # => "pname" + # http.proxy_pass # => "ppass" + # + # ### Proxy Using '`ENV['http_proxy']`' + # + # When environment variable `'http_proxy'` is set to a URI string, the returned + # `http` will have the server at that URI as its proxy; note that the URI string + # must have a protocol such as `'http'` or `'https'`: + # + # ENV['http_proxy'] = 'http://example.com' + # http = Net::HTTP.new(hostname) + # http.proxy? # => true + # http.proxy_from_env? # => true + # http.proxy_address # => "example.com" + # # These use default values. + # http.proxy_port # => 80 + # http.proxy_user # => nil + # http.proxy_pass # => nil + # + # The URI string may include proxy username, password, and port number: + # + # ENV['http_proxy'] = 'http://pname:ppass@example.com:8000' + # http = Net::HTTP.new(hostname) + # http.proxy? # => true + # http.proxy_from_env? # => true + # http.proxy_address # => "example.com" + # http.proxy_port # => 8000 + # http.proxy_user # => "pname" + # http.proxy_pass # => "ppass" + # + # ### Filtering Proxies + # + # With method Net::HTTP.new (but not Net::HTTP.start), you can use argument + # `p_no_proxy` to filter proxies: + # + # * Reject a certain address: # - # In previous versions of Ruby you would need to require 'net/https' to use - # HTTPS. This is no longer true. + # http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example') + # http.proxy_address # => nil # - # ## Proxies + # * Reject certain domains or subdomains: # - # Net::HTTP will automatically create a proxy from the `http_proxy` environment - # variable if it is present. To disable use of `http_proxy`, pass `nil` for the - # proxy address. + # http = Net::HTTP.new('example.com', nil, 'my.proxy.example', 8000, 'pname', 'ppass', 'proxy.example') + # http.proxy_address # => nil # - # You may also create a custom proxy: + # * Reject certain addresses and port combinations: # - # proxy_addr = 'your.proxy.host' - # proxy_port = 8080 + # http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example:1234') + # http.proxy_address # => "proxy.example" # - # Net::HTTP.new('example.com', nil, proxy_addr, proxy_port).start { |http| - # # always proxy via your.proxy.addr:8080 - # } + # http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example:8000') + # http.proxy_address # => nil # - # See Net::HTTP.new for further details and examples such as proxies that - # require a username and password. + # * Reject a list of the types above delimited using a comma: # - # ## Compression + # http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'my.proxy,proxy.example:8000') + # http.proxy_address # => nil # - # Net::HTTP automatically adds Accept-Encoding for compression of response - # bodies and automatically decompresses gzip and deflate responses unless a - # Range header was sent. + # http = Net::HTTP.new('example.com', nil, 'my.proxy', 8000, 'pname', 'ppass', 'my.proxy,proxy.example:8000') + # http.proxy_address # => nil # - # Compression can be disabled through the Accept-Encoding: identity header. + # + # ## Compression and Decompression + # + # Net::HTTP does not compress the body of a request before sending. + # + # By default, Net::HTTP adds header `'Accept-Encoding'` to a new [request + # object](rdoc-ref:Net::HTTPRequest): + # + # Net::HTTP::Get.new(uri)['Accept-Encoding'] + # # => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" + # + # This requests the server to zip-encode the response body if there is one; the + # server is not required to do so. + # + # Net::HTTP does not automatically decompress a response body if the response + # has header `'Content-Range'`. + # + # Otherwise decompression (or not) depends on the value of header + # [Content-Encoding](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#co + # ntent-encoding-response-header): + # + # * `'deflate'`, `'gzip'`, or `'x-gzip'`: decompresses the body and deletes + # the header. + # * `'none'` or `'identity'`: does not decompress the body, but deletes the + # header. + # * Any other value: leaves the body and header unchanged. + # + # + # ## What's Here + # + # This is a categorized summary of methods and attributes. + # + # ### Net::HTTP Objects + # + # * [::new](rdoc-ref:Net::HTTP.new): Creates a new instance. + # * [#inspect](rdoc-ref:Net::HTTP#inspect): Returns a string representation of + # `self`. + # + # + # ### Sessions + # + # * [::start](rdoc-ref:Net::HTTP.start): Begins a new session in a new + # Net::HTTP object. + # * [#started?](rdoc-ref:Net::HTTP#started?) (aliased as + # [#active?](rdoc-ref:Net::HTTP#active?)): Returns whether in a session. + # * [#finish](rdoc-ref:Net::HTTP#finish): Ends an active session. + # * [#start](rdoc-ref:Net::HTTP#start): Begins a new session in an existing + # Net::HTTP object (`self`). + # + # + # ### Connections + # + # * [:continue_timeout](rdoc-ref:Net::HTTP#continue_timeout): Returns the + # continue timeout. + # * [#continue_timeout=](rdoc-ref:Net::HTTP#continue_timeout=): Sets the + # continue timeout seconds. + # * [:keep_alive_timeout](rdoc-ref:Net::HTTP#keep_alive_timeout): Returns the + # keep-alive timeout. + # * [:keep_alive_timeout=](rdoc-ref:Net::HTTP#keep_alive_timeout=): Sets the + # keep-alive timeout. + # * [:max_retries](rdoc-ref:Net::HTTP#max_retries): Returns the maximum + # retries. + # * [#max_retries=](rdoc-ref:Net::HTTP#max_retries=): Sets the maximum + # retries. + # * [:open_timeout](rdoc-ref:Net::HTTP#open_timeout): Returns the open + # timeout. + # * [:open_timeout=](rdoc-ref:Net::HTTP#open_timeout=): Sets the open timeout. + # * [:read_timeout](rdoc-ref:Net::HTTP#read_timeout): Returns the open + # timeout. + # * [:read_timeout=](rdoc-ref:Net::HTTP#read_timeout=): Sets the read timeout. + # * [:ssl_timeout](rdoc-ref:Net::HTTP#ssl_timeout): Returns the ssl timeout. + # * [:ssl_timeout=](rdoc-ref:Net::HTTP#ssl_timeout=): Sets the ssl timeout. + # * [:write_timeout](rdoc-ref:Net::HTTP#write_timeout): Returns the write + # timeout. + # * [write_timeout=](rdoc-ref:Net::HTTP#write_timeout=): Sets the write + # timeout. + # + # + # ### Requests + # + # * [::get](rdoc-ref:Net::HTTP.get): Sends a GET request and returns the + # string response body. + # * [::get_print](rdoc-ref:Net::HTTP.get_print): Sends a GET request and write + # the string response body to $stdout. + # * [::get_response](rdoc-ref:Net::HTTP.get_response): Sends a GET request and + # returns a response object. + # * [::post_form](rdoc-ref:Net::HTTP.post_form): Sends a POST request with + # form data and returns a response object. + # * [::post](rdoc-ref:Net::HTTP.post): Sends a POST request with data and + # returns a response object. + # * [#copy](rdoc-ref:Net::HTTP#copy): Sends a COPY request and returns a + # response object. + # * [#delete](rdoc-ref:Net::HTTP#delete): Sends a DELETE request and returns a + # response object. + # * [#get](rdoc-ref:Net::HTTP#get): Sends a GET request and returns a response + # object. + # * [#head](rdoc-ref:Net::HTTP#head): Sends a HEAD request and returns a + # response object. + # * [#lock](rdoc-ref:Net::HTTP#lock): Sends a LOCK request and returns a + # response object. + # * [#mkcol](rdoc-ref:Net::HTTP#mkcol): Sends a MKCOL request and returns a + # response object. + # * [#move](rdoc-ref:Net::HTTP#move): Sends a MOVE request and returns a + # response object. + # * [#options](rdoc-ref:Net::HTTP#options): Sends a OPTIONS request and + # returns a response object. + # * [#patch](rdoc-ref:Net::HTTP#patch): Sends a PATCH request and returns a + # response object. + # * [#post](rdoc-ref:Net::HTTP#post): Sends a POST request and returns a + # response object. + # * [#propfind](rdoc-ref:Net::HTTP#propfind): Sends a PROPFIND request and + # returns a response object. + # * [#proppatch](rdoc-ref:Net::HTTP#proppatch): Sends a PROPPATCH request and + # returns a response object. + # * [#put](rdoc-ref:Net::HTTP#put): Sends a PUT request and returns a response + # object. + # * [#request](rdoc-ref:Net::HTTP#request): Sends a request and returns a + # response object. + # * [#request_get](rdoc-ref:Net::HTTP#request_get) (aliased as + # [#get2](rdoc-ref:Net::HTTP#get2)): Sends a GET request and forms a + # response object; if a block given, calls the block with the object, + # otherwise returns the object. + # * [#request_head](rdoc-ref:Net::HTTP#request_head) (aliased as + # [#head2](rdoc-ref:Net::HTTP#head2)): Sends a HEAD request and forms a + # response object; if a block given, calls the block with the object, + # otherwise returns the object. + # * [#request_post](rdoc-ref:Net::HTTP#request_post) (aliased as + # [#post2](rdoc-ref:Net::HTTP#post2)): Sends a POST request and forms a + # response object; if a block given, calls the block with the object, + # otherwise returns the object. + # * [#send_request](rdoc-ref:Net::HTTP#send_request): Sends a request and + # returns a response object. + # * [#trace](rdoc-ref:Net::HTTP#trace): Sends a TRACE request and returns a + # response object. + # * [#unlock](rdoc-ref:Net::HTTP#unlock): Sends an UNLOCK request and returns + # a response object. + # + # + # ### Responses + # + # * [:close_on_empty_response](rdoc-ref:Net::HTTP#close_on_empty_response): + # Returns whether to close connection on empty response. + # * [:close_on_empty_response=](rdoc-ref:Net::HTTP#close_on_empty_response=): + # Sets whether to close connection on empty response. + # * [:ignore_eof](rdoc-ref:Net::HTTP#ignore_eof): Returns whether to ignore + # end-of-file when reading a response body with `Content-Length` headers. + # * [:ignore_eof=](rdoc-ref:Net::HTTP#ignore_eof=): Sets whether to ignore + # end-of-file when reading a response body with `Content-Length` headers. + # * [:response_body_encoding](rdoc-ref:Net::HTTP#response_body_encoding): + # Returns the encoding to use for the response body. + # * [#response_body_encoding=](rdoc-ref:Net::HTTP#response_body_encoding=): + # Sets the response body encoding. + # + # + # ### Proxies + # + # * [:proxy_address](rdoc-ref:Net::HTTP#proxy_address): Returns the proxy + # address. + # * [:proxy_address=](rdoc-ref:Net::HTTP#proxy_address=): Sets the proxy + # address. + # * [::proxy_class?](rdoc-ref:Net::HTTP.proxy_class?): Returns whether `self` + # is a proxy class. + # * [#proxy?](rdoc-ref:Net::HTTP#proxy?): Returns whether `self` has a proxy. + # * [#proxy_address](rdoc-ref:Net::HTTP#proxy_address) (aliased as + # [#proxyaddr](rdoc-ref:Net::HTTP#proxyaddr)): Returns the proxy address. + # * [#proxy_from_env?](rdoc-ref:Net::HTTP#proxy_from_env?): Returns whether + # the proxy is taken from an environment variable. + # * [:proxy_from_env=](rdoc-ref:Net::HTTP#proxy_from_env=): Sets whether the + # proxy is to be taken from an environment variable. + # * [:proxy_pass](rdoc-ref:Net::HTTP#proxy_pass): Returns the proxy password. + # * [:proxy_pass=](rdoc-ref:Net::HTTP#proxy_pass=): Sets the proxy password. + # * [:proxy_port](rdoc-ref:Net::HTTP#proxy_port): Returns the proxy port. + # * [:proxy_port=](rdoc-ref:Net::HTTP#proxy_port=): Sets the proxy port. + # * [#proxy_user](rdoc-ref:Net::HTTP#proxy_user): Returns the proxy user name. + # * [:proxy_user=](rdoc-ref:Net::HTTP#proxy_user=): Sets the proxy user. + # + # + # ### Security + # + # * [:ca_file](rdoc-ref:Net::HTTP#ca_file): Returns the path to a CA + # certification file. + # * [:ca_file=](rdoc-ref:Net::HTTP#ca_file=): Sets the path to a CA + # certification file. + # * [:ca_path](rdoc-ref:Net::HTTP#ca_path): Returns the path of to CA + # directory containing certification files. + # * [:ca_path=](rdoc-ref:Net::HTTP#ca_path=): Sets the path of to CA directory + # containing certification files. + # * [:cert](rdoc-ref:Net::HTTP#cert): Returns the OpenSSL::X509::Certificate + # object to be used for client certification. + # * [:cert=](rdoc-ref:Net::HTTP#cert=): Sets the OpenSSL::X509::Certificate + # object to be used for client certification. + # * [:cert_store](rdoc-ref:Net::HTTP#cert_store): Returns the X509::Store to + # be used for verifying peer certificate. + # * [:cert_store=](rdoc-ref:Net::HTTP#cert_store=): Sets the X509::Store to be + # used for verifying peer certificate. + # * [:ciphers](rdoc-ref:Net::HTTP#ciphers): Returns the available SSL ciphers. + # * [:ciphers=](rdoc-ref:Net::HTTP#ciphers=): Sets the available SSL ciphers. + # * [:extra_chain_cert](rdoc-ref:Net::HTTP#extra_chain_cert): Returns the + # extra X509 certificates to be added to the certificate chain. + # * [:extra_chain_cert=](rdoc-ref:Net::HTTP#extra_chain_cert=): Sets the extra + # X509 certificates to be added to the certificate chain. + # * [:key](rdoc-ref:Net::HTTP#key): Returns the OpenSSL::PKey::RSA or + # OpenSSL::PKey::DSA object. + # * [:key=](rdoc-ref:Net::HTTP#key=): Sets the OpenSSL::PKey::RSA or + # OpenSSL::PKey::DSA object. + # * [:max_version](rdoc-ref:Net::HTTP#max_version): Returns the maximum SSL + # version. + # * [:max_version=](rdoc-ref:Net::HTTP#max_version=): Sets the maximum SSL + # version. + # * [:min_version](rdoc-ref:Net::HTTP#min_version): Returns the minimum SSL + # version. + # * [:min_version=](rdoc-ref:Net::HTTP#min_version=): Sets the minimum SSL + # version. + # * [#peer_cert](rdoc-ref:Net::HTTP#peer_cert): Returns the X509 certificate + # chain for the session's socket peer. + # * [:ssl_version](rdoc-ref:Net::HTTP#ssl_version): Returns the SSL version. + # * [:ssl_version=](rdoc-ref:Net::HTTP#ssl_version=): Sets the SSL version. + # * [#use_ssl=](rdoc-ref:Net::HTTP#use_ssl=): Sets whether a new session is to + # use Transport Layer Security. + # * [#use_ssl?](rdoc-ref:Net::HTTP#use_ssl?): Returns whether `self` uses SSL. + # * [:verify_callback](rdoc-ref:Net::HTTP#verify_callback): Returns the + # callback for the server certification verification. + # * [:verify_callback=](rdoc-ref:Net::HTTP#verify_callback=): Sets the + # callback for the server certification verification. + # * [:verify_depth](rdoc-ref:Net::HTTP#verify_depth): Returns the maximum + # depth for the certificate chain verification. + # * [:verify_depth=](rdoc-ref:Net::HTTP#verify_depth=): Sets the maximum depth + # for the certificate chain verification. + # * [:verify_hostname](rdoc-ref:Net::HTTP#verify_hostname): Returns the flags + # for server the certification verification at the beginning of the SSL/TLS + # session. + # * [:verify_hostname=](rdoc-ref:Net::HTTP#verify_hostname=): Sets he flags + # for server the certification verification at the beginning of the SSL/TLS + # session. + # * [:verify_mode](rdoc-ref:Net::HTTP#verify_mode): Returns the flags for + # server the certification verification at the beginning of the SSL/TLS + # session. + # * [:verify_mode=](rdoc-ref:Net::HTTP#verify_mode=): Sets the flags for + # server the certification verification at the beginning of the SSL/TLS + # session. + # + # + # ### Addresses and Ports + # + # * [:address](rdoc-ref:Net::HTTP#address): Returns the string host name or + # host IP. + # * [::default_port](rdoc-ref:Net::HTTP.default_port): Returns integer 80, the + # default port to use for HTTP requests. + # * [::http_default_port](rdoc-ref:Net::HTTP.http_default_port): Returns + # integer 80, the default port to use for HTTP requests. + # * [::https_default_port](rdoc-ref:Net::HTTP.https_default_port): Returns + # integer 443, the default port to use for HTTPS requests. + # * [#ipaddr](rdoc-ref:Net::HTTP#ipaddr): Returns the IP address for the + # connection. + # * [#ipaddr=](rdoc-ref:Net::HTTP#ipaddr=): Sets the IP address for the + # connection. + # * [:local_host](rdoc-ref:Net::HTTP#local_host): Returns the string local + # host used to establish the connection. + # * [:local_host=](rdoc-ref:Net::HTTP#local_host=): Sets the string local host + # used to establish the connection. + # * [:local_port](rdoc-ref:Net::HTTP#local_port): Returns the integer local + # port used to establish the connection. + # * [:local_port=](rdoc-ref:Net::HTTP#local_port=): Sets the integer local + # port used to establish the connection. + # * [:port](rdoc-ref:Net::HTTP#port): Returns the integer port number. + # + # + # ### HTTP Version + # + # * [::version_1_2?](rdoc-ref:Net::HTTP.version_1_2?) (aliased as + # [::is_version_1_2?](rdoc-ref:Net::HTTP.is_version_1_2?) and + # [::version_1_2](rdoc-ref:Net::HTTP.version_1_2)): Returns true; retained + # for compatibility. + # + # + # ### Debugging + # + # * [#set_debug_output](rdoc-ref:Net::HTTP#set_debug_output): Sets the output + # stream for debugging. # class HTTP < Protocol # :stopdoc: @@ -549,7 +885,7 @@ module Net # rdoc-file=lib/net/http.rb # - default_port() # --> - # Returns intger `80`, the default port to use for HTTP requests: + # Returns integer `80`, the default port to use for HTTP requests: # # Net::HTTP.default_port # => 80 # @@ -582,15 +918,12 @@ module Net # --> # Creates a new Net::HTTP object, `http`, via Net::HTTP.new: # - # Net::HTTP.new(address, port, p_addr, p_port, p_user, p_pass) - # - # * For arguments `hostname` through `p_pass`, see Net::HTTP.new. + # * For arguments `address` and `port`, see Net::HTTP.new. + # * For proxy-defining arguments `p_addr` through `p_pass`, see [Proxy + # Server](rdoc-ref:Net::HTTP@Proxy+Server). # * For argument `opts`, see below. # # - # Note: If `port` is `nil` and `opts[:use_ssl]` is a truthy value, the value - # passed to `new` is Net::HTTP.https_default_port, not `port`. - # # With no block given: # # * Calls `http.start` with no block (see #start), which opens a TCP @@ -664,6 +997,10 @@ module Net # * #verify_mode # * #write_timeout # + # + # Note: If `port` is `nil` and `opts[:use_ssl]` is a truthy value, the value + # passed to `new` is Net::HTTP.https_default_port, not `port`. + # def self.start: (String address, ?Integer? port, ?String | :ENV | nil p_addr, ?Integer? p_port, ?String? p_user, ?String? p_pass, ?Hash[Symbol, untyped]? opt) -> Net::HTTP | [T] (String address, ?Integer? port, ?String | :ENV | nil p_addr, ?Integer? p_port, ?String? p_user, ?String? p_pass, ?Hash[Symbol, untyped]? opt) { (Net::HTTP) -> T } -> T @@ -676,11 +1013,36 @@ module Net # - # Creates a new Net::HTTP object for the specified server address, without - # opening the TCP connection or initializing the HTTP session. The `address` - # should be a DNS hostname or IP address. + # Returns a new Net::HTTP object `http` (but does not open a TCP connection or + # HTTP session). + # + # With only string argument `address` given (and `ENV['http_proxy']` undefined + # or `nil`), the returned `http`: + # + # * Has the given address. + # * Has the default port number, Net::HTTP.default_port (80). + # * Has no proxy. + # + # + # Example: + # + # http = Net::HTTP.new(hostname) + # # => # + # http.address # => "jsonplaceholder.typicode.com" + # http.port # => 80 + # http.proxy? # => false + # + # With integer argument `port` also given, the returned `http` has the given + # port: + # + # http = Net::HTTP.new(hostname, 8000) + # # => # + # http.port # => 8000 + # + # For proxy-defining arguments `p_addr` through `p_no_proxy`, see [Proxy + # Server](rdoc-ref:Net::HTTP@Proxy+Server). # def self.new: (String address, ?Integer? port, ?String | :ENV | nil p_addr, ?Integer? p_port, ?String? p_user, ?String? p_pass, ?untyped? p_no_proxy) -> Net::HTTP @@ -751,40 +1113,52 @@ module Net def set_debug_output: (IO output) -> void # - # The DNS host name or IP address to connect to. + # Returns the string host name or host IP given as argument `address` in ::new. # attr_reader address: String # - # The port number to connect to. + # Returns the integer port number given as argument `port` in ::new. # attr_reader port: Integer # - # The local host used to establish the connection. + # Sets or returns the string local host used to establish the connection; + # initially `nil`. # attr_accessor local_host: String # - # The local port used to establish the connection. + # Sets or returns the integer local port used to establish the connection; + # initially `nil`. # attr_accessor local_port: Integer + # + # Sets whether to determine the proxy from environment variable + # '`ENV['http_proxy']`'; see [Proxy Using + # ENV['http_proxy']](rdoc-ref:Net::HTTP@Proxy+Using+-27ENV-5B-27http_proxy-27-5D + # -27). + # attr_writer proxy_from_env: untyped # + # Sets the proxy address; see [Proxy Server](rdoc-ref:Net::HTTP@Proxy+Server). # attr_accessor proxy_address: String? # + # Sets the proxy port; see [Proxy Server](rdoc-ref:Net::HTTP@Proxy+Server). # attr_accessor proxy_port: Integer? # + # Sets the proxy user; see [Proxy Server](rdoc-ref:Net::HTTP@Proxy+Server). # attr_accessor proxy_user: String? # + # Sets the proxy password; see [Proxy Server](rdoc-ref:Net::HTTP@Proxy+Server). # attr_accessor proxy_pass: String? @@ -825,18 +1199,15 @@ module Net attr_accessor ipaddr: String? # - # Number of seconds to wait for the connection to open. Any number may be used, - # including Floats for fractional seconds. If the HTTP object cannot open a - # connection in this many seconds, it raises a Net::OpenTimeout exception. The - # default value is 60 seconds. + # Sets or returns the numeric (Integer or Float) number of seconds to wait for a + # connection to open; initially 60. If the connection is not made in the given + # interval, an exception is raised. # attr_accessor open_timeout: Float | Integer # - # Number of seconds to wait for one block to be read (via one read(2) call). Any - # number may be used, including Floats for fractional seconds. If the HTTP - # object cannot read data in this many seconds, it raises a Net::ReadTimeout - # exception. The default value is 60 seconds. + # Returns the numeric (Integer or Float) number of seconds to wait for one block + # to be read (via one read(2) call); see #read_timeout=. # ---- # - # Number of seconds to wait for one block to be written (via one write(2) call). - # Any number may be used, including Floats for fractional seconds. If the HTTP - # object cannot write data in this many seconds, it raises a Net::WriteTimeout - # exception. The default value is 60 seconds. Net::WriteTimeout is not raised on - # Windows. + # Returns the numeric (Integer or Float) number of seconds to wait for one block + # to be written (via one write(2) call); see #write_timeout=. # ---- # + # Returns the maximum number of times to retry an idempotent request; see + # #max_retries=. + # ---- # - # Seconds to wait for 100 Continue response. If the HTTP object does not receive - # a response in this many seconds it sends the request body. The default value - # is `nil`. + # Returns the continue timeout value; see continue_timeout=. # ---- # - # Setter for the continue_timeout attribute. + # Sets the continue timeout value, which is the number of seconds to wait for an + # expected 100 Continue response. If the HTTP object does not receive a response + # in this many seconds it sends the request body. # attr_accessor continue_timeout: Float | Integer | nil # - # Seconds to reuse the connection of the previous request. If the idle time is - # less than this Keep-Alive Timeout, Net::HTTP reuses the TCP/IP socket used by - # the previous communication. The default value is 2 seconds. + # Sets or returns the numeric (Integer or Float) number of seconds to keep the + # connection open after a request is sent; initially 2. If a new request is made + # during the given interval, the still-open connection is used; otherwise the + # connection will have been closed and a new connection is opened. # attr_accessor keep_alive_timeout: Float | Integer @@ -913,7 +1300,19 @@ module Net # rdoc-file=lib/net/http.rb # - started?() # --> - # Returns true if the HTTP session has been started. + # Returns `true` if the HTTP session has been started: + # + # http = Net::HTTP.new(hostname) + # http.started? # => false + # http.start + # http.started? # => true + # http.finish # => nil + # http.started? # => false + # + # Net::HTTP.start(hostname) do |http| + # http.started? + # end # => true + # http.started? # => false # def started?: () -> bool @@ -924,13 +1323,17 @@ module Net # alias active? started? + # + # Sets or returns whether to close the connection when the response is empty; + # initially `false`. + # attr_accessor close_on_empty_response: untyped # - # Returns true if SSL/TLS is being used with HTTP. + # Returns `true` if `self` uses SSL, `false` otherwise. See Net::HTTP#use_ssl=. # def use_ssl?: () -> bool @@ -938,8 +1341,12 @@ module Net # rdoc-file=lib/net/http.rb # - use_ssl=(flag) # --> - # Turn on/off SSL. This flag must be set before starting session. If you change - # use_ssl value after session started, a Net::HTTP object raises IOError. + # Sets whether a new session is to use [Transport Layer + # Security](https://en.wikipedia.org/wiki/Transport_Layer_Security): + # + # Raises IOError if attempting to change during a session. + # + # Raises OpenSSL::SSL::SSLError if the port is not an HTTPS port. # def use_ssl=: (boolish flag) -> void @@ -948,87 +1355,95 @@ module Net SSL_ATTRIBUTES: Array[Symbol] # - # Sets path of a CA certification file in PEM format. - # - # The file can contain several CA certificates. + # Sets or returns the path to a CA certification file in PEM format. # attr_accessor ca_file: untyped # - # Sets path of a CA certification directory containing certifications in PEM - # format. + # Sets or returns the path of to CA directory containing certification files in + # PEM format. # attr_accessor ca_path: untyped # - # Sets an OpenSSL::X509::Certificate object as client certificate. (This method - # is appeared in Michal Rokos's OpenSSL extension). + # Sets or returns the OpenSSL::X509::Certificate object to be used for client + # certification. # attr_accessor cert: untyped # - # Sets the X509::Store to verify peer certificate. + # Sets or returns the X509::Store to be used for verifying peer certificate. # attr_accessor cert_store: untyped # - # Sets the available ciphers. See OpenSSL::SSL::SSLContext#ciphers= + # Sets or returns the available SSL ciphers. See + # [OpenSSL::SSL::SSLContext#ciphers=](rdoc-ref:OpenSSL::SSL::SSLContext#ciphers- + # 3D). # attr_accessor ciphers: untyped # - # Sets the extra X509 certificates to be added to the certificate chain. See - # OpenSSL::SSL::SSLContext#extra_chain_cert= + # Sets or returns the extra X509 certificates to be added to the certificate + # chain. See + # [OpenSSL::SSL::SSLContext#add_certificate](rdoc-ref:OpenSSL::SSL::SSLContext#a + # dd_certificate). # attr_accessor extra_chain_cert: untyped # - # Sets an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object. (This method is - # appeared in Michal Rokos's OpenSSL extension.) + # Sets or returns the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object. # attr_accessor key: untyped # - # Sets the SSL timeout seconds. + # Sets or returns the SSL timeout seconds. # attr_accessor ssl_timeout: untyped # - # Sets the SSL version. See OpenSSL::SSL::SSLContext#ssl_version= + # Sets or returns the SSL version. See + # [OpenSSL::SSL::SSLContext#ssl_version=](rdoc-ref:OpenSSL::SSL::SSLContext#ssl_ + # version-3D). # attr_accessor ssl_version: untyped # - # Sets the minimum SSL version. See OpenSSL::SSL::SSLContext#min_version= + # Sets or returns the minimum SSL version. See + # [OpenSSL::SSL::SSLContext#min_version=](rdoc-ref:OpenSSL::SSL::SSLContext#min_ + # version-3D). # attr_accessor min_version: untyped # - # Sets the maximum SSL version. See OpenSSL::SSL::SSLContext#max_version= + # Sets or returns the maximum SSL version. See + # [OpenSSL::SSL::SSLContext#max_version=](rdoc-ref:OpenSSL::SSL::SSLContext#max_ + # version-3D). # attr_accessor max_version: untyped # - # Sets the verify callback for the server certification verification. + # Sets or returns the callback for the server certification verification. # attr_accessor verify_callback: untyped # - # Sets the maximum depth for the certificate chain verification. + # Sets or returns the maximum depth for the certificate chain verification. # attr_accessor verify_depth: untyped # - # Sets the flags for server the certification verification at beginning of - # SSL/TLS session. - # - # OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER are acceptable. + # Sets or returns the flags for server the certification verification at the + # beginning of the SSL/TLS session. OpenSSL::SSL::VERIFY_NONE or + # OpenSSL::SSL::VERIFY_PEER are acceptable. # attr_accessor verify_mode: untyped # - # Sets to check the server certificate is valid for the hostname. See - # OpenSSL::SSL::SSLContext#verify_hostname= + # Sets or returns whether to verify that the server certificate is valid for the + # hostname. See + # [OpenSSL::SSL::SSLContext#verify_hostname=](rdoc-ref:OpenSSL::SSL::SSLContext# + # attribute-i-verify_mode). # attr_accessor verify_hostname: untyped @@ -1036,7 +1451,8 @@ module Net # rdoc-file=lib/net/http.rb # - peer_cert() # --> - # Returns the X.509 certificates the server presented. + # Returns the X509 certificate chain (an array of strings) for the session's + # socket peer, or `nil` if none. # def peer_cert: () -> (nil | untyped) @@ -1044,14 +1460,25 @@ module Net # rdoc-file=lib/net/http.rb # - start() { |http| ... } # --> - # Opens a TCP connection and HTTP session. + # Starts an HTTP session. + # + # Without a block, returns `self`: # - # When this method is called with a block, it passes the Net::HTTP object to the - # block, and closes the TCP connection and HTTP session after the block has been - # executed. + # http = Net::HTTP.new(hostname) + # # => # + # http.start + # # => # + # http.started? # => true + # http.finish + # + # With a block, calls the block with `self`, finishes the session when the block + # exits, and returns the block's value: # - # When called with a block, it returns the return value of the block; otherwise, - # it returns self. + # http.start do |http| + # http + # end + # # => # + # http.started? # => false # def start: [T] () { (Net::HTTP) -> T } -> T | () -> Net::HTTP @@ -1062,8 +1489,15 @@ module Net # rdoc-file=lib/net/http.rb # - finish() # --> - # Finishes the HTTP session and closes the TCP connection. Raises IOError if the - # session has not been started. + # Finishes the HTTP session: + # + # http = Net::HTTP.new(hostname) + # http.start + # http.started? # => true + # http.finish # => nil + # http.started? # => false + # + # Raises IOError if not in a session. # def finish: () -> void @@ -1085,27 +1519,31 @@ module Net # rdoc-file=lib/net/http.rb # - proxy_class?() # --> - # returns true if self is a class which was created by HTTP::Proxy. + # Returns true if self is a class which was created by HTTP::Proxy. # def self.proxy_class?: () -> bool # - # Address of proxy host. If Net::HTTP does not use a proxy, nil. + # Returns the address of the proxy host, or `nil` if none; see + # Net::HTTP@Proxy+Server. # attr_reader self.proxy_address: String? # - # Port number of proxy host. If Net::HTTP does not use a proxy, nil. + # Returns the port number of the proxy host, or `nil` if none; see + # Net::HTTP@Proxy+Server. # attr_reader self.proxy_port: Integer? # - # User name for accessing proxy. If Net::HTTP does not use a proxy, nil. + # Returns the user name for accessing the proxy, or `nil` if none; see + # Net::HTTP@Proxy+Server. # attr_reader self.proxy_user: String? # - # User password for accessing proxy. If Net::HTTP does not use a proxy, nil. + # Returns the password for accessing the proxy, or `nil` if none; see + # Net::HTTP@Proxy+Server. # attr_reader self.proxy_pass: String? @@ -1113,7 +1551,8 @@ module Net # rdoc-file=lib/net/http.rb # - proxy?() # --> - # True if requests for this connection will be proxied + # Returns `true` if a proxy server is defined, `false` otherwise; see [Proxy + # Server](rdoc-ref:Net::HTTP@Proxy+Server). # def proxy?: () -> bool @@ -1121,7 +1560,8 @@ module Net # rdoc-file=lib/net/http.rb # - proxy_from_env?() # --> - # True if the proxy for this connection is determined from the environment + # Returns `true` if the proxy server is defined in the environment, `false` + # otherwise; see [Proxy Server](rdoc-ref:Net::HTTP@Proxy+Server). # def proxy_from_env?: () -> bool @@ -1145,39 +1585,33 @@ module Net # - # Retrieves data from `path` on the connected-to host which may be an absolute - # path String or a URI to extract the path from. + # Sends a GET request to the server; returns an instance of a subclass of + # Net::HTTPResponse. # - # `initheader` must be a Hash like { 'Accept' => '**/**', ... }, and it defaults - # to an empty hash. If `initheader` doesn't have the key 'accept-encoding', then - # a value of "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" is used, so that gzip - # compression is used in preference to deflate compression, which is used in - # preference to no compression. Ruby doesn't have libraries to support the - # compress (Lempel-Ziv) compression, so that is not supported. The intent of - # this is to reduce bandwidth by default. If this routine sets up compression, - # then it does the decompression also, removing the header as well to prevent - # confusion. Otherwise it leaves the body as it found it. + # The request is based on the Net::HTTP::Get object created from string `path` + # and initial headers hash `initheader`. # - # This method returns a Net::HTTPResponse object. + # With a block given, calls the block with the response body: # - # If called with a block, yields each fragment of the entity body in turn as a - # string as it is read from the socket. Note that in this case, the returned - # response object will **not** contain a (meaningful) body. + # http = Net::HTTP.new(hostname) + # http.get('/todos/1') do |res| + # p res + # end # => # # - # `dest` argument is obsolete. It still works but you must not use it. + # Output: # - # This method never raises an exception. + # "{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false\n}" # - # response = http.get('/index.html') + # With no block given, simply returns the response object: # - # # using block - # File.open('result.txt', 'w') {|f| - # http.get('/~foo/') do |str| - # f.write str - # end - # } + # http.get('/') # => # + # + # Related: + # + # * Net::HTTP::Get: request class for HTTP method GET. + # * Net::HTTP.get: sends GET request, returns response body. # def get: (String path, ?Hash[String, untyped] initheader, ?bot dest) ?{ (String body_segment) -> void } -> Net::HTTPResponse @@ -1185,69 +1619,112 @@ module Net # rdoc-file=lib/net/http.rb # - head(path, initheader = nil) # --> - # Gets only the header from `path` on the connected-to host. `header` is a Hash - # like { 'Accept' => '**/**', ... }. + # Sends a HEAD request to the server; returns an instance of a subclass of + # Net::HTTPResponse. # - # This method returns a Net::HTTPResponse object. + # The request is based on the Net::HTTP::Head object created from string `path` + # and initial headers hash `initheader`: # - # This method never raises an exception. - # - # response = nil - # Net::HTTP.start('some.www.server', 80) {|http| - # response = http.head('/index.html') - # } - # p response['content-type'] + # res = http.head('/todos/1') # => # + # res.body # => nil + # res.to_hash.take(3) + # # => + # [["date", ["Wed, 15 Feb 2023 15:25:42 GMT"]], + # ["content-type", ["application/json; charset=utf-8"]], + # ["connection", ["close"]]] # def head: (String path, ?Hash[String, untyped] initheader) -> Net::HTTPResponse # - # Posts `data` (must be a String) to `path`. `header` must be a Hash like { - # 'Accept' => '**/**', ... }. + # Sends a POST request to the server; returns an instance of a subclass of + # Net::HTTPResponse. # - # This method returns a Net::HTTPResponse object. + # The request is based on the Net::HTTP::Post object created from string `path`, + # string `data`, and initial headers hash `initheader`. # - # If called with a block, yields each fragment of the entity body in turn as a - # string as it is read from the socket. Note that in this case, the returned - # response object will **not** contain a (meaningful) body. + # With a block given, calls the block with the response body: # - # `dest` argument is obsolete. It still works but you must not use it. + # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}' + # http = Net::HTTP.new(hostname) + # http.post('/todos', data) do |res| + # p res + # end # => # # - # This method never raises exception. + # Output: # - # response = http.post('/cgi-bin/search.rb', 'query=foo') + # "{\n \"{\\\"userId\\\": 1, \\\"id\\\": 1, \\\"title\\\": \\\"delectus aut autem\\\", \\\"completed\\\": false}\": \"\",\n \"id\": 201\n}" # - # # using block - # File.open('result.txt', 'w') {|f| - # http.post('/cgi-bin/search.rb', 'query=foo') do |str| - # f.write str - # end - # } + # With no block given, simply returns the response object: # - # You should set Content-Type: header field for POST. If no Content-Type: field - # given, this method uses "application/x-www-form-urlencoded" by default. + # http.post('/todos', data) # => # + # + # Related: + # + # * Net::HTTP::Post: request class for HTTP method POST. + # * Net::HTTP.post: sends POST request, returns response body. # def post: (String path, String data, ?Hash[String, untyped] initheader, ?bot dest) ?{ (String body_segment) -> void } -> Net::HTTPResponse # - # Sends a PATCH request to the `path` and gets a response, as an HTTPResponse - # object. + # Sends a PATCH request to the server; returns an instance of a subclass of + # Net::HTTPResponse. + # + # The request is based on the Net::HTTP::Patch object created from string + # `path`, string `data`, and initial headers hash `initheader`. + # + # With a block given, calls the block with the response body: + # + # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}' + # http = Net::HTTP.new(hostname) + # http.patch('/todos/1', data) do |res| + # p res + # end # => # + # + # Output: + # + # "{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false,\n \"{\\\"userId\\\": 1, \\\"id\\\": 1, \\\"title\\\": \\\"delectus aut autem\\\", \\\"completed\\\": false}\": \"\"\n}" + # + # With no block given, simply returns the response object: + # + # http.patch('/todos/1', data) # => # # def patch: (String path, String data, ?Hash[String, untyped] initheader, ?bot dest) ?{ (String body_segment) -> void } -> Net::HTTPResponse + # + # Sends a PUT request to the server; returns an instance of a subclass of + # Net::HTTPResponse. + # + # The request is based on the Net::HTTP::Put object created from string `path`, + # string `data`, and initial headers hash `initheader`. + # + # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}' + # http = Net::HTTP.new(hostname) + # http.put('/todos/1', data) # => # + # def put: (String path, String data, ?Hash[String, untyped] initheader) -> Net::HTTPResponse # - # Sends a PROPPATCH request to the `path` and gets a response, as an - # HTTPResponse object. + # Sends a PROPPATCH request to the server; returns an instance of a subclass of + # Net::HTTPResponse. + # + # The request is based on the Net::HTTP::Proppatch object created from string + # `path`, string `body`, and initial headers hash `initheader`. + # + # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}' + # http = Net::HTTP.new(hostname) + # http.proppatch('/todos/1', data) # def proppatch: (String path, String body, ?Hash[String, untyped] initheader) -> Net::HTTPResponse @@ -1255,8 +1732,15 @@ module Net # rdoc-file=lib/net/http.rb # - lock(path, body, initheader = nil) # --> - # Sends a LOCK request to the `path` and gets a response, as an HTTPResponse - # object. + # Sends a LOCK request to the server; returns an instance of a subclass of + # Net::HTTPResponse. + # + # The request is based on the Net::HTTP::Lock object created from string `path`, + # string `body`, and initial headers hash `initheader`. + # + # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}' + # http = Net::HTTP.new(hostname) + # http.lock('/todos/1', data) # def lock: (String path, String body, ?Hash[String, untyped] initheader) -> Net::HTTPResponse @@ -1264,8 +1748,15 @@ module Net # rdoc-file=lib/net/http.rb # - unlock(path, body, initheader = nil) # --> - # Sends a UNLOCK request to the `path` and gets a response, as an HTTPResponse - # object. + # Sends an UNLOCK request to the server; returns an instance of a subclass of + # Net::HTTPResponse. + # + # The request is based on the Net::HTTP::Unlock object created from string + # `path`, string `body`, and initial headers hash `initheader`. + # + # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}' + # http = Net::HTTP.new(hostname) + # http.unlock('/todos/1', data) # def unlock: (String path, String body, ?Hash[String, untyped] initheader) -> Net::HTTPResponse @@ -1273,8 +1764,14 @@ module Net # rdoc-file=lib/net/http.rb # - options(path, initheader = nil) # --> - # Sends a OPTIONS request to the `path` and gets a response, as an HTTPResponse - # object. + # Sends an Options request to the server; returns an instance of a subclass of + # Net::HTTPResponse. + # + # The request is based on the Net::HTTP::Options object created from string + # `path` and initial headers hash `initheader`. + # + # http = Net::HTTP.new(hostname) + # http.options('/') # def options: (String path, ?Hash[String, untyped] initheader) -> Net::HTTPResponse @@ -1282,8 +1779,15 @@ module Net # rdoc-file=lib/net/http.rb # - propfind(path, body = nil, initheader = {'Depth' => '0'}) # --> - # Sends a PROPFIND request to the `path` and gets a response, as an HTTPResponse - # object. + # Sends a PROPFIND request to the server; returns an instance of a subclass of + # Net::HTTPResponse. + # + # The request is based on the Net::HTTP::Propfind object created from string + # `path`, string `body`, and initial headers hash `initheader`. + # + # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}' + # http = Net::HTTP.new(hostname) + # http.propfind('/todos/1', data) # def propfind: (String path, ?untyped? body, ?Hash[String, untyped] initheader) -> Net::HTTPResponse @@ -1291,8 +1795,14 @@ module Net # rdoc-file=lib/net/http.rb # - delete(path, initheader = {'Depth' => 'Infinity'}) # --> - # Sends a DELETE request to the `path` and gets a response, as an HTTPResponse - # object. + # Sends a DELETE request to the server; returns an instance of a subclass of + # Net::HTTPResponse. + # + # The request is based on the Net::HTTP::Delete object created from string + # `path` and initial headers hash `initheader`. + # + # http = Net::HTTP.new(hostname) + # http.delete('/todos/1') # def delete: (String path, ?Hash[String, untyped] initheader) -> Net::HTTPResponse @@ -1300,8 +1810,14 @@ module Net # rdoc-file=lib/net/http.rb # - move(path, initheader = nil) # --> - # Sends a MOVE request to the `path` and gets a response, as an HTTPResponse - # object. + # Sends a MOVE request to the server; returns an instance of a subclass of + # Net::HTTPResponse. + # + # The request is based on the Net::HTTP::Move object created from string `path` + # and initial headers hash `initheader`. + # + # http = Net::HTTP.new(hostname) + # http.move('/todos/1') # def move: (String path, ?Hash[String, untyped] initheader) -> Net::HTTPResponse @@ -1309,8 +1825,14 @@ module Net # rdoc-file=lib/net/http.rb # - copy(path, initheader = nil) # --> - # Sends a COPY request to the `path` and gets a response, as an HTTPResponse - # object. + # Sends a COPY request to the server; returns an instance of a subclass of + # Net::HTTPResponse. + # + # The request is based on the Net::HTTP::Copy object created from string `path` + # and initial headers hash `initheader`. + # + # http = Net::HTTP.new(hostname) + # http.copy('/todos/1') # def copy: (String path, ?Hash[String, untyped] initheader) -> Net::HTTPResponse @@ -1318,8 +1840,15 @@ module Net # rdoc-file=lib/net/http.rb # - mkcol(path, body = nil, initheader = nil) # --> - # Sends a MKCOL request to the `path` and gets a response, as an HTTPResponse - # object. + # Sends a MKCOL request to the server; returns an instance of a subclass of + # Net::HTTPResponse. + # + # The request is based on the Net::HTTP::Mkcol object created from string + # `path`, string `body`, and initial headers hash `initheader`. + # + # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}' + # http.mkcol('/todos/1', data) + # http = Net::HTTP.new(hostname) # def mkcol: (String path, ?untyped? body, ?Hash[String, untyped] initheader) -> Net::HTTPResponse @@ -1327,8 +1856,14 @@ module Net # rdoc-file=lib/net/http.rb # - trace(path, initheader = nil) # --> - # Sends a TRACE request to the `path` and gets a response, as an HTTPResponse - # object. + # Sends a TRACE request to the server; returns an instance of a subclass of + # Net::HTTPResponse. + # + # The request is based on the Net::HTTP::Trace object created from string `path` + # and initial headers hash `initheader`. + # + # http = Net::HTTP.new(hostname) + # http.trace('/todos/1') # def trace: (String path, ?Hash[String, untyped] initheader) -> Net::HTTPResponse @@ -1336,29 +1871,27 @@ module Net # rdoc-file=lib/net/http.rb # - request_get(path, initheader = nil) { |response| ... } # --> - # Sends a GET request to the `path`. Returns the response as a Net::HTTPResponse + # Sends a GET request to the server; forms the response into a Net::HTTPResponse # object. # - # When called with a block, passes an HTTPResponse object to the block. The body - # of the response will not have been read yet; the block can process it using - # HTTPResponse#read_body, if desired. + # The request is based on the Net::HTTP::Get object created from string `path` + # and initial headers hash `initheader`. + # + # With no block given, returns the response object: # - # Returns the response. + # http = Net::HTTP.new(hostname) + # http.request_get('/todos') # => # # - # This method never raises Net::* exceptions. + # With a block given, calls the block with the response object and returns the + # response object: # - # response = http.request_get('/index.html') - # # The entity body is already read in this case. - # p response['content-type'] - # puts response.body + # http.request_get('/todos') do |res| + # p res + # end # => # # - # # Using a block - # http.request_get('/index.html') {|response| - # p response['content-type'] - # response.read_body do |str| # read body now - # print str - # end - # } + # Output: + # + # # # def request_get: (String path, ?Hash[String, untyped] initheader) ?{ (Net::HTTPResponse response) -> void } -> Net::HTTPResponse @@ -1366,15 +1899,14 @@ module Net # rdoc-file=lib/net/http.rb # - request_head(path, initheader = nil, &block) # --> - # Sends a HEAD request to the `path` and returns the response as a - # Net::HTTPResponse object. + # Sends a HEAD request to the server; returns an instance of a subclass of + # Net::HTTPResponse. # - # Returns the response. + # The request is based on the Net::HTTP::Head object created from string `path` + # and initial headers hash `initheader`. # - # This method never raises Net::* exceptions. - # - # response = http.request_head('/index.html') - # p response['content-type'] + # http = Net::HTTP.new(hostname) + # http.head('/todos/1') # => # # def request_head: (String path, ?Hash[String, untyped] initheader) ?{ (Net::HTTPResponse response) -> void } -> Net::HTTPResponse @@ -1382,31 +1914,28 @@ module Net # rdoc-file=lib/net/http.rb # - request_post(path, data, initheader = nil) { |response| ... } # --> - # Sends a POST request to the `path`. + # Sends a POST request to the server; forms the response into a + # Net::HTTPResponse object. # - # Returns the response as a Net::HTTPResponse object. + # The request is based on the Net::HTTP::Post object created from string `path`, + # string `data`, and initial headers hash `initheader`. # - # When called with a block, the block is passed an HTTPResponse object. The - # body of that response will not have been read yet; the block can process it - # using HTTPResponse#read_body, if desired. + # With no block given, returns the response object: # - # Returns the response. + # http = Net::HTTP.new(hostname) + # http.post('/todos', 'xyzzy') + # # => # # - # This method never raises Net::* exceptions. + # With a block given, calls the block with the response body and returns the + # response object: # - # # example - # response = http.request_post('/cgi-bin/nice.rb', 'datadatadata...') - # p response.status - # puts response.body # body is already read in this case + # http.post('/todos', 'xyzzy') do |res| + # p res + # end # => # # - # # using block - # http.request_post('/cgi-bin/nice.rb', 'datadatadata...') {|response| - # p response.status - # p response['content-type'] - # response.read_body do |str| # read body now - # print str - # end - # } + # Output: + # + # "{\n \"xyzzy\": \"\",\n \"id\": 201\n}" # def request_post: (String path, String data, ?Hash[String, untyped] initheader) ?{ (Net::HTTPResponse response) -> void } -> Net::HTTPResponse @@ -1439,15 +1968,24 @@ module Net # rdoc-file=lib/net/http.rb # - send_request(name, path, data = nil, header = nil) # --> - # Sends an HTTP request to the HTTP server. Also sends a DATA string if `data` - # is given. + # Sends an HTTP request to the server; returns an instance of a subclass of + # Net::HTTPResponse. # - # Returns a Net::HTTPResponse object. + # The request is based on the Net::HTTPRequest object created from string + # `path`, string `data`, and initial headers hash `header`. That object is an + # instance of the [subclass of + # Net::HTTPRequest](rdoc-ref:Net::HTTPRequest@Request+Subclasses), that + # corresponds to the given uppercase string `name`, which must be an [HTTP + # request method](https://en.wikipedia.org/wiki/HTTP#Request_methods) or a + # [WebDAV request method](https://en.wikipedia.org/wiki/WebDAV#Implementation). # - # This method never raises Net::* exceptions. + # Examples: # - # response = http.send_request('GET', '/index.html') - # puts response.body + # http = Net::HTTP.new(hostname) + # http.send_request('GET', '/todos/1') + # # => # + # http.send_request('POST', '/todos', 'xyzzy') + # # => # # def send_request: (String name, String path, ?String? data, ?Hash[String, untyped]? header) -> Net::HTTPResponse @@ -1455,28 +1993,80 @@ module Net # rdoc-file=lib/net/http.rb # - request(req, body = nil) { |response| ... } # --> - # Sends an HTTPRequest object `req` to the HTTP server. + # Sends the given request `req` to the server; forms the response into a + # Net::HTTPResponse object. + # + # The given `req` must be an instance of a [subclass of + # Net::HTTPRequest](rdoc-ref:Net::HTTPRequest@Request+Subclasses). Argument + # `body` should be given only if needed for the request. + # + # With no block given, returns the response object: + # + # http = Net::HTTP.new(hostname) + # + # req = Net::HTTP::Get.new('/todos/1') + # http.request(req) + # # => # # - # If `req` is a Net::HTTP::Post or Net::HTTP::Put request containing data, the - # data is also sent. Providing data for a Net::HTTP::Head or Net::HTTP::Get - # request results in an ArgumentError. + # req = Net::HTTP::Post.new('/todos') + # http.request(req, 'xyzzy') + # # => # # - # Returns an HTTPResponse object. + # With a block given, calls the block with the response and returns the + # response: # - # When called with a block, passes an HTTPResponse object to the block. The body - # of the response will not have been read yet; the block can process it using - # HTTPResponse#read_body, if desired. + # req = Net::HTTP::Get.new('/todos/1') + # http.request(req) do |res| + # p res + # end # => # + # + # Output: # - # This method never raises Net::* exceptions. + # # # def request: (Net::HTTPRequest req, ?String? body) ?{ (Net::HTTPResponse response) -> void } -> Net::HTTPResponse end # - # HTTPGenericRequest is the parent of the Net::HTTPRequest class. Do not use - # this directly; use a subclass of Net::HTTPRequest. + # HTTPGenericRequest is the parent of the Net::HTTPRequest class. + # + # Do not use this directly; instead, use a subclass of Net::HTTPRequest. + # + # ## About the Examples + # + # Examples here assume that `net/http` has been required (which also requires + # `uri`): + # + # require 'net/http' + # + # Many code examples here use these example websites: + # + # * https://jsonplaceholder.typicode.com. + # * http://example.com. + # + # + # Some examples also assume these variables: + # + # uri = URI('https://jsonplaceholder.typicode.com/') + # uri.freeze # Examples may not modify. + # hostname = uri.hostname # => "jsonplaceholder.typicode.com" + # path = uri.path # => "/" + # port = uri.port # => 443 # - # Mixes in the Net::HTTPHeader module to provide easier access to HTTP headers. + # So that example requests may be written as: + # + # Net::HTTP.get(uri) + # Net::HTTP.get(hostname, '/index.html') + # Net::HTTP.start(hostname) do |http| + # http.get('/todos/1') + # http.get('/todos/2') + # end + # + # An example that needs a modified URI first duplicates `uri`, then modifies the + # duplicate: + # + # _uri = uri.dup + # _uri.path = '/todos/1' # class HTTPGenericRequest include Net::HTTPHeader @@ -1488,15 +2078,43 @@ module Net # def initialize: (String m, boolish reqbody, boolish resbody, URI::Generic | String uri_or_path, ?Hash[String, untyped] initheader) -> Net::HTTP + # + # Returns the string method name for the request: + # + # Net::HTTP::Get.new(uri).method # => "GET" + # Net::HTTP::Post.new(uri).method # => "POST" + # attr_reader method: String + # + # Returns the string path for the request: + # + # Net::HTTP::Get.new(uri).path # => "/" + # Net::HTTP::Post.new('example.com').path # => "example.com" + # attr_reader path: String + # + # Returns the URI object for the request, or `nil` if none: + # + # Net::HTTP::Get.new(uri).uri + # # => # + # Net::HTTP::Get.new('example.com').uri # => nil + # attr_reader uri: URI::Generic # - # Automatically set to false if the user sets the Accept-Encoding header. This - # indicates they wish to handle Content-encoding in responses themselves. + # Returns `false` if the request's header `'Accept-Encoding'` has been set + # manually or deleted (indicating that the user intends to handle encoding in + # the response), `true` otherwise: + # + # req = Net::HTTP::Get.new(uri) # => # + # req['Accept-Encoding'] # => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" + # req.decode_content # => true + # req['Accept-Encoding'] = 'foo' + # req.decode_content # => false + # req.delete('Accept-Encoding') + # req.decode_content # => false # attr_reader decode_content: bool @@ -1504,6 +2122,9 @@ module Net # rdoc-file=lib/net/http/generic_request.rb # - inspect() # --> + # Returns a string representation of the request: + # + # Net::HTTP::Post.new(uri).inspect # => "#" # def inspect: () -> String @@ -1513,6 +2134,10 @@ module Net # rdoc-file=lib/net/http/generic_request.rb # - request_body_permitted?() # --> + # Returns whether the request may have a body: + # + # Net::HTTP::Post.new(uri).request_body_permitted? # => true + # Net::HTTP::Get.new(uri).request_body_permitted? # => false # def request_body_permitted?: () -> bool @@ -1520,6 +2145,10 @@ module Net # rdoc-file=lib/net/http/generic_request.rb # - response_body_permitted?() # --> + # Returns whether the response may have a body: + # + # Net::HTTP::Post.new(uri).response_body_permitted? # => true + # Net::HTTP::Head.new(uri).response_body_permitted? # => false # def response_body_permitted?: () -> bool @@ -1530,17 +2159,47 @@ module Net # def body_exist?: () -> bool + # + # Returns the string body for the request, or `nil` if there is none: + # + # req = Net::HTTP::Post.new(uri) + # req.body # => nil + # req.body = '{"title": "foo","body": "bar","userId": 1}' + # req.body # => "{\"title\": \"foo\",\"body\": \"bar\",\"userId\": 1}" + # ---- # + # Sets the body for the request: + # + # req = Net::HTTP::Post.new(uri) + # req.body # => nil + # req.body = '{"title": "foo","body": "bar","userId": 1}' + # req.body # => "{\"title\": \"foo\",\"body\": \"bar\",\"userId\": 1}" # attr_accessor body: String? + # + # Returns the body stream object for the request, or `nil` if there is none: + # + # req = Net::HTTP::Post.new(uri) # => # + # req.body_stream # => nil + # require 'stringio' + # req.body_stream = StringIO.new('xyzzy') # => # + # req.body_stream # => # + # ---- # + # Sets the body stream for the request: + # + # req = Net::HTTP::Post.new(uri) # => # + # req.body_stream # => nil + # require 'stringio' + # req.body_stream = StringIO.new('xyzzy') # => # + # req.body_stream # => # # attr_accessor body_stream: untyped end @@ -1594,9 +2253,10 @@ module Net # # Some examples also assume these variables: # - # uri = URI('https://jsonplaceholder.typicode.com') + # uri = URI('https://jsonplaceholder.typicode.com/') # uri.freeze # Examples may not modify. # hostname = uri.hostname # => "jsonplaceholder.typicode.com" + # path = uri.path # => "/" # port = uri.port # => 443 # # So that example requests may be written as: @@ -2327,18 +2987,37 @@ module Net # rdoc-file=lib/net/http/header.rb # - set_form_data(params, sep = '&') # --> - # Set header fields and a body from HTML form data. `params` should be an Array - # of Arrays or a Hash containing HTML form data. Optional argument `sep` means - # data record separator. + # Sets the request body to a URL-encoded string derived from argument `params`, + # and sets request header field `'Content-Type'` to + # `'application/x-www-form-urlencoded'`. # - # Values are URL encoded as necessary and the content-type is set to - # application/x-www-form-urlencoded + # The resulting request is suitable for HTTP request `POST` or `PUT`. # - # Example: + # Argument `params` must be suitable for use as argument `enum` to + # [URI.encode_www_form](rdoc-ref:URI.encode_www_form). + # + # With only argument `params` given, sets the body to a URL-encoded string with + # the default separator `'&'`: + # + # req = Net::HTTP::Post.new('example.com') + # + # req.set_form_data(q: 'ruby', lang: 'en') + # req.body # => "q=ruby&lang=en" + # req['Content-Type'] # => "application/x-www-form-urlencoded" + # + # req.set_form_data([['q', 'ruby'], ['lang', 'en']]) + # req.body # => "q=ruby&lang=en" + # + # req.set_form_data(q: ['ruby', 'perl'], lang: 'en') + # req.body # => "q=ruby&q=perl&lang=en" + # + # req.set_form_data([['q', 'ruby'], ['q', 'perl'], ['lang', 'en']]) + # req.body # => "q=ruby&q=perl&lang=en" + # + # With string argument `sep` also given, uses that string as the separator: # - # http.form_data = {"q" => "ruby", "lang" => "en"} - # http.form_data = {"q" => ["ruby", "perl"], "lang" => "en"} - # http.set_form_data({"q" => "ruby", "lang" => "en"}, ';') + # req.set_form_data({q: 'ruby', lang: 'en'}, '|') + # req.body # => "q=ruby|lang=en" # # Net::HTTPHeader#form_data= is an alias for Net::HTTPHeader#set_form_data. # @@ -2355,61 +3034,110 @@ module Net # rdoc-file=lib/net/http/header.rb # - set_form(params, enctype='application/x-www-form-urlencoded', formopt={}) # --> - # Set an HTML form data set. - # `params` - # : The form data to set, which should be an enumerable. See below for more - # details. - # `enctype` - # : The content type to use to encode the form submission, which should be - # application/x-www-form-urlencoded or multipart/form-data. - # `formopt` - # : An options hash, supporting the following options: - # :boundary - # : The boundary of the multipart message. If not given, a random boundary - # will be used. - # :charset - # : The charset of the form submission. All field names and values of - # non-file fields should be encoded with this charset. + # Stores form data to be used in a `POST` or `PUT` request. # + # The form data given in `params` consists of zero or more fields; each field + # is: # + # * A scalar value. + # * A name/value pair. + # * An IO stream opened for reading. # - # Each item of params should respond to `each` and yield 2-3 arguments, or an - # array of 2-3 elements. The arguments yielded should be: # - # * The name of the field. - # * The value of the field, it should be a String or a File or IO-like. - # * An options hash, supporting the following options (used only for file - # uploads); entries: + # Argument `params` should be an + # [Enumerable](rdoc-ref:Enumerable@Enumerable+in+Ruby+Classes) (method + # `params.map` will be called), and is often an array or hash. # - # * `:filename`: The name of the file to use. - # * `:content_type`: The content type of the uploaded file. + # First, we set up a request: # + # _uri = uri.dup + # _uri.path ='/posts' + # req = Net::HTTP::Post.new(_uri) # + # **Argument `params` As an Array** # - # Each item is a file field or a normal field. If `value` is a File object or - # the `opt` hash has a :filename key, the item is treated as a file field. + # When `params` is an array, each of its elements is a subarray that defines a + # field; the subarray may contain: # - # If Transfer-Encoding is set as chunked, this sends the request using chunked - # encoding. Because chunked encoding is HTTP/1.1 feature, you should confirm - # that the server supports HTTP/1.1 before using chunked encoding. + # * One string: # - # Example: + # req.set_form([['foo'], ['bar'], ['baz']]) + # + # * Two strings: + # + # req.set_form([%w[foo 0], %w[bar 1], %w[baz 2]]) + # + # * When argument `enctype` (see below) is given as `'multipart/form-data'`: + # + # * A string name and an IO stream opened for reading: + # + # require 'stringio' + # req.set_form([['file', StringIO.new('Ruby is cool.')]]) + # + # * A string name, an IO stream opened for reading, and an options hash, + # which may contain these entries: + # + # * `:filename`: The name of the file to use. + # * `:content_type`: The content type of the uploaded file. + # + # + # Example: # - # req.set_form([["q", "ruby"], ["lang", "en"]]) + # req.set_form([['file', file, {filename: "other-filename.foo"}]] # - # req.set_form({"f"=>File.open('/path/to/filename')}, - # "multipart/form-data", - # charset: "UTF-8", - # ) # - # req.set_form([["f", - # File.open('/path/to/filename.bar'), - # {filename: "other-filename.foo"} - # ]], - # "multipart/form-data", - # ) # - # See also RFC 2388, RFC 2616, HTML 4.01, and HTML5 + # The various forms may be mixed: + # + # req.set_form(['foo', %w[bar 1], ['file', file]]) + # + # **Argument `params` As a Hash** + # + # When `params` is a hash, each of its entries is a name/value pair that defines + # a field: + # + # * The name is a string. + # * The value may be: + # + # * `nil`. + # * Another string. + # * An IO stream opened for reading (only when argument `enctype` -- see + # below -- is given as `'multipart/form-data'`). + # + # + # + # Examples: + # + # # Nil-valued fields. + # req.set_form({'foo' => nil, 'bar' => nil, 'baz' => nil}) + # + # # String-valued fields. + # req.set_form({'foo' => 0, 'bar' => 1, 'baz' => 2}) + # + # # IO-valued field. + # require 'stringio' + # req.set_form({'file' => StringIO.new('Ruby is cool.')}) + # + # # Mixture of fields. + # req.set_form({'foo' => nil, 'bar' => 1, 'file' => file}) + # + # Optional argument `enctype` specifies the value to be given to field + # `'Content-Type'`, and must be one of: + # + # * `'application/x-www-form-urlencoded'` (the default). + # * `'multipart/form-data'`; see [RFC + # 7578](https://www.rfc-editor.org/rfc/rfc7578). + # + # + # Optional argument `formopt` is a hash of options (applicable only when + # argument `enctype` is `'multipart/form-data'`) that may include the following + # entries: + # + # * `:boundary`: The value is the boundary string for the multipart message. + # If not given, the boundary is a random string. See + # [Boundary](https://www.rfc-editor.org/rfc/rfc7578#section-4.1). + # * `:charset`: Value is the character set for the form submission. Field + # names and values of non-file fields should be encoded with this charset. # def set_form: (Hash[untyped, untyped] params, ?String enctype, ?Hash[untyped, untyped] formopt) -> void @@ -2417,7 +3145,12 @@ module Net # rdoc-file=lib/net/http/header.rb # - basic_auth(account, password) # --> - # Set the Authorization: header for "Basic" authorization. + # Sets header `'Authorization'` using the given `account` and `password` + # strings: + # + # req.basic_auth('my_account', 'my_password') + # req['Authorization'] + # # => "Basic bXlfYWNjb3VudDpteV9wYXNzd29yZA==" # def basic_auth: (String account, String password) -> void @@ -2425,7 +3158,12 @@ module Net # rdoc-file=lib/net/http/header.rb # - proxy_basic_auth(account, password) # --> - # Set Proxy-Authorization: header for "Basic" authorization. + # Sets header `'Proxy-Authorization'` using the given `account` and `password` + # strings: + # + # req.proxy_basic_auth('my_account', 'my_password') + # req['Proxy-Authorization'] + # # => "Basic bXlfYWNjb3VudDpteV9wYXNzd29yZA==" # def proxy_basic_auth: (String account, String password) -> void @@ -2444,6 +3182,7 @@ module Net # rdoc-file=lib/net/http/header.rb # - connection_close?() # --> + # Returns whether the HTTP session is to be closed. # def connection_close?: () -> bool @@ -2451,15 +3190,70 @@ module Net # rdoc-file=lib/net/http/header.rb # - connection_keep_alive?() # --> + # Returns whether the HTTP session is to be kept alive. # def connection_keep_alive?: () -> bool end # - # This class is the base class for Net::HTTP request classes; it wraps together - # the request path and the request headers. + # This class is the base class for Net::HTTP request classes. The class should + # not be used directly; instead you should use its subclasses, listed below. + # + # ## Creating a Request # - # The class should not be used directly; instead you should use its subclasses. + # An request object may be created with either a URI or a string hostname: + # + # require 'net/http' + # uri = URI('https://jsonplaceholder.typicode.com/') + # req = Net::HTTP::Get.new(uri) # => # + # req = Net::HTTP::Get.new(uri.hostname) # => # + # + # And with any of the subclasses: + # + # req = Net::HTTP::Head.new(uri) # => # + # req = Net::HTTP::Post.new(uri) # => # + # req = Net::HTTP::Put.new(uri) # => # + # # ... + # + # The new instance is suitable for use as the argument to Net::HTTP#request. + # + # ## Request Headers + # + # A new request object has these header fields by default: + # + # req.to_hash + # # => + # {"accept-encoding"=>["gzip;q=1.0,deflate;q=0.6,identity;q=0.3"], + # "accept"=>["*/*"], + # "user-agent"=>["Ruby"], + # "host"=>["jsonplaceholder.typicode.com"]} + # + # See: + # + # * [Request header + # Accept-Encoding](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields# + # Accept-Encoding) and [Compression and + # Decompression](rdoc-ref:Net::HTTP@Compression+and+Decompression). + # * [Request header + # Accept](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#accept-re + # quest-header). + # * [Request header + # User-Agent](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#user- + # agent-request-header). + # * [Request header + # Host](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#host-reques + # t-header). + # + # + # You can add headers or override default headers: + # + # # res = Net::HTTP::Get.new(uri, {'foo' => '0', 'bar' => '1'}) + # + # This class (and therefore its subclasses) also includes (indirectly) module + # Net::HTTPHeader, which gives access to its [methods for setting + # headers](rdoc-ref:Net::HTTPHeader@Setters). + # + # ## Request Subclasses # # Subclasses for HTTP requests: # @@ -2511,6 +3305,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Properties: # # * Request body: optional. @@ -2549,6 +3345,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Properties: # # * Request body: optional. @@ -2589,6 +3387,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Properties: # # * Request body: yes. @@ -2630,6 +3430,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Properties: # # * Request body: yes. @@ -2663,6 +3465,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Properties: # # * Request body: optional. @@ -2700,6 +3504,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Properties: # # * Request body: optional. @@ -2737,6 +3543,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Properties: # # * Request body: no. @@ -2777,6 +3585,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Properties: # # * Request body: yes. @@ -2813,6 +3623,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Related: # # * Net::HTTP#propfind: sends `PROPFIND` request, returns response object. @@ -2837,6 +3649,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Related: # # * Net::HTTP#proppatch: sends `PROPPATCH` request, returns response object. @@ -2861,6 +3675,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Related: # # * Net::HTTP#mkcol: sends `MKCOL` request, returns response object. @@ -2885,6 +3701,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Related: # # * Net::HTTP#copy: sends `COPY` request, returns response object. @@ -2909,6 +3727,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Related: # # * Net::HTTP#move: sends `MOVE` request, returns response object. @@ -2933,6 +3753,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Related: # # * Net::HTTP#lock: sends `LOCK` request, returns response object. @@ -2957,6 +3779,8 @@ module Net # http.request(req) # end # + # See [Request Headers](rdoc-ref:Net::HTTPRequest@Request+Headers). + # # Related: # # * Net::HTTP#unlock: sends `UNLOCK` request, returns response object. @@ -2970,7 +3794,7 @@ module Net end # - # This class is the base class for Net::HTTP request classes. + # This class is the base class for Net::HTTP response classes. # # ## About the Examples # @@ -2987,9 +3811,10 @@ module Net # # Some examples also assume these variables: # - # uri = URI('https://jsonplaceholder.typicode.com') + # uri = URI('https://jsonplaceholder.typicode.com/') # uri.freeze # Examples may not modify. # hostname = uri.hostname # => "jsonplaceholder.typicode.com" + # path = uri.path # => "/" # port = uri.port # => 443 # # So that example requests may be written as: @@ -3254,19 +4079,20 @@ module Net # rdoc-file=lib/net/http/response.rb # - body() # --> - # Returns the full entity body. + # Returns the string response body; note that repeated calls for the unmodified + # body return a cached string: # - # Calling this method a second or subsequent time will return the string already - # read. + # path = '/todos/1' + # Net::HTTP.start(hostname) do |http| + # res = http.get(path) + # p res.body + # p http.head(path).body # No body. + # end # - # http.request_get('/index.html') {|res| - # puts res.body - # } + # Output: # - # http.request_get('/index.html') {|res| - # p res.body.object_id # 538149362 - # p res.body.object_id # 538149362 - # } + # "{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false\n}" + # nil # def body: () -> String @@ -3274,8 +4100,7 @@ module Net # rdoc-file=lib/net/http/response.rb # - body=(value) # --> - # Because it may be necessary to modify the body, Eg, decompression this method - # facilitates that. + # Sets the body of the response to the given value. # def body=: (untyped value) -> void @@ -3387,6 +4212,9 @@ module Net # A `Continue` response indicates that the server has received the request # headers. # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # # References: # # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/100). @@ -3403,6 +4231,9 @@ module Net # The Switching Protocol response indicates that the server has received # a request to switch protocols, and has agreed to do so. # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # # References: # # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/101). @@ -3421,8 +4252,12 @@ module Net # The `Processing` response indicates that the server has received and is # processing the request, but no response is available yet. # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # # References: # + # * [RFC 2518](https://www.rfc-editor.org/rfc/rfc2518#section-10.1). # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#102). # class HTTPProcessing < HTTPInformation @@ -3436,9 +4271,13 @@ module Net # request, and contains certain headers; the final response is not available # yet. # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # # References: # # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/103). + # * [RFC 8297](https://www.rfc-editor.org/rfc/rfc8297.html#section-2). # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#103). # class HTTPEarlyHints < HTTPInformation @@ -3449,8 +4288,16 @@ module Net # Response class for `OK` responses (status code 200). # # The `OK` response indicates that the server has received a request and has - # responded successfully. See [200 - # OK](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#200). + # responded successfully. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200). + # * [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-200-ok). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#200). # class HTTPOK < HTTPSuccess HAS_BODY: bool @@ -3460,8 +4307,16 @@ module Net # Response class for `Created` responses (status code 201). # # The `Created` response indicates that the server has received and has - # fulfilled a request to create a new resource. See [201 - # Created](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#201). + # fulfilled a request to create a new resource. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/201). + # * [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-201-created). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#201). # class HTTPCreated < HTTPSuccess HAS_BODY: bool @@ -3471,8 +4326,16 @@ module Net # Response class for `Accepted` responses (status code 202). # # The `Accepted` response indicates that the server has received and is - # processing a request, but the processing has not yet been completed. See [202 - # Accepted](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#202). + # processing a request, but the processing has not yet been completed. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202). + # * [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-202-accepted). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#202). # class HTTPAccepted < HTTPSuccess HAS_BODY: bool @@ -3485,8 +4348,17 @@ module Net # The `Non-Authoritative Information` response indicates that the server is a # transforming proxy (such as a Web accelerator) that received a 200 OK response # from its origin, and is returning a modified version of the origin's response. - # See [203 Non-Authoritative - # Information](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#203). + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/203). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-203-non-authoritati + # ve-infor). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#203). # class HTTPNonAuthoritativeInformation < HTTPSuccess HAS_BODY: bool @@ -3496,8 +4368,17 @@ module Net # Response class for `No Content` responses (status code 204). # # The `No Content` response indicates that the server successfully processed the - # request, and is not returning any content. See [204 No - # Content](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#204). + # request, and is not returning any content. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-204-no-content). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#204). # class HTTPNoContent < HTTPSuccess HAS_BODY: bool @@ -3508,8 +4389,17 @@ module Net # # The `Reset Content` response indicates that the server successfully processed # the request, asks that the client reset its document view, and is not - # returning any content. See [205 Reset - # Content](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#205). + # returning any content. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/205). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-205-reset-content). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#205). # class HTTPResetContent < HTTPSuccess HAS_BODY: bool @@ -3519,9 +4409,18 @@ module Net # Response class for `Partial Content` responses (status code 206). # # The `Partial Content` response indicates that the server is delivering only - # part of the resource (byte serving) due to a Range header in the request. See - # [206 Partial - # Content](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#206). + # part of the resource (byte serving) due to a Range header in the request. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/206). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-206-partial-content + # ). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#206). # class HTTPPartialContent < HTTPSuccess HAS_BODY: bool @@ -3532,8 +4431,15 @@ module Net # # The `Multi-Status (WebDAV)` response indicates that the server has received # the request, and that the message body can contain a number of separate - # response codes. See [207 Multi-Status - # (WebDAV)](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#207). + # response codes. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [RFC 4818](https://www.rfc-editor.org/rfc/rfc4918#section-11.1). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#207). # class HTTPMultiStatus < HTTPSuccess HAS_BODY: bool @@ -3545,8 +4451,15 @@ module Net # The `Already Reported (WebDAV)` response indicates that the server has # received the request, and that the members of a DAV binding have already been # enumerated in a preceding part of the (multi-status) response, and are not - # being included again. See [208 Already Reported - # (WebDAV)](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#208). + # being included again. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [RFC 5842](https://www.rfc-editor.org/rfc/rfc5842.html#section-7.1). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#208). # class HTTPAlreadyReported < HTTPSuccess HAS_BODY: bool @@ -3557,8 +4470,15 @@ module Net # # The `IM Used` response indicates that the server has fulfilled a request for # the resource, and the response is a representation of the result of one or - # more instance-manipulations applied to the current instance. See [226 IM - # Used](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#226). + # more instance-manipulations applied to the current instance. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [RFC 3229](https://www.rfc-editor.org/rfc/rfc3229.html#section-10.4.1). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#226). # class HTTPIMUsed < HTTPSuccess HAS_BODY: bool @@ -3568,8 +4488,18 @@ module Net # Response class for `Multiple Choices` responses (status code 300). # # The `Multiple Choices` response indicates that the server offers multiple - # options for the resource from which the client may choose. See [300 Multiple - # Choices](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#300). + # options for the resource from which the client may choose. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/300). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-300-multiple-choice + # s). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#300). # class HTTPMultipleChoices < HTTPRedirection HAS_BODY: bool @@ -3579,8 +4509,18 @@ module Net # Response class for `Multiple Choices` responses (status code 300). # # The `Multiple Choices` response indicates that the server offers multiple - # options for the resource from which the client may choose. See [300 Multiple - # Choices](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#300). + # options for the resource from which the client may choose. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/300). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-300-multiple-choice + # s). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#300). # HTTPMultipleChoice: HTTPMultipleChoices @@ -3588,8 +4528,18 @@ module Net # Response class for `Moved Permanently` responses (status code 301). # # The `Moved Permanently` response indicates that links or records returning - # this response should be updated to use the given URL. See [301 Moved - # Permanently](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#301). + # this response should be updated to use the given URL. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/301). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-301-moved-permanent + # ly). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#301). # class HTTPMovedPermanently < HTTPRedirection HAS_BODY: bool @@ -3599,8 +4549,16 @@ module Net # Response class for `Found` responses (status code 302). # # The `Found` response indicates that the client should look at (browse to) - # another URL. See [302 - # Found](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#302). + # another URL. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302). + # * [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-302-found). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#302). # class HTTPFound < HTTPRedirection HAS_BODY: bool @@ -3610,8 +4568,17 @@ module Net # Response class for `See Other` responses (status code 303). # # The response to the request can be found under another URI using the GET - # method. See [303 See - # Other](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#303). + # method. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/303). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-303-see-other). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#303). # class HTTPSeeOther < HTTPRedirection HAS_BODY: bool @@ -3621,8 +4588,17 @@ module Net # Response class for `Not Modified` responses (status code 304). # # Indicates that the resource has not been modified since the version specified - # by the request headers. See [304 Not - # Modified](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#304). + # by the request headers. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-304-not-modified). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#304). # class HTTPNotModified < HTTPRedirection HAS_BODY: bool @@ -3632,8 +4608,16 @@ module Net # Response class for `Use Proxy` responses (status code 305). # # The requested resource is available only through a proxy, whose address is - # provided in the response. See [305 Use - # Proxy](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#305). + # provided in the response. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-305-use-proxy). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#305). # class HTTPUseProxy < HTTPRedirection HAS_BODY: bool @@ -3643,8 +4627,18 @@ module Net # Response class for `Temporary Redirect` responses (status code 307). # # The request should be repeated with another URI; however, future requests - # should still use the original URI. See [307 Temporary - # Redirect](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#307). + # should still use the original URI. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/307). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-307-temporary-redir + # ect). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#307). # class HTTPTemporaryRedirect < HTTPRedirection HAS_BODY: bool @@ -3653,9 +4647,18 @@ module Net # # Response class for `Permanent Redirect` responses (status code 308). # - # This and all future requests should be directed to the given URI. See [308 - # Permanent - # Redirect](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#308). + # This and all future requests should be directed to the given URI. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/308). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-308-permanent-redir + # ect). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#308). # class HTTPPermanentRedirect < HTTPRedirection HAS_BODY: bool @@ -3665,8 +4668,17 @@ module Net # Response class for `Bad Request` responses (status code 400). # # The server cannot or will not process the request due to an apparent client - # error. See [400 Bad - # Request](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#400). + # error. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-400-bad-request). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#400). # class HTTPBadRequest < HTTPClientError HAS_BODY: bool @@ -3675,8 +4687,17 @@ module Net # # Response class for `Unauthorized` responses (status code 401). # - # Authentication is required, but either was not provided or failed. See [401 - # Unauthorized](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#401). + # Authentication is required, but either was not provided or failed. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-401-unauthorized). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#401). # class HTTPUnauthorized < HTTPClientError HAS_BODY: bool @@ -3685,8 +4706,18 @@ module Net # # Response class for `Payment Required` responses (status code 402). # - # Reserved for future use. See [402 Payment - # Required](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#402). + # Reserved for future use. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/402). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-402-payment-require + # d). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#402). # class HTTPPaymentRequired < HTTPClientError HAS_BODY: bool @@ -3696,8 +4727,17 @@ module Net # Response class for `Forbidden` responses (status code 403). # # The request contained valid data and was understood by the server, but the - # server is refusing action. See [403 - # Forbidden](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#403). + # server is refusing action. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-403-forbidden). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#403). # class HTTPForbidden < HTTPClientError HAS_BODY: bool @@ -3707,8 +4747,16 @@ module Net # Response class for `Not Found` responses (status code 404). # # The requested resource could not be found but may be available in the future. - # See [404 Not - # Found](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#404). + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-404-not-found). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#404). # class HTTPNotFound < HTTPClientError HAS_BODY: bool @@ -3717,9 +4765,18 @@ module Net # # Response class for `Method Not Allowed` responses (status code 405). # - # The request method is not supported for the requested resource. See [405 - # Method Not - # Allowed](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#405). + # The request method is not supported for the requested resource. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-405-method-not-allo + # wed). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#405). # class HTTPMethodNotAllowed < HTTPClientError HAS_BODY: bool @@ -3729,8 +4786,18 @@ module Net # Response class for `Not Acceptable` responses (status code 406). # # The requested resource is capable of generating only content that not - # acceptable according to the Accept headers sent in the request. See [406 Not - # Acceptable](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#406). + # acceptable according to the Accept headers sent in the request. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/406). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-406-not-acceptable) + # . + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#406). # class HTTPNotAcceptable < HTTPClientError HAS_BODY: bool @@ -3740,9 +4807,18 @@ module Net # Response class for `Proxy Authentication Required` responses (status code # 407). # - # The client must first authenticate itself with the proxy. See [407 Proxy - # Authentication - # Required](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#407). + # The client must first authenticate itself with the proxy. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/407). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-407-proxy-authentic + # ation-re). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#407). # class HTTPProxyAuthenticationRequired < HTTPClientError HAS_BODY: bool @@ -3751,8 +4827,18 @@ module Net # # Response class for `Request Timeout` responses (status code 408). # - # The server timed out waiting for the request. See [408 Request - # Timeout](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#408). + # The server timed out waiting for the request. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-408-request-timeout + # ). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#408). # class HTTPRequestTimeout < HTTPClientError HAS_BODY: bool @@ -3762,8 +4848,16 @@ module Net # Response class for `Conflict` responses (status code 409). # # The request could not be processed because of conflict in the current state of - # the resource. See [409 - # Conflict](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#409). + # the resource. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/409). + # * [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-409-conflict). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#409). # class HTTPConflict < HTTPClientError HAS_BODY: bool @@ -3773,8 +4867,16 @@ module Net # Response class for `Gone` responses (status code 410). # # The resource requested was previously in use but is no longer available and - # will not be available again. See [410 - # Gone](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#410). + # will not be available again. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/410). + # * [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-410-gone). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#410). # class HTTPGone < HTTPClientError HAS_BODY: bool @@ -3784,8 +4886,18 @@ module Net # Response class for `Length Required` responses (status code 411). # # The request did not specify the length of its content, which is required by - # the requested resource. See [411 Length - # Required](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#411). + # the requested resource. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/411). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-411-length-required + # ). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#411). # class HTTPLengthRequired < HTTPClientError HAS_BODY: bool @@ -3795,8 +4907,18 @@ module Net # Response class for `Precondition Failed` responses (status code 412). # # The server does not meet one of the preconditions specified in the request - # headers. See [412 Precondition - # Failed](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#412). + # headers. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/412). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-412-precondition-fa + # iled). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#412). # class HTTPPreconditionFailed < HTTPClientError HAS_BODY: bool @@ -3805,9 +4927,18 @@ module Net # # Response class for `Payload Too Large` responses (status code 413). # - # The request is larger than the server is willing or able to process. See [413 - # Payload Too - # Large](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#413). + # The request is larger than the server is willing or able to process. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/413). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-413-content-too-lar + # ge). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#413). # class HTTPPayloadTooLarge < HTTPClientError HAS_BODY: bool @@ -3816,8 +4947,17 @@ module Net # # Response class for `URI Too Long` responses (status code 414). # - # The URI provided was too long for the server to process. See [414 URI Too - # Long](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#414). + # The URI provided was too long for the server to process. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/414). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-414-uri-too-long). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#414). # class HTTPURITooLong < HTTPClientError HAS_BODY: bool @@ -3827,8 +4967,18 @@ module Net # Response class for `Unsupported Media Type` responses (status code 415). # # The request entity has a media type which the server or resource does not - # support. See [415 Unsupported Media - # Type](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#415). + # support. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/415). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-415-unsupported-med + # ia-type). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#415). # class HTTPUnsupportedMediaType < HTTPClientError HAS_BODY: bool @@ -3838,8 +4988,18 @@ module Net # Response class for `Range Not Satisfiable` responses (status code 416). # # The request entity has a media type which the server or resource does not - # support. See [416 Range Not - # Satisfiable](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#416). + # support. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/416). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-416-range-not-satis + # fiable). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#416). # class HTTPRangeNotSatisfiable < HTTPClientError HAS_BODY: bool @@ -3849,8 +5009,17 @@ module Net # Response class for `Expectation Failed` responses (status code 417). # # The server cannot meet the requirements of the Expect request-header field. - # See [417 Expectation - # Failed](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#417). + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/417). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-417-expectation-fai + # led). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#417). # class HTTPExpectationFailed < HTTPClientError HAS_BODY: bool @@ -3860,8 +5029,16 @@ module Net # Response class for `Misdirected Request` responses (status code 421). # # The request was directed at a server that is not able to produce a response. - # See [421 Misdirected - # Request](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#421). + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-421-misdirected-req + # uest). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#421). # class HTTPMisdirectedRequest < HTTPClientError HAS_BODY: bool @@ -3870,8 +5047,18 @@ module Net # # Response class for `Unprocessable Entity` responses (status code 422). # - # The request was well-formed but had semantic errors. See [422 Unprocessable - # Entity](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#422). + # The request was well-formed but had semantic errors. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-422-unprocessable-c + # ontent). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#422). # class HTTPUnprocessableEntity < HTTPClientError HAS_BODY: bool @@ -3880,8 +5067,15 @@ module Net # # Response class for `Locked (WebDAV)` responses (status code 423). # - # The requested resource is locked. See [423 Locked - # (WebDAV)](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#423). + # The requested resource is locked. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [RFC 4918](https://www.rfc-editor.org/rfc/rfc4918#section-11.3). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#423). # class HTTPLocked < HTTPClientError HAS_BODY: bool @@ -3894,6 +5088,14 @@ module Net # failed. See [424 Failed Dependency # (WebDAV)](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#424). # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [RFC 4918](https://www.rfc-editor.org/rfc/rfc4918#section-11.4). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#424). + # class HTTPFailedDependency < HTTPClientError HAS_BODY: bool end @@ -3902,8 +5104,17 @@ module Net # Response class for `Upgrade Required` responses (status code 426). # # The client should switch to the protocol given in the Upgrade header field. - # See [426 Upgrade - # Required](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#426). + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/426). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-426-upgrade-require + # d). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#426). # class HTTPUpgradeRequired < HTTPClientError HAS_BODY: bool @@ -3912,9 +5123,16 @@ module Net # # Response class for `Precondition Required` responses (status code 428). # - # The origin server requires the request to be conditional. See [428 - # Precondition - # Required](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#428). + # The origin server requires the request to be conditional. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/428). + # * [RFC 6585](https://www.rfc-editor.org/rfc/rfc6585#section-3). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#428). # class HTTPPreconditionRequired < HTTPClientError HAS_BODY: bool @@ -3923,8 +5141,16 @@ module Net # # Response class for `Too Many Requests` responses (status code 429). # - # The user has sent too many requests in a given amount of time. See [429 Too - # Many Requests](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#429). + # The user has sent too many requests in a given amount of time. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429). + # * [RFC 6585](https://www.rfc-editor.org/rfc/rfc6585#section-4). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#429). # class HTTPTooManyRequests < HTTPClientError HAS_BODY: bool @@ -3935,8 +5161,16 @@ module Net # 431). # # An individual header field is too large, or all the header fields - # collectively, are too large. See [431 Request Header Fields Too - # Large](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#431). + # collectively, are too large. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/431). + # * [RFC 6585](https://www.rfc-editor.org/rfc/rfc6585#section-5). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#431). # class HTTPRequestHeaderFieldsTooLarge < HTTPClientError HAS_BODY: bool @@ -3947,9 +5181,16 @@ module Net # 451). # # A server operator has received a legal demand to deny access to a resource or - # to a set of resources that includes the requested resource. See [451 - # Unavailable For Legal - # Reasons](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#451). + # to a set of resources that includes the requested resource. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/451). + # * [RFC 7725](https://www.rfc-editor.org/rfc/rfc7725.html#section-3). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#451). # class HTTPUnavailableForLegalReasons < HTTPClientError HAS_BODY: bool @@ -3959,8 +5200,18 @@ module Net # Response class for `Internal Server Error` responses (status code 500). # # An unexpected condition was encountered and no more specific message is - # suitable. See [500 Internal Server - # Error](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#500). + # suitable. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-500-internal-server + # -error). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#500). # class HTTPInternalServerError < HTTPServerError HAS_BODY: bool @@ -3970,8 +5221,18 @@ module Net # Response class for `Not Implemented` responses (status code 501). # # The server either does not recognize the request method, or it lacks the - # ability to fulfil the request. See [501 Not - # Implemented](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#501). + # ability to fulfil the request. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/501). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-501-not-implemented + # ). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#501). # class HTTPNotImplemented < HTTPServerError HAS_BODY: bool @@ -3981,8 +5242,17 @@ module Net # Response class for `Bad Gateway` responses (status code 502). # # The server was acting as a gateway or proxy and received an invalid response - # from the upstream server. See [502 Bad - # Gateway](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#502). + # from the upstream server. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-502-bad-gateway). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#502). # class HTTPBadGateway < HTTPServerError HAS_BODY: bool @@ -3992,8 +5262,18 @@ module Net # Response class for `Service Unavailable` responses (status code 503). # # The server cannot handle the request (because it is overloaded or down for - # maintenance). See [503 Service - # Unavailable](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#503). + # maintenance). + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-503-service-unavail + # able). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#503). # class HTTPServiceUnavailable < HTTPServerError HAS_BODY: bool @@ -4003,8 +5283,18 @@ module Net # Response class for `Gateway Timeout` responses (status code 504). # # The server was acting as a gateway or proxy and did not receive a timely - # response from the upstream server. See [504 Gateway - # Timeout](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#504). + # response from the upstream server. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-504-gateway-timeout + # ). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#504). # class HTTPGatewayTimeout < HTTPServerError HAS_BODY: bool @@ -4013,9 +5303,18 @@ module Net # # Response class for `HTTP Version Not Supported` responses (status code 505). # - # The server does not support the HTTP version used in the request. See [505 - # HTTP Version Not - # Supported](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#505). + # The server does not support the HTTP version used in the request. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/505). + # * [RFC + # 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-505-http-version-no + # t-suppor). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#505). # class HTTPVersionNotSupported < HTTPServerError HAS_BODY: bool @@ -4025,8 +5324,16 @@ module Net # Response class for `Variant Also Negotiates` responses (status code 506). # # Transparent content negotiation for the request results in a circular - # reference. See [506 Variant Also - # Negotiates](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#506). + # reference. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/506). + # * [RFC 2295](https://www.rfc-editor.org/rfc/rfc2295#section-8.1). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#506). # class HTTPVariantAlsoNegotiates < HTTPServerError HAS_BODY: bool @@ -4037,8 +5344,16 @@ module Net # 507). # # The server is unable to store the representation needed to complete the - # request. See [507 Insufficient Storage - # (WebDAV)](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#507). + # request. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/507). + # * [RFC 4918](https://www.rfc-editor.org/rfc/rfc4918#section-11.5). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#507). # class HTTPInsufficientStorage < HTTPServerError HAS_BODY: bool @@ -4047,9 +5362,16 @@ module Net # # Response class for `Loop Detected (WebDAV)` responses (status code 508). # - # The server detected an infinite loop while processing the request. See [508 - # Loop Detected - # (WebDAV)](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#508). + # The server detected an infinite loop while processing the request. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/508). + # * [RFC 5942](https://www.rfc-editor.org/rfc/rfc5842.html#section-7.2). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#508). # class HTTPLoopDetected < HTTPServerError HAS_BODY: bool @@ -4059,8 +5381,15 @@ module Net # Response class for `Not Extended` responses (status code 510). # # Further extensions to the request are required for the server to fulfill it. - # See [510 Not - # Extended](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#510). + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/510). + # * [RFC 2774](https://www.rfc-editor.org/rfc/rfc2774.html#section-7). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#510). # class HTTPNotExtended < HTTPServerError HAS_BODY: bool @@ -4070,16 +5399,23 @@ module Net # Response class for `Network Authentication Required` responses (status code # 511). # - # The client needs to authenticate to gain network access. See [511 Network - # Authentication - # Required](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#511). + # The client needs to authenticate to gain network access. + # + # This class also includes (indirectly) module Net::HTTPHeader, which gives + # access to its [methods for getting headers](rdoc-ref:Net::HTTPHeader@Getters). + # + # References: + # + # * [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/511). + # * [RFC 6585](https://www.rfc-editor.org/rfc/rfc6585#section-6). + # * [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#511). # class HTTPNetworkAuthenticationRequired < HTTPServerError HAS_BODY: bool end # - # This class is the base class for Net::HTTP request classes. + # This class is the base class for Net::HTTP response classes. # # ## About the Examples # @@ -4096,9 +5432,10 @@ module Net # # Some examples also assume these variables: # - # uri = URI('https://jsonplaceholder.typicode.com') + # uri = URI('https://jsonplaceholder.typicode.com/') # uri.freeze # Examples may not modify. # hostname = uri.hostname # => "jsonplaceholder.typicode.com" + # path = uri.path # => "/" # port = uri.port # => 443 # # So that example requests may be written as: diff --git a/stdlib/objspace/0/objspace.rbs b/stdlib/objspace/0/objspace.rbs index d0ab10267..72216b082 100644 --- a/stdlib/objspace/0/objspace.rbs +++ b/stdlib/objspace/0/objspace.rbs @@ -4,9 +4,9 @@ # # You need to `require 'objspace'` to use this extension module. # -# Generally, you *SHOULD NOT* use this library if you do not know about the MRI -# implementation. Mainly, this library is for (memory) profiler developers and -# MRI developers who need to know about MRI memory usage. +# Generally, you **SHOULD** **NOT** use this library if you do not know about +# the MRI implementation. Mainly, this library is for (memory) profiler +# developers and MRI developers who need to know about MRI memory usage. # %a{annotate:rdoc:source:from=ext/objspace} module ObjectSpace @@ -233,12 +233,20 @@ module ObjectSpace # # Dump the contents of a ruby object as JSON. # + # *output* can be one of: `:stdout`, `:file`, `:string`, or IO object. + # + # * `:file` means dumping to a tempfile and returning corresponding File + # object; + # * `:stdout` means printing the dump and returning `nil`; + # * `:string` means returning a string with the dump; + # * if an instance of IO object is provided, the output goes there, and the + # object is returned. + # + # # This method is only expected to work with C Ruby. This is an experimental # method and is subject to change. In particular, the function signature and # output format are not guaranteed to be compatible in future versions of ruby. @@ -247,16 +255,14 @@ module ObjectSpace # # Dump the contents of the ruby heap as JSON. # - # *full* must be a boolean. If true all heap slots are dumped including the - # empty ones (T_NONE). + # *output* argument is the same as for #dump. + # + # *full* must be a boolean. If true, all heap slots are dumped including the + # empty ones (`T_NONE`). # # *since* must be a non-negative integer or `nil`. # diff --git a/stdlib/openssl/0/openssl.rbs b/stdlib/openssl/0/openssl.rbs index 2d805591c..8a5693501 100644 --- a/stdlib/openssl/0/openssl.rbs +++ b/stdlib/openssl/0/openssl.rbs @@ -20,23 +20,21 @@ # # key = OpenSSL::PKey::RSA.new 2048 # -# open 'private_key.pem', 'w' do |io| io.write key.to_pem end -# open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end +# File.write 'private_key.pem', key.private_to_pem +# File.write 'public_key.pem', key.public_to_pem # # ### Exporting a Key # # Keys saved to disk without encryption are not secure as anyone who gets ahold # of the key may use it unless it is encrypted. In order to securely export a -# key you may export it with a pass phrase. +# key you may export it with a password. # # cipher = OpenSSL::Cipher.new 'aes-256-cbc' -# pass_phrase = 'my secure pass phrase goes here' +# password = 'my secure password goes here' # -# key_secure = key.export cipher, pass_phrase +# key_secure = key.private_to_pem cipher, password # -# open 'private.secure.pem', 'w' do |io| -# io.write key_secure -# end +# File.write 'private.secure.pem', key_secure # # OpenSSL::Cipher.ciphers returns a list of available ciphers. # @@ -56,13 +54,13 @@ # # ### Loading an Encrypted Key # -# OpenSSL will prompt you for your pass phrase when loading an encrypted key. If -# you will not be able to type in the pass phrase you may provide it when -# loading the key: +# OpenSSL will prompt you for your password when loading an encrypted key. If +# you will not be able to type in the password you may provide it when loading +# the key: # # key4_pem = File.read 'private.secure.pem' -# pass_phrase = 'my secure pass phrase goes here' -# key4 = OpenSSL::PKey.read key4_pem, pass_phrase +# password = 'my secure password goes here' +# key4 = OpenSSL::PKey.read key4_pem, password # # ## RSA Encryption # @@ -175,44 +173,6 @@ # decrypted = cipher.update encrypted # decrypted << cipher.final # -# ## PKCS #5 Password-based Encryption -# -# PKCS #5 is a password-based encryption standard documented at -# [RFC2898](http://www.ietf.org/rfc/rfc2898.txt). It allows a short password or -# passphrase to be used to create a secure encryption key. If possible, PBKDF2 -# as described above should be used if the circumstances allow it. -# -# PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption key. -# -# pass_phrase = 'my secure pass phrase goes here' -# salt = '8 octets' -# -# ### Encryption -# -# First set up the cipher for encryption -# -# encryptor = OpenSSL::Cipher.new 'aes-256-cbc' -# encryptor.encrypt -# encryptor.pkcs5_keyivgen pass_phrase, salt -# -# Then pass the data you want to encrypt through -# -# encrypted = encryptor.update 'top secret document' -# encrypted << encryptor.final -# -# ### Decryption -# -# Use a new Cipher instance set up for decryption -# -# decryptor = OpenSSL::Cipher.new 'aes-256-cbc' -# decryptor.decrypt -# decryptor.pkcs5_keyivgen pass_phrase, salt -# -# Then pass the data you want to decrypt through -# -# plain = decryptor.update encrypted -# plain << decryptor.final -# # ## X509 Certificates # # ### Creating a Certificate @@ -290,12 +250,12 @@ # not readable by other users. # # ca_key = OpenSSL::PKey::RSA.new 2048 -# pass_phrase = 'my secure pass phrase goes here' +# password = 'my secure password goes here' # -# cipher = OpenSSL::Cipher.new 'aes-256-cbc' +# cipher = 'aes-256-cbc' # # open 'ca_key.pem', 'w', 0400 do |io| -# io.write ca_key.export(cipher, pass_phrase) +# io.write ca_key.private_to_pem(cipher, password) # end # # ### CA Certificate @@ -584,7 +544,18 @@ module OpenSSL OPENSSL_VERSION: String # - # Version number of OpenSSL the ruby OpenSSL extension was built with (base 16) + # Version number of OpenSSL the ruby OpenSSL extension was built with (base 16). + # The formats are below. + # + # OpenSSL 3 + # : `0xMNN00PP0 (major minor 00 patch 0)` + # OpenSSL before 3 + # : `0xMNNFFPPS (major minor fix patch status)` + # LibreSSL + # : `0x20000000 (fixed value)` + # + # + # See also the man page OPENSSL_VERSION_NUMBER(3). # OPENSSL_VERSION_NUMBER: Integer @@ -3221,14 +3192,10 @@ module OpenSSL # Return the hash value computed with *name* Digest. *name* is either the long # name or short name of a supported digest algorithm. # - # ### Examples + # ### Example # # OpenSSL::Digest.digest("SHA256", "abc") # - # which is equivalent to: - # - # OpenSSL::Digest.digest('SHA256', "abc") - # def self.digest: (String name, String data) -> String public @@ -3998,7 +3965,7 @@ module OpenSSL # # ### Parameters # pass - # : The passphrase. + # : The password. # salt # : The salt. Salts prevent attacks based on dictionaries of common passwords # and attacks based on rainbow tables. It is a public value that can be @@ -4312,7 +4279,7 @@ module OpenSSL # require 'net/http' # # http_response = - # Net::HTTP.start ocsp_uri.hostname, ocsp.port do |http| + # Net::HTTP.start ocsp_uri.hostname, ocsp_uri.port do |http| # http.post ocsp_uri.path, request.to_der, # 'content-type' => 'application/ocsp-request' # end @@ -5637,9 +5604,20 @@ module OpenSSL # - dh.to_pem -> aString # - dh.to_s -> aString # --> - # Encodes this DH to its PEM encoding. Note that any existing per-session - # public/private keys will **not** get encoded, just the Diffie-Hellman - # parameters will be encoded. + # Serializes the DH parameters to a PEM-encoding. + # + # Note that any existing per-session public/private keys will **not** get + # encoded, just the Diffie-Hellman parameters will be encoded. + # + # PEM-encoded parameters will look like: + # + # -----BEGIN DH PARAMETERS----- + # [...] + # -----END DH PARAMETERS----- + # + # See also #public_to_pem (X.509 SubjectPublicKeyInfo) and #private_to_pem (PKCS + # #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for serialization with the + # private or public key components. # def export: () -> String @@ -5765,23 +5743,50 @@ module OpenSSL # rdoc-file=ext/openssl/ossl_pkey_dh.c # - dh.to_der -> aString # --> - # Encodes this DH to its DER encoding. Note that any existing per-session - # public/private keys will **not** get encoded, just the Diffie-Hellman - # parameters will be encoded. + # Serializes the DH parameters to a DER-encoding + # + # Note that any existing per-session public/private keys will **not** get + # encoded, just the Diffie-Hellman parameters will be encoded. + # + # See also #public_to_der (X.509 SubjectPublicKeyInfo) and #private_to_der (PKCS + # #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for serialization with the + # private or public key components. # def to_der: () -> String # - # Encodes this DH to its PEM encoding. Note that any existing per-session - # public/private keys will **not** get encoded, just the Diffie-Hellman - # parameters will be encoded. + # Serializes the DH parameters to a PEM-encoding. + # + # Note that any existing per-session public/private keys will **not** get + # encoded, just the Diffie-Hellman parameters will be encoded. + # + # PEM-encoded parameters will look like: + # + # -----BEGIN DH PARAMETERS----- + # [...] + # -----END DH PARAMETERS----- + # + # See also #public_to_pem (X.509 SubjectPublicKeyInfo) and #private_to_pem (PKCS + # #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for serialization with the + # private or public key components. # alias to_pem export # - # Encodes this DH to its PEM encoding. Note that any existing per-session - # public/private keys will **not** get encoded, just the Diffie-Hellman - # parameters will be encoded. + # Serializes the DH parameters to a PEM-encoding. + # + # Note that any existing per-session public/private keys will **not** get + # encoded, just the Diffie-Hellman parameters will be encoded. + # + # PEM-encoded parameters will look like: + # + # -----BEGIN DH PARAMETERS----- + # [...] + # -----END DH PARAMETERS----- + # + # See also #public_to_pem (X.509 SubjectPublicKeyInfo) and #private_to_pem (PKCS + # #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for serialization with the + # private or public key components. # alias to_s export @@ -5885,16 +5890,54 @@ module OpenSSL # - dsa.to_pem([cipher, password]) -> aString # - dsa.to_s([cipher, password]) -> aString # --> - # Encodes this DSA to its PEM encoding. + # Serializes a private or public key to a PEM-encoding. # - # ### Parameters - # * *cipher* is an OpenSSL::Cipher. - # * *password* is a string containing your password. + # When the key contains public components only + # : Serializes it into an X.509 SubjectPublicKeyInfo. The parameters *cipher* + # and *password* are ignored. # + # A PEM-encoded key will look like: # - # ### Examples - # DSA.to_pem -> aString - # DSA.to_pem(cipher, 'mypassword') -> aString + # -----BEGIN PUBLIC KEY----- + # [...] + # -----END PUBLIC KEY----- + # + # Consider using #public_to_pem instead. This serializes the key into an + # X.509 SubjectPublicKeyInfo regardless of whether it is a public key or a + # private key. + # + # When the key contains private components, and no parameters are given + # : Serializes it into a traditional OpenSSL DSAPrivateKey. + # + # A PEM-encoded key will look like: + # + # -----BEGIN DSA PRIVATE KEY----- + # [...] + # -----END DSA PRIVATE KEY----- + # + # When the key contains private components, and *cipher* and *password* are given + # : Serializes it into a traditional OpenSSL DSAPrivateKey and encrypts it in + # OpenSSL's traditional PEM encryption format. *cipher* must be a cipher + # name understood by OpenSSL::Cipher.new or an instance of OpenSSL::Cipher. + # + # An encrypted PEM-encoded key will look like: + # + # -----BEGIN DSA PRIVATE KEY----- + # Proc-Type: 4,ENCRYPTED + # DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + # + # [...] + # -----END DSA PRIVATE KEY----- + # + # Note that this format uses MD5 to derive the encryption key, and hence + # will not be available on FIPS-compliant systems. + # + # + # **This method is kept for compatibility.** This should only be used when the + # traditional, non-standard OpenSSL format is required. + # + # Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + # (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. # def export: (String cipher, String password) -> String | () -> String @@ -6018,35 +6061,118 @@ module OpenSSL # rdoc-file=ext/openssl/ossl_pkey_dsa.c # - dsa.to_der -> aString # --> - # Encodes this DSA to its DER encoding. + # Serializes a private or public key to a DER-encoding. + # + # See #to_pem for details. + # + # **This method is kept for compatibility.** This should only be used when the + # traditional, non-standard OpenSSL format is required. + # + # Consider using #public_to_der or #private_to_der instead. # def to_der: () -> String # - # Encodes this DSA to its PEM encoding. + # Serializes a private or public key to a PEM-encoding. # - # ### Parameters - # * *cipher* is an OpenSSL::Cipher. - # * *password* is a string containing your password. + # When the key contains public components only + # : Serializes it into an X.509 SubjectPublicKeyInfo. The parameters *cipher* + # and *password* are ignored. # + # A PEM-encoded key will look like: # - # ### Examples - # DSA.to_pem -> aString - # DSA.to_pem(cipher, 'mypassword') -> aString + # -----BEGIN PUBLIC KEY----- + # [...] + # -----END PUBLIC KEY----- + # + # Consider using #public_to_pem instead. This serializes the key into an + # X.509 SubjectPublicKeyInfo regardless of whether it is a public key or a + # private key. + # + # When the key contains private components, and no parameters are given + # : Serializes it into a traditional OpenSSL DSAPrivateKey. + # + # A PEM-encoded key will look like: + # + # -----BEGIN DSA PRIVATE KEY----- + # [...] + # -----END DSA PRIVATE KEY----- + # + # When the key contains private components, and *cipher* and *password* are given + # : Serializes it into a traditional OpenSSL DSAPrivateKey and encrypts it in + # OpenSSL's traditional PEM encryption format. *cipher* must be a cipher + # name understood by OpenSSL::Cipher.new or an instance of OpenSSL::Cipher. + # + # An encrypted PEM-encoded key will look like: + # + # -----BEGIN DSA PRIVATE KEY----- + # Proc-Type: 4,ENCRYPTED + # DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + # + # [...] + # -----END DSA PRIVATE KEY----- + # + # Note that this format uses MD5 to derive the encryption key, and hence + # will not be available on FIPS-compliant systems. + # + # + # **This method is kept for compatibility.** This should only be used when the + # traditional, non-standard OpenSSL format is required. + # + # Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + # (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. # alias to_pem export # - # Encodes this DSA to its PEM encoding. + # Serializes a private or public key to a PEM-encoding. # - # ### Parameters - # * *cipher* is an OpenSSL::Cipher. - # * *password* is a string containing your password. + # When the key contains public components only + # : Serializes it into an X.509 SubjectPublicKeyInfo. The parameters *cipher* + # and *password* are ignored. # + # A PEM-encoded key will look like: # - # ### Examples - # DSA.to_pem -> aString - # DSA.to_pem(cipher, 'mypassword') -> aString + # -----BEGIN PUBLIC KEY----- + # [...] + # -----END PUBLIC KEY----- + # + # Consider using #public_to_pem instead. This serializes the key into an + # X.509 SubjectPublicKeyInfo regardless of whether it is a public key or a + # private key. + # + # When the key contains private components, and no parameters are given + # : Serializes it into a traditional OpenSSL DSAPrivateKey. + # + # A PEM-encoded key will look like: + # + # -----BEGIN DSA PRIVATE KEY----- + # [...] + # -----END DSA PRIVATE KEY----- + # + # When the key contains private components, and *cipher* and *password* are given + # : Serializes it into a traditional OpenSSL DSAPrivateKey and encrypts it in + # OpenSSL's traditional PEM encryption format. *cipher* must be a cipher + # name understood by OpenSSL::Cipher.new or an instance of OpenSSL::Cipher. + # + # An encrypted PEM-encoded key will look like: + # + # -----BEGIN DSA PRIVATE KEY----- + # Proc-Type: 4,ENCRYPTED + # DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + # + # [...] + # -----END DSA PRIVATE KEY----- + # + # Note that this format uses MD5 to derive the encryption key, and hence + # will not be available on FIPS-compliant systems. + # + # + # **This method is kept for compatibility.** This should only be used when the + # traditional, non-standard OpenSSL format is required. + # + # Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + # (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. # alias to_s export @@ -6197,13 +6323,57 @@ module OpenSSL # - # Outputs the EC key in PEM encoding. If *cipher* and *pass_phrase* are given - # they will be used to encrypt the key. *cipher* must be an OpenSSL::Cipher - # instance. Note that encryption will only be effective for a private key, - # public keys will always be encoded in plain text. + # Serializes a private or public key to a PEM-encoding. + # + # When the key contains public components only + # : Serializes it into an X.509 SubjectPublicKeyInfo. The parameters *cipher* + # and *password* are ignored. + # + # A PEM-encoded key will look like: + # + # -----BEGIN PUBLIC KEY----- + # [...] + # -----END PUBLIC KEY----- + # + # Consider using #public_to_pem instead. This serializes the key into an + # X.509 SubjectPublicKeyInfo regardless of whether it is a public key or a + # private key. + # + # When the key contains private components, and no parameters are given + # : Serializes it into a SEC 1/RFC 5915 ECPrivateKey. + # + # A PEM-encoded key will look like: + # + # -----BEGIN EC PRIVATE KEY----- + # [...] + # -----END EC PRIVATE KEY----- + # + # When the key contains private components, and *cipher* and *password* are given + # : Serializes it into a SEC 1/RFC 5915 ECPrivateKey and encrypts it in + # OpenSSL's traditional PEM encryption format. *cipher* must be a cipher + # name understood by OpenSSL::Cipher.new or an instance of OpenSSL::Cipher. + # + # An encrypted PEM-encoded key will look like: + # + # -----BEGIN EC PRIVATE KEY----- + # Proc-Type: 4,ENCRYPTED + # DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + # + # [...] + # -----END EC PRIVATE KEY----- + # + # Note that this format uses MD5 to derive the encryption key, and hence + # will not be available on FIPS-compliant systems. + # + # + # **This method is kept for compatibility.** This should only be used when the + # SEC 1/RFC 5915 ECPrivateKey format is required. + # + # Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + # (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. # def export: (String cipher, String password) -> String | () -> String @@ -6321,15 +6491,66 @@ module OpenSSL # rdoc-file=ext/openssl/ossl_pkey_ec.c # - key.to_der => String # --> - # See the OpenSSL documentation for i2d_ECPrivateKey_bio() + # Serializes a private or public key to a DER-encoding. + # + # See #to_pem for details. + # + # **This method is kept for compatibility.** This should only be used when the + # SEC 1/RFC 5915 ECPrivateKey format is required. + # + # Consider using #public_to_der or #private_to_der instead. # def to_der: () -> String # - # Outputs the EC key in PEM encoding. If *cipher* and *pass_phrase* are given - # they will be used to encrypt the key. *cipher* must be an OpenSSL::Cipher - # instance. Note that encryption will only be effective for a private key, - # public keys will always be encoded in plain text. + # Serializes a private or public key to a PEM-encoding. + # + # When the key contains public components only + # : Serializes it into an X.509 SubjectPublicKeyInfo. The parameters *cipher* + # and *password* are ignored. + # + # A PEM-encoded key will look like: + # + # -----BEGIN PUBLIC KEY----- + # [...] + # -----END PUBLIC KEY----- + # + # Consider using #public_to_pem instead. This serializes the key into an + # X.509 SubjectPublicKeyInfo regardless of whether it is a public key or a + # private key. + # + # When the key contains private components, and no parameters are given + # : Serializes it into a SEC 1/RFC 5915 ECPrivateKey. + # + # A PEM-encoded key will look like: + # + # -----BEGIN EC PRIVATE KEY----- + # [...] + # -----END EC PRIVATE KEY----- + # + # When the key contains private components, and *cipher* and *password* are given + # : Serializes it into a SEC 1/RFC 5915 ECPrivateKey and encrypts it in + # OpenSSL's traditional PEM encryption format. *cipher* must be a cipher + # name understood by OpenSSL::Cipher.new or an instance of OpenSSL::Cipher. + # + # An encrypted PEM-encoded key will look like: + # + # -----BEGIN EC PRIVATE KEY----- + # Proc-Type: 4,ENCRYPTED + # DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + # + # [...] + # -----END EC PRIVATE KEY----- + # + # Note that this format uses MD5 to derive the encryption key, and hence + # will not be available on FIPS-compliant systems. + # + # + # **This method is kept for compatibility.** This should only be used when the + # SEC 1/RFC 5915 ECPrivateKey format is required. + # + # Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + # (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. # alias to_pem export @@ -6771,6 +6992,18 @@ module OpenSSL # Serializes the private key to PEM-encoded PKCS #8 format. See #private_to_der # for more details. # + # An unencrypted PEM-encoded key will look like: + # + # -----BEGIN PRIVATE KEY----- + # [...] + # -----END PRIVATE KEY----- + # + # An encrypted PEM-encoded key will look like: + # + # -----BEGIN ENCRYPTED PRIVATE KEY----- + # [...] + # -----END ENCRYPTED PRIVATE KEY----- + # def private_to_pem: (String cipher, String password) -> String | () -> String @@ -6788,6 +7021,12 @@ module OpenSSL # --> # Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format. # + # A PEM-encoded key will look like: + # + # -----BEGIN PUBLIC KEY----- + # [...] + # -----END PUBLIC KEY----- + # def public_to_pem: () -> String # - # Outputs this keypair in PEM encoding. If *cipher* and *pass_phrase* are given - # they will be used to encrypt the key. *cipher* must be an OpenSSL::Cipher - # instance. + # Serializes a private or public key to a PEM-encoding. + # + # When the key contains public components only + # : Serializes it into an X.509 SubjectPublicKeyInfo. The parameters *cipher* + # and *password* are ignored. + # + # A PEM-encoded key will look like: + # + # -----BEGIN PUBLIC KEY----- + # [...] + # -----END PUBLIC KEY----- + # + # Consider using #public_to_pem instead. This serializes the key into an + # X.509 SubjectPublicKeyInfo regardless of whether the key is a public key + # or a private key. + # + # When the key contains private components, and no parameters are given + # : Serializes it into a PKCS #1 RSAPrivateKey. + # + # A PEM-encoded key will look like: + # + # -----BEGIN RSA PRIVATE KEY----- + # [...] + # -----END RSA PRIVATE KEY----- + # + # When the key contains private components, and *cipher* and *password* are given + # : Serializes it into a PKCS #1 RSAPrivateKey and encrypts it in OpenSSL's + # traditional PEM encryption format. *cipher* must be a cipher name + # understood by OpenSSL::Cipher.new or an instance of OpenSSL::Cipher. + # + # An encrypted PEM-encoded key will look like: + # + # -----BEGIN RSA PRIVATE KEY----- + # Proc-Type: 4,ENCRYPTED + # DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + # + # [...] + # -----END RSA PRIVATE KEY----- + # + # Note that this format uses MD5 to derive the encryption key, and hence + # will not be available on FIPS-compliant systems. + # + # + # **This method is kept for compatibility.** This should only be used when the + # PKCS #1 RSAPrivateKey format is required. + # + # Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + # (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. # def export: (String cipher, String password) -> String | () -> String @@ -7093,21 +7377,118 @@ module OpenSSL # rdoc-file=ext/openssl/ossl_pkey_rsa.c # - rsa.to_der => DER-format String # --> - # Outputs this keypair in DER encoding. + # Serializes a private or public key to a DER-encoding. + # + # See #to_pem for details. + # + # **This method is kept for compatibility.** This should only be used when the + # PKCS #1 RSAPrivateKey format is required. + # + # Consider using #public_to_der or #private_to_der instead. # def to_der: () -> String # - # Outputs this keypair in PEM encoding. If *cipher* and *pass_phrase* are given - # they will be used to encrypt the key. *cipher* must be an OpenSSL::Cipher - # instance. + # Serializes a private or public key to a PEM-encoding. + # + # When the key contains public components only + # : Serializes it into an X.509 SubjectPublicKeyInfo. The parameters *cipher* + # and *password* are ignored. + # + # A PEM-encoded key will look like: + # + # -----BEGIN PUBLIC KEY----- + # [...] + # -----END PUBLIC KEY----- + # + # Consider using #public_to_pem instead. This serializes the key into an + # X.509 SubjectPublicKeyInfo regardless of whether the key is a public key + # or a private key. + # + # When the key contains private components, and no parameters are given + # : Serializes it into a PKCS #1 RSAPrivateKey. + # + # A PEM-encoded key will look like: + # + # -----BEGIN RSA PRIVATE KEY----- + # [...] + # -----END RSA PRIVATE KEY----- + # + # When the key contains private components, and *cipher* and *password* are given + # : Serializes it into a PKCS #1 RSAPrivateKey and encrypts it in OpenSSL's + # traditional PEM encryption format. *cipher* must be a cipher name + # understood by OpenSSL::Cipher.new or an instance of OpenSSL::Cipher. + # + # An encrypted PEM-encoded key will look like: + # + # -----BEGIN RSA PRIVATE KEY----- + # Proc-Type: 4,ENCRYPTED + # DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + # + # [...] + # -----END RSA PRIVATE KEY----- + # + # Note that this format uses MD5 to derive the encryption key, and hence + # will not be available on FIPS-compliant systems. + # + # + # **This method is kept for compatibility.** This should only be used when the + # PKCS #1 RSAPrivateKey format is required. + # + # Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + # (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. # alias to_pem export # - # Outputs this keypair in PEM encoding. If *cipher* and *pass_phrase* are given - # they will be used to encrypt the key. *cipher* must be an OpenSSL::Cipher - # instance. + # Serializes a private or public key to a PEM-encoding. + # + # When the key contains public components only + # : Serializes it into an X.509 SubjectPublicKeyInfo. The parameters *cipher* + # and *password* are ignored. + # + # A PEM-encoded key will look like: + # + # -----BEGIN PUBLIC KEY----- + # [...] + # -----END PUBLIC KEY----- + # + # Consider using #public_to_pem instead. This serializes the key into an + # X.509 SubjectPublicKeyInfo regardless of whether the key is a public key + # or a private key. + # + # When the key contains private components, and no parameters are given + # : Serializes it into a PKCS #1 RSAPrivateKey. + # + # A PEM-encoded key will look like: + # + # -----BEGIN RSA PRIVATE KEY----- + # [...] + # -----END RSA PRIVATE KEY----- + # + # When the key contains private components, and *cipher* and *password* are given + # : Serializes it into a PKCS #1 RSAPrivateKey and encrypts it in OpenSSL's + # traditional PEM encryption format. *cipher* must be a cipher name + # understood by OpenSSL::Cipher.new or an instance of OpenSSL::Cipher. + # + # An encrypted PEM-encoded key will look like: + # + # -----BEGIN RSA PRIVATE KEY----- + # Proc-Type: 4,ENCRYPTED + # DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + # + # [...] + # -----END RSA PRIVATE KEY----- + # + # Note that this format uses MD5 to derive the encryption key, and hence + # will not be available on FIPS-compliant systems. + # + # + # **This method is kept for compatibility.** This should only be used when the + # PKCS #1 RSAPrivateKey format is required. + # + # Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + # (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. # alias to_s export @@ -7153,8 +7534,8 @@ module OpenSSL # # Generates or loads an RSA keypair. @@ -7164,9 +7545,9 @@ module OpenSSL # #set_crt_params. # # If called with a String, tries to parse as DER or PEM encoding of an RSA key. - # Note that, if *passphrase* is not specified but the key is encrypted with a - # passphrase, OpenSSL will prompt for it. See also OpenSSL::PKey.read which can - # parse keys of any kinds. + # Note that if *password* is not specified, but the key is encrypted with a + # password, OpenSSL will prompt for it. See also OpenSSL::PKey.read which can + # parse keys of any kind. # # If called with a number, generates a new key pair. This form works as an alias # of RSA.generate. @@ -7174,7 +7555,7 @@ module OpenSSL # Examples: # OpenSSL::PKey::RSA.new 2048 # OpenSSL::PKey::RSA.new File.read 'rsa.pem' - # OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my pass phrase' + # OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my password' # def initialize: () -> void | (Integer key_size) -> void diff --git a/stdlib/optparse/0/optparse.rbs b/stdlib/optparse/0/optparse.rbs index e36f07dc7..3070c612c 100644 --- a/stdlib/optparse/0/optparse.rbs +++ b/stdlib/optparse/0/optparse.rbs @@ -1,7 +1,7 @@ # # ## OptionParser # -# ### New to OptionParser? +# ### New to `OptionParser`? # # See the [Tutorial](optparse/tutorial.rdoc). # @@ -106,13 +106,17 @@ # OptionParser supports the ability to coerce command line arguments into # objects for us. # -# OptionParser comes with a few ready-to-use kinds of type coercion. They are: -# -# * Date -- Anything accepted by `Date.parse` -# * DateTime -- Anything accepted by `DateTime.parse` -# * Time -- Anything accepted by `Time.httpdate` or `Time.parse` -# * URI -- Anything accepted by `URI.parse` -# * Shellwords -- Anything accepted by `Shellwords.shellwords` +# OptionParser comes with a few ready-to-use kinds of type coercion. They are: +# +# * Date -- Anything accepted by `Date.parse` (need to require +# `optparse/date`) +# * DateTime -- Anything accepted by `DateTime.parse` (need to require +# `optparse/date`) +# * Time -- Anything accepted by `Time.httpdate` or `Time.parse` (need to +# require `optparse/time`) +# * URI -- Anything accepted by `URI.parse` (need to require `optparse/uri`) +# * Shellwords -- Anything accepted by `Shellwords.shellwords` (need to +# require `optparse/shellwords`) # * String -- Any non-empty string # * Integer -- Any integer. Will convert octal. (e.g. 124, -3, 040) # * Float -- Any float. (e.g. 10, 3.14, -100E+13) @@ -400,7 +404,7 @@ class OptionParser # # See #getopts. # @@ -598,7 +602,7 @@ class OptionParser # # Wrapper method for getopts.rb. # @@ -609,6 +613,16 @@ class OptionParser # # params["bar"] = "x" # --bar x # # params["zot"] = "z" # --zot Z # + # Option `symbolize_names` (boolean) specifies whether returned Hash keys should + # be Symbols; defaults to `false` (use Strings). + # + # params = ARGV.getopts("ab:", "foo", "bar:", "zot:Z;zot option", symbolize_names: true) + # # params[:a] = true # -a + # # params[:b] = "1" # -b1 + # # params[:foo] = "1" # --foo + # # params[:bar] = "x" # --bar x + # # params[:zot] = "z" # --zot Z + # def getopts: (*String options) -> Hash[String, untyped] | (Array[String] args, *String options) -> Hash[String, untyped] @@ -1099,7 +1113,7 @@ module OptionParser::Arguable # # Substitution of getopts is possible as follows. Also see OptionParser#getopts. # diff --git a/stdlib/pp/0/pp.rbs b/stdlib/pp/0/pp.rbs index a85fbd15b..661eeab18 100644 --- a/stdlib/pp/0/pp.rbs +++ b/stdlib/pp/0/pp.rbs @@ -38,7 +38,8 @@ # ## Output Customization # # To define a customized pretty printing function for your classes, redefine -# method `#pretty_print(pp)` in the class. +# method `#pretty_print(pp)` in the class. Note that `require 'pp'` is needed +# before redefining `#pretty_print(pp)`. # # `#pretty_print` takes the `pp` argument, which is an instance of the PP class. # The method uses #text, #breakable, #nest, #group and #pp to print the object. @@ -291,10 +292,6 @@ module Kernel # --> # Returns a pretty printed object as a string. # - # In order to use this method you must first require the PP module: - # - # require 'pp' - # # See the PP module for more information. # def pretty_inspect: () -> String diff --git a/stdlib/prettyprint/0/prettyprint.rbs b/stdlib/prettyprint/0/prettyprint.rbs index 22c6d7eec..7f3cb18c4 100644 --- a/stdlib/prettyprint/0/prettyprint.rbs +++ b/stdlib/prettyprint/0/prettyprint.rbs @@ -25,10 +25,10 @@ # # ## References # Christian Lindig, Strictly Pretty, March 2000, -# http://www.st.cs.uni-sb.de/~lindig/papers/#pretty +# https://lindig.github.io/papers/strictly-pretty-2000.pdf # # Philip Wadler, A prettier printer, March 1998, -# http://homepages.inf.ed.ac.uk/wadler/topics/language-design.html#prettier +# https://homepages.inf.ed.ac.uk/wadler/topics/language-design.html#prettier # # ## Author # Tanaka Akira diff --git a/stdlib/pstore/0/pstore.rbs b/stdlib/pstore/0/pstore.rbs index 09c6ecda8..08a3e935b 100644 --- a/stdlib/pstore/0/pstore.rbs +++ b/stdlib/pstore/0/pstore.rbs @@ -352,8 +352,7 @@ class PStore # - abort() # --> # Exits the current transaction block, discarding any changes specified in the - # transaction block. See [Committing or - # Aborting](rdoc-ref:PStore@Committing+or+Aborting). + # [transaction block](rdoc-ref:PStore@The+Transaction+Block). # # Raises an exception if called outside a transaction block. # @@ -364,8 +363,7 @@ class PStore # - commit() # --> # Exits the current transaction block, committing any changes specified in the - # transaction block. See [Committing or - # Aborting](rdoc-ref:PStore@Committing+or+Aborting). + # [transaction block](rdoc-ref:PStore@The+Transaction+Block). # # Raises an exception if called outside a transaction block. # diff --git a/stdlib/rdoc/0/comment.rbs b/stdlib/rdoc/0/comment.rbs index 2752ae75f..9eb9894a5 100644 --- a/stdlib/rdoc/0/comment.rbs +++ b/stdlib/rdoc/0/comment.rbs @@ -7,8 +7,7 @@ module RDoc # Each comment may have a different markup format set by #format=. By default # 'rdoc' is used. The :markup: directive tells RDoc which format to use. # - # See RDoc::Markup@Other+directives for instructions on adding an alternate - # format. + # See RDoc::MarkupReference@Directive+for+Specifying+RDoc+Source+Format. # class Comment # diff --git a/stdlib/socket/0/socket.rbs b/stdlib/socket/0/socket.rbs index 770917544..04037564d 100644 --- a/stdlib/socket/0/socket.rbs +++ b/stdlib/socket/0/socket.rbs @@ -1517,8 +1517,8 @@ Socket::AF_IMPLINK: Integer # Socket::AF_INET: Integer -# -# IPv6 protocol +# +# IPv6 protocol family # Socket::AF_INET6: Integer diff --git a/stdlib/socket/0/unix_socket.rbs b/stdlib/socket/0/unix_socket.rbs index 3e703ebe4..1d0286eb3 100644 --- a/stdlib/socket/0/unix_socket.rbs +++ b/stdlib/socket/0/unix_socket.rbs @@ -9,7 +9,7 @@ class UNIXSocket < BasicSocket # --> # Creates a pair of sockets connected to each other. # - # *socktype* should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. + # *type* should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. # # *protocol* should be a protocol defined in the domain. 0 is default protocol # for the domain. @@ -28,7 +28,7 @@ class UNIXSocket < BasicSocket # --> # Creates a pair of sockets connected to each other. # - # *socktype* should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. + # *type* should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. # # *protocol* should be a protocol defined in the domain. 0 is default protocol # for the domain. diff --git a/stdlib/strscan/0/string_scanner.rbs b/stdlib/strscan/0/string_scanner.rbs index 01d389f81..606ce7acd 100644 --- a/stdlib/strscan/0/string_scanner.rbs +++ b/stdlib/strscan/0/string_scanner.rbs @@ -567,8 +567,9 @@ class StringScanner # method is obsolete; use #eos? instead. # # s = StringScanner.new('test string') - # s.eos? # These two - # s.rest? # are opposites. + # # These two are opposites + # s.eos? # => false + # s.rest? # => true # def rest?: () -> bool diff --git a/stdlib/tempfile/0/tempfile.rbs b/stdlib/tempfile/0/tempfile.rbs index d9ba5222d..0e065740d 100644 --- a/stdlib/tempfile/0/tempfile.rbs +++ b/stdlib/tempfile/0/tempfile.rbs @@ -48,7 +48,7 @@ # Note that Tempfile.create returns a File instance instead of a Tempfile, which # also avoids the overhead and complications of delegation. # -# Tempfile.open('foo') do |file| +# Tempfile.create('foo') do |file| # # ...do something with file... # end # diff --git a/stdlib/uri/0/common.rbs b/stdlib/uri/0/common.rbs index b04a4895a..b28c58d4f 100644 --- a/stdlib/uri/0/common.rbs +++ b/stdlib/uri/0/common.rbs @@ -125,22 +125,37 @@ module URI # rdoc-file=lib/uri/common.rb # - decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false) # --> - # Decodes URL-encoded form data from given `str`. + # Returns name/value pairs derived from the given string `str`, which must be an + # ASCII string. # - # This decodes application/x-www-form-urlencoded data and returns an array of - # key-value arrays. + # The method may be used to decode the body of Net::HTTPResponse object `res` + # for which `res['Content-Type']` is `'application/x-www-form-urlencoded'`. # - # This refers http://url.spec.whatwg.org/#concept-urlencoded-parser, so this - # supports only &-separator, and doesn't support ;-separator. + # The returned data is an array of 2-element subarrays; each subarray is a + # name/value pair (both are strings). Each returned string has encoding `enc`, + # and has had invalid characters removed via + # [String#scrub](rdoc-ref:String#scrub). # - # ary = URI.decode_www_form("a=1&a=2&b=3") - # ary #=> [['a', '1'], ['a', '2'], ['b', '3']] - # ary.assoc('a').last #=> '1' - # ary.assoc('b').last #=> '3' - # ary.rassoc('a').last #=> '2' - # Hash[ary] #=> {"a"=>"2", "b"=>"3"} + # A simple example: # - # See URI.decode_www_form_component, URI.encode_www_form. + # URI.decode_www_form('foo=0&bar=1&baz') + # # => [["foo", "0"], ["bar", "1"], ["baz", ""]] + # + # The returned strings have certain conversions, similar to those performed in + # URI.decode_www_form_component: + # + # URI.decode_www_form('f%23o=%2F&b-r=%24&b+z=%40') + # # => [["f#o", "/"], ["b-r", "$"], ["b z", "@"]] + # + # The given string may contain consecutive separators: + # + # URI.decode_www_form('foo=0&&bar=1&&baz=2') + # # => [["foo", "0"], ["", ""], ["bar", "1"], ["", ""], ["baz", "2"]] + # + # A different separator may be specified: + # + # URI.decode_www_form('foo=0--bar=1--baz', separator: '--') + # # => [["foo", "0"], ["bar", "1"], ["baz", ""]] # def self.decode_www_form: (String str, ?encoding enc, ?isindex: boolish, ?use__charset_: boolish, ?separator: String) -> Array[[ String, String ]] @@ -148,11 +163,38 @@ module URI # rdoc-file=lib/uri/common.rb # - decode_www_form_component(str, enc=Encoding::UTF_8) # --> - # Decodes given `str` of URL-encoded form data. + # Returns a string decoded from the given URL-encoded string `str`. + # + # The given string is first encoded as Encoding::ASCII-8BIT (using String#b), + # then decoded (as below), and finally force-encoded to the given encoding + # `enc`. + # + # The returned string: + # + # * Preserves: + # + # * Characters `'*'`, `'.'`, `'-'`, and `'_'`. + # * Character in ranges `'a'..'z'`, `'A'..'Z'`, and `'0'..'9'`. + # + # + # Example: + # + # URI.decode_www_form_component('*.-_azAZ09') + # # => "*.-_azAZ09" + # + # * Converts: # - # This decodes + to SP. + # * Character `'+'` to character `' '`. + # * Each "percent notation" to an ASCII character. # - # See URI.encode_www_form_component, URI.decode_www_form. + # + # Example: + # + # URI.decode_www_form_component('Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A') + # # => "Here are some punctuation characters: ,;?:" + # + # + # Related: URI.decode_uri_component (preserves `'+'`). # def self.decode_www_form_component: (String str, ?encoding enc) -> String @@ -160,33 +202,101 @@ module URI # rdoc-file=lib/uri/common.rb # - encode_www_form(enum, enc=nil) # --> - # Generates URL-encoded form data from given `enum`. + # Returns a URL-encoded string derived from the given + # [Enumerable](rdoc-ref:Enumerable@Enumerable+in+Ruby+Classes) `enum`. + # + # The result is suitable for use as form data for an HTTP request whose + # `Content-Type` is `'application/x-www-form-urlencoded'`. + # + # The returned string consists of the elements of `enum`, each converted to one + # or more URL-encoded strings, and all joined with character `'&'`. + # + # Simple examples: + # + # URI.encode_www_form([['foo', 0], ['bar', 1], ['baz', 2]]) + # # => "foo=0&bar=1&baz=2" + # URI.encode_www_form({foo: 0, bar: 1, baz: 2}) + # # => "foo=0&bar=1&baz=2" + # + # The returned string is formed using method URI.encode_www_form_component, + # which converts certain characters: + # + # URI.encode_www_form('f#o': '/', 'b-r': '$', 'b z': '@') + # # => "f%23o=%2F&b-r=%24&b+z=%40" + # + # When `enum` is Array-like, each element `ele` is converted to a field: + # + # * If `ele` is an array of two or more elements, the field is formed from its + # first two elements (and any additional elements are ignored): + # + # name = URI.encode_www_form_component(ele[0], enc) + # value = URI.encode_www_form_component(ele[1], enc) + # "#{name}=#{value}" # - # This generates application/x-www-form-urlencoded data defined in HTML5 from - # given an Enumerable object. + # Examples: # - # This internally uses URI.encode_www_form_component(str). + # URI.encode_www_form([%w[foo bar], %w[baz bat bah]]) + # # => "foo=bar&baz=bat" + # URI.encode_www_form([['foo', 0], ['bar', :baz, 'bat']]) + # # => "foo=0&bar=baz" # - # This method doesn't convert the encoding of given items, so convert them - # before calling this method if you want to send data as other than original - # encoding or mixed encoding data. (Strings which are encoded in an HTML5 ASCII - # incompatible encoding are converted to UTF-8.) + # * If `ele` is an array of one element, the field is formed from `ele[0]`: # - # This method doesn't handle files. When you send a file, use - # multipart/form-data. + # URI.encode_www_form_component(ele[0]) # - # This refers https://url.spec.whatwg.org/#concept-urlencoded-serializer + # Example: # - # URI.encode_www_form([["q", "ruby"], ["lang", "en"]]) - # #=> "q=ruby&lang=en" - # URI.encode_www_form("q" => "ruby", "lang" => "en") - # #=> "q=ruby&lang=en" - # URI.encode_www_form("q" => ["ruby", "perl"], "lang" => "en") - # #=> "q=ruby&q=perl&lang=en" - # URI.encode_www_form([["q", "ruby"], ["q", "perl"], ["lang", "en"]]) - # #=> "q=ruby&q=perl&lang=en" + # URI.encode_www_form([['foo'], [:bar], [0]]) + # # => "foo&bar&0" # - # See URI.encode_www_form_component, URI.decode_www_form. + # * Otherwise the field is formed from `ele`: + # + # URI.encode_www_form_component(ele) + # + # Example: + # + # URI.encode_www_form(['foo', :bar, 0]) + # # => "foo&bar&0" + # + # + # The elements of an Array-like `enum` may be mixture: + # + # URI.encode_www_form([['foo', 0], ['bar', 1, 2], ['baz'], :bat]) + # # => "foo=0&bar=1&baz&bat" + # + # When `enum` is Hash-like, each `key`/`value` pair is converted to one or more + # fields: + # + # * If `value` is + # [Array-convertible](rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Ob + # jects), each element `ele` in `value` is paired with `key` to form a + # field: + # + # name = URI.encode_www_form_component(key, enc) + # value = URI.encode_www_form_component(ele, enc) + # "#{name}=#{value}" + # + # Example: + # + # URI.encode_www_form({foo: [:bar, 1], baz: [:bat, :bam, 2]}) + # # => "foo=bar&foo=1&baz=bat&baz=bam&baz=2" + # + # * Otherwise, `key` and `value` are paired to form a field: + # + # name = URI.encode_www_form_component(key, enc) + # value = URI.encode_www_form_component(value, enc) + # "#{name}=#{value}" + # + # Example: + # + # URI.encode_www_form({foo: 0, bar: 1, baz: 2}) + # # => "foo=0&bar=1&baz=2" + # + # + # The elements of a Hash-like `enum` may be mixture: + # + # URI.encode_www_form({foo: [0, 1], bar: 2}) + # # => "foo=0&foo=1&bar=2" # def self.encode_www_form: (Enumerable[[ _ToS, _ToS ]] enum, ?encoding? enc) -> String @@ -194,17 +304,44 @@ module URI # rdoc-file=lib/uri/common.rb # - encode_www_form_component(str, enc=nil) # --> - # Encodes given `str` to URL-encoded form data. + # Returns a URL-encoded string derived from the given string `str`. + # + # The returned string: + # + # * Preserves: + # + # * Characters `'*'`, `'.'`, `'-'`, and `'_'`. + # * Character in ranges `'a'..'z'`, `'A'..'Z'`, and `'0'..'9'`. + # + # + # Example: + # + # URI.encode_www_form_component('*.-_azAZ09') + # # => "*.-_azAZ09" + # + # * Converts: + # + # * Character `' '` to character `'+'`. + # * Any other character to "percent notation"; the percent notation for + # character *c* is `'%%%X' % c.ord`. + # # - # This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP - # (ASCII space) to + and converts others to %XX. + # Example: # - # If `enc` is given, convert `str` to the encoding before percent encoding. + # URI.encode_www_form_component('Here are some punctuation characters: ,;?:') + # # => "Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A" # - # This is an implementation of - # https://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data. # - # See URI.decode_www_form_component, URI.encode_www_form. + # Encoding: + # + # * If `str` has encoding Encoding::ASCII_8BIT, argument `enc` is ignored. + # * Otherwise `str` is converted first to Encoding::UTF_8 (with suitable + # character replacements), and then to encoding `enc`. + # + # + # In either case, the returned string has forced encoding Encoding::US_ASCII. + # + # Related: URI.encode_uri_component (encodes `' '` as `'%20'`). # def self.encode_www_form_component: (_ToS str, ?encoding? enc) -> String @@ -245,23 +382,13 @@ module URI # rdoc-file=lib/uri/common.rb # - join(*str) # --> - # ## Synopsis - # - # URI::join(str[, str, ...]) - # - # ## Args - # - # `str` - # : String(s) to work with, will be converted to RFC3986 URIs before merging. + # Merges the given URI strings `str` per [RFC + # 2396](https://www.rfc-editor.org/rfc/rfc2396.html). # + # Each string in `str` is converted to an [RFC3986 + # URI](https://www.rfc-editor.org/rfc/rfc3986.html) before being merged. # - # ## Description - # - # Joins URIs. - # - # ## Usage - # - # require 'uri' + # Examples: # # URI.join("http://example.com/","main.rbx") # # => # @@ -284,39 +411,15 @@ module URI # rdoc-file=lib/uri/common.rb # - parse(uri) # --> - # ## Synopsis - # - # URI::parse(uri_str) - # - # ## Args - # - # `uri_str` - # : String with URI. - # - # - # ## Description - # - # Creates one of the URI's subclasses instance from the string. - # - # ## Raises - # - # URI::InvalidURIError - # : Raised if URI given is not a correct one. + # Returns a new URI object constructed from the given string `uri`: # + # URI.parse('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top') + # # => # + # URI.parse('http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top') + # # => # # - # ## Usage - # - # require 'uri' - # - # uri = URI.parse("http://www.ruby-lang.org/") - # # => # - # uri.scheme - # # => "http" - # uri.host - # # => "www.ruby-lang.org" - # - # It's recommended to first ::escape the provided `uri_str` if there are any - # invalid URI characters. + # It's recommended to first ::escape string `uri` if it may contain invalid URI + # characters. # def self.parse: (_ToStr uri) -> (File | FTP | HTTP | HTTPS | LDAP | LDAPS | MailTo | WS | WSS | Generic) @@ -362,7 +465,20 @@ module URI # rdoc-file=lib/uri/common.rb # - scheme_list() # --> - # Returns a Hash of the defined schemes. + # Returns a hash of the defined schemes: + # + # URI.scheme_list + # # => + # {"MAILTO"=>URI::MailTo, + # "LDAPS"=>URI::LDAPS, + # "WS"=>URI::WS, + # "HTTP"=>URI::HTTP, + # "HTTPS"=>URI::HTTPS, + # "LDAP"=>URI::LDAP, + # "FILE"=>URI::File, + # "FTP"=>URI::FTP} + # + # Related: URI.register_scheme. # def self.scheme_list: () -> Hash[String, Class] @@ -370,8 +486,21 @@ module URI # rdoc-file=lib/uri/common.rb # - for(scheme, *arguments, default: Generic) # --> - # Construct a URI instance, using the scheme to detect the appropriate class - # from `URI.scheme_list`. + # Returns a new object constructed from the given `scheme`, `arguments`, and + # `default`: + # + # * The new object is an instance of `URI.scheme_list[scheme.upcase]`. + # * The object is initialized by calling the class initializer using `scheme` + # and `arguments`. See URI::Generic.new. + # + # + # Examples: + # + # values = ['john.doe', 'www.example.com', '123', nil, '/forum/questions/', nil, 'tag=networking&order=newest', 'top'] + # URI.for('https', *values) + # # => # + # URI.for('foo', *values, default: URI::HTTP) + # # => # # def self.for: (String scheme, *untyped arguments, ?default: Class) -> (File | FTP | HTTP | HTTPS | LDAP | LDAPS | MailTo | WS | WSS | Generic) @@ -379,37 +508,22 @@ module URI # rdoc-file=lib/uri/common.rb # - split(uri) # --> - # ## Synopsis - # - # URI::split(uri) - # - # ## Args - # - # `uri` - # : String with URI. - # - # - # ## Description - # - # Splits the string on following parts and returns array with result: - # - # * Scheme - # * Userinfo - # * Host - # * Port - # * Registry - # * Path - # * Opaque - # * Query - # * Fragment - # - # - # ## Usage - # - # require 'uri' - # - # URI.split("http://www.ruby-lang.org/") - # # => ["http", nil, "www.ruby-lang.org", nil, nil, "/", nil, nil, nil] + # Returns a 9-element array representing the parts of the URI formed from the + # string `uri`; each array element is a string or `nil`: + # + # names = %w[scheme userinfo host port registry path opaque query fragment] + # values = URI.split('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top') + # names.zip(values) + # # => + # [["scheme", "https"], + # ["userinfo", "john.doe"], + # ["host", "www.example.com"], + # ["port", "123"], + # ["registry", nil], + # ["path", "/forum/questions/"], + # ["opaque", nil], + # ["query", "tag=networking&order=newest"], + # ["fragment", "top"]] # def self.split: (_ToStr uri) -> [ String?, String?, String?, String?, nil, String?, String?, String?, String? ] end @@ -473,7 +587,15 @@ module Kernel # rdoc-file=lib/uri/common.rb # - URI(uri) # --> - # Returns `uri` converted to an URI object. + # Returns a URI object derived from the given `uri`, which may be a URI string + # or an existing URI object: + # + # # Returns a new URI. + # uri = URI('http://github.com/ruby/ruby') + # # => # + # # Returns the given URI. + # URI(uri) + # # => # # def self?.URI: (URI::Generic | String uri) -> URI::Generic end