4.22. kink/STR

Companion mod for str vals.

4.22.1. type str

A str is a finite immutable sequence of Unicode codepoints. Codepoints are called runes in Kink, likewise in Go.

4.22.1.1. Str1.op_add(Str2)

`op_add` makes a str containing the runes of `Str1` on the front, and the runes of `Str2` on the back.

Precondition:

• `Str2` must be a str

Example:

:Str <- 'foo' + 'bar'
stdout.print_line(Str.repr) # => "foobar"

4.22.1.2. Str.runes

`runes` returns a vec of the runes of the Str.

Example:

stdout.print_line('xyz'.runes.repr) # => [120 121 122]

4.22.1.3. Str.empty?

`empty?` returns whether `Str` contains one or more runes.

4.22.1.4. Str.size

`size` returns the number of runes in `Str` as an int num.

4.22.1.5. Str.get(Rune_index)

`get` returns the rune specified by `Rune_index`.

The result is an int num which represents the rune.

Example:

stdout.print_line('xyz'.get(0).repr) # => 120

4.22.1.6. Str.slice(From_pos To_pos)

`slice` returns the specified slice of `Str`.

Preconditions:

• `From_pos` and `To_pos` must be int nums in the range [0, Str.size]

• `From_pos` must be less than or equal to `To_pos`

The result is a str whose runes are copied from the slice of `Str`.

Example:

:Str <- 'foobar'
:Slice <- Str.slice(1 4)
stdout.print_line(Slice.repr) # => "oob"

4.22.1.7. Str.take_front(N)

`take_front` makes a str containing the first `N` runes of `Str`.

Precondition:

• `N` must be an int num in the range [0, Str.size].

Example:

stdout.print_line('foobar'.take_front(2).repr)  # => "fo"

4.22.1.8. Str.take_back(N)

`take_back` makes a str containing the last `N` runes of `Str`.

Precondition:

• `N` must be an int num in the range [0, Str.size].

Example:

stdout.print_line('foobar'.take_back(2).repr)  # => "ar"

4.22.1.9. Str.drop_front(N)

`drop_front` makes a str dropping the first `N` runes of `Str`.

Precondition:

• `N` must be an int num in the range [0, Str.size].

Example:

stdout.print_line('foobar'.drop_front(2).repr)  # => "obar"

4.22.1.10. Str.drop_back(N)

`drop_back` makes a str dropping the last `N` runes of `Str`.

Precondition:

• `N` must be an int num in the range [0, Str.size].

Example:

stdout.print_line('foobar'.drop_back(2).repr)  # => "foob"

4.22.1.11. Str.search_slice(Min_ind Slice)

`search_slice` searches `Slice` in `Str`.

Preconditions:

• `Min_rune_ind` must be an int num in the range [0, Str.size]

• `Slice` must be a str

`search_slice` tries to find the smallest `Ind` which is >= `Min_ind`, such that `Str.slice(Ind Slice.size)` is equal to `Slice`.

If such `Ind` is found, `search_slice` returns a vec [Ind].

If not found, `search_slice` returns an empty vec [].

Example:

:attempt_search <- {(:Str :Min_ind :Slice)
  Str.search_slice(Min_ind Slice).with_just_or(
    {(:Ind) stdout.print_line('found at: {}'.format(Ind.repr)) }
    { stdout.print_line('not found') }
  )
}
attempt_search('foofoo' 0 'oo')  # => found at: 1
attempt_search('foofoo' 1 'oo')  # => found at: 1
attempt_search('foofoo' 2 'oo')  # => found at: 4
attempt_search('foofoo' 3 'oo')  # => found at: 4
attempt_search('foofoo' 4 'oo')  # => found at: 4
attempt_search('foofoo' 5 'oo')  # => not found
attempt_search('foofoo' 6 'oo')  # => not found

4.22.1.12. Str.have_prefix?(Prefix)

`have_prefix?` returns whether `Str` has the slice `Prefix` at the front.

Precondition:

• `Prefix` must be a str.

If `Str.slice(0 Prefix.size)` is equal to `Prefix`, `have_prefix?` returns true. If not, `have_prefix?` returns false.

4.22.1.13. Str.have_suffix?(Suffix)

`have_suffix?` returns whether `Str` has the slice `Suffix` at the back.

Precondition:

• `Suffix` must be a str.

If `Str.slice(Str.size - Suffix.size Str.size)` is equal to `Suffix`, `have_suffix?` returns true. If not, `have_suffix?` returns false.

4.22.1.14. Str.have_slice?(Slice)

`have_slice?` returns whether `Str` has `Slice`.

Precondition:

• `Slice` must be a str.

If there is `Ind` such that `Str.slice(Ind Ind+Slice.size)` is equal to `Slice`, `have_slice?` returns true. If not, `have_slice?` returns false.

4.22.1.15. Str.trim

`trim` returns a slice of `Str` trimming space-like characters from the front and the back.

Definition of space-like characters:

• Rune which is bigger than U+0021, and which is not U+007f

`trim` returns the longest slice of `Str` which does not start with a space-like character, and does not end with a space-like character.

Exaample:

stdout.print_line(" \t\r\nfoobar\n\r\t ".trim.repr) # => "foobar"
stdout.print_line(" \t\r\n\n\r\t ".trim.repr)       # => ""

4.22.1.16. Str.trim_front

`trim_front` returns a slice of `Str` trimming space-like characters from the front.

See `trim` for the definition of space-like characters.

`trim_front` returns the longest slice of `Str` which does not start with a space-like character.

Exaample:

stdout.print_line(" \t\r\nfoobar\n\r\t ".trim_front.repr) # => "foobar\n\r\t "
stdout.print_line(" \t\r\n\n\r\t ".trim_front.repr)       # => ""

4.22.1.17. Str.trim_back

`trim_back` returns a slice of `Str` trimming space-like characters from the back. See `trim` for the definition of space-like characters.

`trim_back` returns the longest slice of `Str` which does not end with a space-like character.

Exaample:

stdout.print_line(" \t\r\nfoobar\n\r\t ".trim_back.repr) # => " \t\r\nfoobar"
stdout.print_line(" \t\r\n\n\r\t ".trim_back.repr)       # => ""

4.22.1.18. Str.ascii_upcase

`ascii_upcase` converts runes of ASCII lowercase letters (from U+0061='a' to U+007A='z') in `Str` to the corresponding ASCII uppercase letters (from U+0041='A' to U+005A='Z').

`ascii_upcase` does not change runes except for ASCII lowercase letters.

Example:

stdout.print_line('Azkaban'.ascii_upcase.repr) # => "AZKABAN"
stdout.print_line('+-*/%<>'.ascii_upcase.repr) # => "+-*/%<>"
stdout.print_line('Товарищ'.ascii_upcase.repr) # => "Товарищ"

4.22.1.19. Str.ascii_downcase

`ascii_downcase` converts runes of ASCII uppercase letters (from U+0041='A' to U+005A='Z') in `Str` to the corresponding ASCII lowercase letters (from U+0061='a' to U+007A='z').

`ascii_downcase` does not change runes except for ASCII uppercase letters.

Example:

stdout.print_line('aZKABAN'.ascii_downcase.repr)  # => "azkaban"
stdout.print_line('+-*/%<>'.ascii_downcase.repr)  # => "+-*/%<>"
stdout.print_line('Товарищ'.ascii_downcase.repr)  # => "Товарищ"

4.22.1.20. Str.format(... Args) / Str.format($config)

`format` generates a str which is formatted using `Str` as a template.

`format` has two overloads.

Overload: Str.format(... Args)

When called with variadic args `Args`, Str.format uses each element of `Args` as a positional argument.

Preconditions:

• `Str` must be a str which suffices the syntax described below.

• Each element of `Args` must have `show` method.

Overload: Str.format($config)

When called with $config fun, `format` uses $config as a config fun.

Preconditions:

• `Str` must be a str which suffices the syntax described below.

• $config must be a fun which takes a format_config val.

The format of the template str

A template str can contain placeholders delimited by braces "{" and "}". Str.format invokes .show(...[$show_config]) method of the arg corresponding to each placeholder, and emplaces the result str in the placeholder.

There are following variants of placeholders.

• "{}": takes a positional argument, with an empty str "" as the spec.

• "{%xxx}": takes a positional argument, with the spec "xxx".

• "{Foo}": takes a named argument with the name "Foo", with an empty str "" as the spec.

• "{Foo%xxx}": takes a named argument with the name "Foo", with the spec "xxx".

The name str must not contain "{", "}" and "%".

The spec str is passed to Show_config.spec(Spec) method. The spec str must not contain "{" or "}".

If you want to include literal "{" and "}" in the template str, escape them as "{{" and "}}".

Examples

stdout.print_line('{} == 0x{%04x}'.format(42 42))
# => 42 == 0x002a

stdout.print_line('{}: message: {}'.format('WARN' 'something went wrong'))
# => WARN: message: something went wrong

With locale:

:LOCALE.require_from('kink/')

:Str <- 'Id: {%04d}, Name: {}, Elevation: {%,d} meters'.format{(:C)
  C.locale(LOCALE.for('da-DK'))
  C.arg(12)
  C.arg('Mount Fuji')
  C.arg(3776.24)
}
stdout.print_line(Str)
# => Id: 0012, Name: Mount Fuji, Elevation: 3.776,24 meters

Using named args:

:LOCALE.require_from('kink/')

:Str <- 'Id: {Id%04d}, Name: {Name}, Elevation: {Elevation%,d} meters'.format{(:C)
  C.locale(LOCALE.for('da-DK'))
  C.named_arg('Id' 12)
  C.named_arg('Name' 'Mount Fuji')
  C.named_arg('Elevation' 3776.24)
}
stdout.print_line(Str)
# => Id: 0012, Name: Mount Fuji, Elevation: 3.776,24 meters

4.22.1.21. Str.op_mul(N)

`op_mul` makes a str repeating `Str` `N` times.

Precondition:

• `N` must be a nonnegative int num.

Example:

stdout.print_line(('foo' * 0).repr) # => ""
stdout.print_line(('foo' * 1).repr) # => "foo"
stdout.print_line(('foo' * 2).repr) # => "foofoo"
stdout.print_line(('foo' * 3).repr) # => "foofoofoo"

4.22.1.22. Str1.op_eq(Str2)

`op_eq` returns whether two strs contains the same sequence of runes.

Precondition:

• `Str1` and `Str2` must be strs.

Example:

stdout.print_line(('foo' == 'foo').repr)  # => true
stdout.print_line(('foo' != 'foo').repr)  # => false

stdout.print_line(('foo' == 'FOO').repr)  # => false
stdout.print_line(('foo' != 'FOO').repr)  # => true

4.22.1.23. Str1.op_lt(Str2)

`op_lt` returns compares the runes of the strs lexicographically, then returns whether `Str1` is less than `Str2`.

Precondition:

• `Str1` and `Str2` must be strs.

Example:

:compare <- {(:Str1 :Str2)
  [:Lt? :Le? :Gt? :Ge?] = [
    Str1 < Str2
    Str1 <= Str2
    Str1 > Str2
    Str1 >= Str2
  ]
  stdout.print_line(
    'Lt?={} Le?={} Gt?={} Ge?={}'.format(Lt?.repr Le?.repr Gt?.repr Ge?.repr))
}

compare('foo' 'foo')  # => Lt?=false Le?=true Gt?=false Ge?=true
compare('foo' 'fooo') # => Lt?=true Le?=true Gt?=false Ge?=false
compare('foo' 'fo')   # => Lt?=false Le?=false Gt?=true Ge?=true

Note that the result of comparison may differ from java.lang.String.compareTo. The reason is that the Java method compares strings by UTF-16 units.

:JAVA.require_from('kink/javahost/')
:X <- "\x{00ffff}"
:Y <- "\x{010302}"
stdout.print_line((X < Y).repr)  # => true
stdout.print_line(
  (JAVA.string(X).call_method('compareTo' JAVA.string(Y)).to_kink_num < 0).repr
)  # => false

4.22.1.24. Str.show(...[$config={}])

`show` returns `Str` itself.

`show` can take an optional parameter $config, but it is never used. This parameter exists in order to meet the requirement by `format` method.

Example:

stdout.print_line('xyz'.show)
# Output:
#   xyz

stdout.print_line('xyz'.show{})
# Output:
#   xyz

stdout.print_line("foo\nbar".show)
# Output:
#   foo
#   bar

4.22.1.25. Str.repr

`repr` returns the str representation of the Str for debugging, such as "xyz" and "foo\nbar".

Example:

stdout.print_line('xyz'.repr)       # => "xyz"
stdout.print_line("foo\nbar".repr)  # => "foo\nbar"

4.22.2. type format_config

A format_config is a conf val of Str.format.

4.22.2.1. Format_config.arg(Pos_arg)

`arg` method adds a positional arg.

Precondition:

• `Pos_arg` must support .show(...[$show_config]) method

The number of invocations of `arg` method must be equal to the unnamed placeholders.

4.22.2.2. Format_config.named_arg(Name Arg)

`named_arg` method adds a named arg.

Preconditions:

• `Name` must be a nonempty str which does not contain "{", "}", or "%"

• `Arg` must support .show(...[$show_config]) method

• The set of Name1, Name2 ,,, must be a superset of the names of the named arguments in the Template

All the names of the named args in the template str must be specified by `named_arg` method.

It is permitted to pass `Name` which is not the name of any named arg in the template str. For example:

stdout.print_line('X={X}, Y={Y}'.format{(:C)
    C.named_arg('X' 10)
    C.named_arg('Y' 20)
    C.named_arg('Z' 30) # Z is not in the template str, but it is OK
  }
)
# => X=10, Y=20

4.22.2.3. Format_config.locale(Locale)

`locale` method specifies the locale.

Precondition:

• Locale must be a locale

4.22.3. type show_config

`show_config` is the config val type of .show(...[$show_config]) methods.

`show` method is expected to return a str which represents the receiver val. In contrast to `repr method, which is used for debugging, the result of `show` method is intended to be used in UI messages.

Usually, `show` methods are called from Str.format. See Str.format for details.

Example usage:

:LOCALE.require_from('kink/')
:Shown <- 3776.24.show{(:S)
  S.locale(LOCALE.for('da-DK'))
  S.spec(',d')
}
stdout.print_line(Shown.repr) # => "3.776,24"

An implementation of show_config type can also implement extra methods such as Num_show_config.radix and .pad_zero.

For example:

:Shown <- 255.show{(:S)
  S.radix(16)
  S.pad_zero(4)
}
stdout.print_line(Shown.repr) # => "00ff"

4.22.3.1. Show_config.locale(Locale_name)

`locale` method specifies the locale which is used to generate the result of `show` method.

Precondition:

• `Locale_name` must be a locale.

4.22.3.2. Show_config.spec(Spec)

`spec` method specifies how the val is converted to a str.

Precondition:

• `Spec` must be a str.

The syntax of `Spec` str varies among `show` method implementations.

4.22.4. STR.is?(Val)

`is?` returns whether `Val` is a str val.

4.22.5. STR.from_runes(Runes)

`from_runes` makes a str which contains the runes.

Precondition:

• `Runes` must be a sequence which support `each` method, such as vec or iter.

• Elements of `Runes` must be int nums in the range [0x000000, 0x10ffff].

Example using vec:

:STR.require_from('kink/')
:Str <- STR.from_runes([120 121 122])
stdout.print_line(Str.repr) # => "xyz"

Example using iter:

:ITER.require_from('kink/iter/')
:STR.require_from('kink/')
:Str <- STR.from_runes(ITER.of(120 121 122))
stdout.print_line(Str.repr) # => "xyz"

4.22.6. STR.default_newline

`default_newline` returns the line separator str default to the runtime.

The result is either "\r\n" or "\n".