# assert "\na\nb\tc\t".trim == "a\nb\tc"
fun trim: SELFTYPE do return (self.l_trim).r_trim
- # Returns `self` removed from its last `\n` (if any).
+ # Returns `self` removed from its last line terminator (if any).
#
# assert "Hello\n".chomp == "Hello"
# assert "Hello".chomp == "Hello"
- # assert "\n\n\n".chomp == "\n\n"
#
- # This method is mainly used to remove the LINE_FEED character from lines of text.
+ # assert "\n".chomp == ""
+ # assert "".chomp == ""
+ #
+ # Line terminators are `"\n"`, `"\r\n"` and `"\r"`.
+ # A single line terminator, the last one, is removed.
+ #
+ # assert "\r\n".chomp == ""
+ # assert "\r\n\n".chomp == "\r\n"
+ # assert "\r\n\r\n".chomp == "\r\n"
+ # assert "\r\n\r".chomp == "\r\n"
+ #
+ # Note: unlike with most IO methods like `IStream::read_line`,
+ # a single `\r` is considered here to be a line terminator and will be removed.
fun chomp: SELFTYPE
do
- if self.chars.last != '\n' then return self
- return substring(0, length-1)
+ var len = length
+ if len == 0 then return self
+ var l = self.chars.last
+ if l == '\r' then
+ return substring(0, len-1)
+ else if l != '\n' then
+ return self
+ else if len > 1 and self.chars[len-2] == '\r' then
+ return substring(0, len-2)
+ else
+ return substring(0, len-1)
+ end
end
# Justify a self in a space of `length`
return " " * before + self + " " * (diff-before)
end
- # Mangle a string to be a unique string only made of alphanumeric characters
+ # Mangle a string to be a unique string only made of alphanumeric characters and underscores.
+ #
+ # This method is injective (two different inputs never produce the same
+ # output) and the returned string always respect the following rules:
+ #
+ # * Contains only US-ASCII letters, digits and underscores.
+ # * Never starts with a digit.
+ # * Never ends with an underscore.
+ # * Never contains two contiguous underscores.
+ #
+ # assert "42_is/The answer!".to_cmangle == "_52d2_is_47dThe_32danswer_33d"
+ # assert "__".to_cmangle == "_95d_95d"
+ # assert "__d".to_cmangle == "_95d_d"
+ # assert "_d_".to_cmangle == "_d_95d"
+ # assert "_42".to_cmangle == "_95d42"
+ # assert "foo".to_cmangle == "foo"
+ # assert "".to_cmangle == ""
fun to_cmangle: String
do
+ if is_empty then return ""
var res = new FlatBuffer
var underscore = false
- for i in [0..length[ do
- var c = chars[i]
+ var start = 0
+ var c = chars[0]
+
+ if c >= '0' and c <= '9' then
+ res.add('_')
+ res.append(c.ascii.to_s)
+ res.add('d')
+ start = 1
+ end
+ for i in [start..length[ do
+ c = chars[i]
if (c >= 'a' and c <= 'z') or (c >='A' and c <= 'Z') then
res.add(c)
underscore = false
underscore = false
end
end
+ if underscore then
+ res.append('_'.ascii.to_s)
+ res.add('d')
+ end
return res.to_s
end