From 717b20ee305e523123bbb18d54fe8e87a78a9cb1 Mon Sep 17 00:00:00 2001 From: Burdette Lamar Date: Wed, 6 Apr 2022 15:47:22 -0500 Subject: [PATCH] [DOC] Enhanced RDoc for string slices (#5769) Creates file doc/string/slices.rdoc that the string slicing methods can link to. --- doc/string/slices.rdoc | 138 ++++++++++++++++++++++++++++++++++++++++ string.c | 140 ++++++++++------------------------------- 2 files changed, 172 insertions(+), 106 deletions(-) create mode 100644 doc/string/slices.rdoc diff --git a/doc/string/slices.rdoc b/doc/string/slices.rdoc new file mode 100644 index 0000000000..4689f30cc1 --- /dev/null +++ b/doc/string/slices.rdoc @@ -0,0 +1,138 @@ +== \String Slices + +A _slice_ of a string is a substring that is selected by certain criteria. + +These instance methods make use of slicing: + +- String#[] (also aliased as String#slice) returns a slice copied from +self+. +- String#[]= returns a copy of +self+ with a slice replaced. +- String#slice! returns +self+ with a slice removed. + +Each of the above methods takes arguments that determine the slice +to be copied or replaced. + +The arguments have several forms. +For string +string+, the forms are: + +- string[index]. +- string[start, length]. +- string[range]. +- string[regexp, capture = 0]. +- string[substring]. + +string[index] + +When non-negative integer argument +index+ is given, +the slice is the 1-character substring found in +self+ at character offset +index+: + + 'bar'[0] # => "b" + 'bar'[2] # => "r" + 'bar'[20] # => nil + 'тест'[2] # => "с" + 'こんにちは'[4] # => "は" + +When negative integer +index+ is given, +the slice begins at the offset given by counting backward from the end of +self+: + + 'bar'[-3] # => "b" + 'bar'[-1] # => "r" + 'bar'[-20] # => nil + +string[start, length] + +When non-negative integer arguments +start+ and +length+ are given, +the slice begins at character offset +start+, if it exists, +and continues for +length+ characters, if available: + + 'foo'[0, 2] # => "fo" + 'тест'[1, 2] # => "ес" + 'こんにちは'[2, 2] # => "にち" + # Zero length. + 'foo'[2, 0] # => "" + # Length not entirely available. + 'foo'[1, 200] # => "oo" + # Start out of range. + 'foo'[4, 2] # => nil + +Special case: if +start+ is equal to the length of +self+, +the slice is a new empty string: + + 'foo'[3, 2] # => "" + 'foo'[3, 200] # => "" + +When negative +start+ and non-negative +length+ are given, +the slice beginning is determined by counting backward from the end of +self+, +and the slice continues for +length+ characters, if available: + + 'foo'[-2, 2] # => "oo" + 'foo'[-2, 200] # => "oo" + # Start out of range. + 'foo'[-4, 2] # => nil + +When negative +length+ is given, there is no slice: + + 'foo'[1, -1] # => nil + 'foo'[-2, -1] # => nil + +string[range] + +When Range argument +range+ is given, +creates a substring of +string+ using the indices in +range+. +The slice is then determined as above: + + 'foo'[0..1] # => "fo" + 'foo'[0, 2] # => "fo" + + 'foo'[2...2] # => "" + 'foo'[2, 0] # => "" + + 'foo'[1..200] # => "oo" + 'foo'[1, 200] # => "oo" + + 'foo'[4..5] # => nil + 'foo'[4, 2] # => nil + + 'foo'[-4..-3] # => nil + 'foo'[-4, 2] # => nil + + 'foo'[3..4] # => "" + 'foo'[3, 2] # => "" + + 'foo'[-2..-1] # => "oo" + 'foo'[-2, 2] # => "oo" + + 'foo'[-2..197] # => "oo" + 'foo'[-2, 200] # => "oo" + +string[regexp, capture = 0] + +When the \Regexp argument +regexp+ is given, +and the +capture+ argument is 0, +the slice is the first matching substring found in +self+: + + 'foo'[/o/] # => "o" + 'foo'[/x/] # => nil + s = 'hello there' + s[/[aeiou](.)\1/] # => "ell" + s[/[aeiou](.)\1/, 0] # => "ell" + +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): + + s = 'hello there' + s[/[aeiou](.)\1/, 1] # => "l" + s[/(?[aeiou])(?[^aeiou])/, "non_vowel"] # => "l" + s[/(?[aeiou])(?[^aeiou])/, :vowel] # => "e" + +If an invalid capture group index is given, there is no slice. +If an invalid capture group name is given, +IndexError+ is raised. + +string[substring] + +When the single \String argument +substring+ is given, +returns the substring from +self+ if found, otherwise +nil+: + + 'foo'['oo'] # => "oo" + 'foo'['xx'] # => nil diff --git a/string.c b/string.c index 2738ecbfcd..9f08e85d60 100644 --- a/string.c +++ b/string.c @@ -5116,86 +5116,9 @@ rb_str_aref(VALUE str, VALUE indx) * string[substring] -> new_string or nil * * Returns the substring of +self+ specified by the arguments. + * See examples at {String Slices}[rdoc-ref:String@String+Slices]. * - * When the single \Integer argument +index+ is given, - * returns the 1-character substring found in +self+ at offset +index+: * - * 'bar'[2] # => "r" - * - * Counts backward from the end of +self+ if +index+ is negative: - * - * 'foo'[-3] # => "f" - * - * Returns +nil+ if +index+ is out of range: - * - * 'foo'[3] # => nil - * 'foo'[-4] # => nil - * - * When the two \Integer arguments +start+ and +length+ are given, - * returns the substring of the given +length+ found in +self+ at offset +start+: - * - * 'foo'[0, 2] # => "fo" - * 'foo'[0, 0] # => "" - * - * Counts backward from the end of +self+ if +start+ is negative: - * - * 'foo'[-2, 2] # => "oo" - * - * Special case: returns a new empty \String if +start+ is equal to the length of +self+: - * - * 'foo'[3, 2] # => "" - * - * Returns +nil+ if +start+ is out of range: - * - * 'foo'[4, 2] # => nil - * 'foo'[-4, 2] # => nil - * - * Returns the trailing substring of +self+ if +length+ is large: - * - * 'foo'[1, 50] # => "oo" - * - * Returns +nil+ if +length+ is negative: - * - * 'foo'[0, -1] # => nil - * - * When the single \Range argument +range+ is given, - * derives +start+ and +length+ values from the given +range+, - * and returns values as above: - * - * - 'foo'[0..1] is equivalent to 'foo'[0, 2]. - * - 'foo'[0...1] is equivalent to 'foo'[0, 1]. - * - * When the \Regexp argument +regexp+ is given, - * and the +capture+ argument is 0, - * returns the first matching substring found in +self+, - * or +nil+ if none found: - * - * 'foo'[/o/] # => "o" - * 'foo'[/x/] # => nil - * s = 'hello there' - * s[/[aeiou](.)\1/] # => "ell" - * s[/[aeiou](.)\1/, 0] # => "ell" - * - * If argument +capture+ is given and not 0, - * it should be either an \Integer capture group index or a \String or \Symbol capture group name; - * the method call returns only the specified capture - * (see Regexp@Capturing): - * - * s = 'hello there' - * s[/[aeiou](.)\1/, 1] # => "l" - * s[/(?[aeiou])(?[^aeiou])/, "non_vowel"] # => "l" - * s[/(?[aeiou])(?[^aeiou])/, :vowel] # => "e" - * - * If an invalid capture group index is given, +nil+ is returned. If an invalid - * capture group name is given, +IndexError+ is raised. - * - * When the single \String argument +substring+ is given, - * returns the substring from +self+ if found, otherwise +nil+: - * - * 'foo'['oo'] # => "oo" - * 'foo'['xx'] # => nil - * - * String#slice is an alias for String#[]. */ static VALUE @@ -5405,26 +5328,31 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val) /* * call-seq: - * str[integer] = new_str - * str[integer, integer] = new_str - * str[range] = aString - * str[regexp] = new_str - * str[regexp, integer] = new_str - * str[regexp, name] = new_str - * str[other_str] = new_str + * string[index] = new_string + * string[start, length] = new_string + * string[range] = new_string + * string[regexp, capture = 0) = new_string + * string[substring] = new_string + * + * Replaces all, some, or none of the contents of +self+; returns +new_string+. + * See {String Slices}[rdoc-ref:String@String+Slices]. + * + * A few examples: + * + * s = 'foo' + * s[2] = 'rtune' # => "rtune" + * s # => "fortune" + * s[1, 5] = 'init' # => "init" + * s # => "finite" + * s[3..4] = 'al' # => "al" + * s # => "finale" + * s[/e$/] = 'ly' # => "ly" + * s # => "finally" + * s['lly'] = 'ncial' # => "ncial" + * s # => "financial" + * + * String#slice is an alias for String#[]. * - * Element Assignment---Replaces some or all of the content of - * str. The portion of the string affected is determined using - * the same criteria as String#[]. If the replacement string is not - * the same length as the text it is replacing, the string will be - * adjusted accordingly. If the regular expression or string is used - * as the index doesn't match a position in the string, IndexError is - * raised. If the regular expression form is used, the optional - * second Integer allows you to specify which portion of the match to - * replace (effectively using the MatchData indexing rules. The forms - * that take an Integer will raise an IndexError if the value is out - * of range; the Range form will raise a RangeError, and the Regexp - * and String will raise an IndexError on negative match. */ static VALUE @@ -5479,16 +5407,14 @@ rb_str_insert(VALUE str, VALUE idx, VALUE str2) /* * call-seq: - * slice!(index) -> new_string or nil - * slice!(start, length) -> new_string or nil - * slice!(range) -> new_string or nil - * slice!(regexp, capture = 0) -> new_string or nil - * slice!(substring) -> new_string or nil + * slice!(index) -> new_string or nil + * slice!(start, length) -> new_string or nil + * slice!(range) -> new_string or nil + * slice!(regexp, capture = 0) -> new_string or nil + * slice!(substring) -> new_string or nil * - * Removes the substring of +self+ specified by the arguments; - * returns the removed substring. - * - * See String#[] for details about the arguments that specify the substring. + * Removes and returns the substring of +self+ specified by the arguments. + * See {String Slices}[rdoc-ref:String@String+Slices]. * * A few examples: * @@ -12126,6 +12052,8 @@ rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc) * - #rstrip, #rstrip!: strip trailing whitespace. * - #strip, #strip!: strip leading and trailing whitespace. * + * :include: doc/string/slices.rdoc + * * == What's Here * * First, what's elsewhere. \Class \String: