Comments (2)
Yes, truncating a string to a certain length including the omission string is the most common use case, I'd say.
Sometimes I could even use something like .truncate_inspect
that returns "truncated_string"...
, i.e. the omission string (if applicable) goes after the .truncate
d and .inspect
ed string.
Probably be a niche case, where you really need to make clear what was part of the original string and what wasn't.
from crystal.
I'm proposing something like this.
Maybe there should be an option to not break Unicode grapheme clusters, regional indicators, flag sequences, tag sequences and whatnot.
class String
# Truncates the string to a given length *`truncate_to`*.
#
# The last characters will be replaced with the *`omission`* string
# (defaults to '`…`') if necessary. The total length will not exceed
# *`truncate_to`*.
#
# Optionally pass a `Char`, `String` or `Regex` separator *`sep`*, such as
# `/\b/` (word boundary), to truncate text at a natural break.
# Optionally set *`sep_max_lose`* to the maximum number of characters you
# want to lose by cutting at a natural break. Otherwise a cut will still be
# made at an arbitrary position. (Defaults to `nil`.)
# Also see `.truncate_at_word_boundary` for truncating a string at word
# boundaries.
#
# Raises `ArgumentError` if *`truncate_to`* < 1.
#
# Raises `ArgumentError` if *`truncate_to`* < the length of the omission
# string.
#
# Raises `ArgumentError` if *`sep_max_lose`* is < 0 (and separator *`sep`*
# is specified).
#
def truncate(
truncate_to : Int32,
*,
omission : (Char | String)? = '…',
sep : (Char | String | Regex)? = nil,
sep_max_lose : Int32? = nil,
) : String
return self if size <= truncate_to # no need to truncate
if truncate_to < 1
raise ArgumentError.new "Invalid truncate value: #{truncate_to}"
end
omission_len = case omission
when Char ; 1
when String; omission.size
when Nil ; 0
else raise "Invalid omission of type #{typeof(omission)}."
end
if truncate_to < omission_len
raise ArgumentError.new "Can't truncate to #{truncate_to} when the omission has #{omission_len} characters (#{omission.inspect})."
end
cut_len = truncate_to - omission_len # length with room for omission
if sep
sep_pos = rindex( sep, cut_len )
if sep_max_lose && sep_max_lose.negative?
raise ArgumentError.new "sep_max_lose must not be negative."
end
if sep_pos && ((! sep_max_lose) || (sep_pos >= cut_len - sep_max_lose))
cut_len = sep_pos
end
end
return String.build( cut_len + omission_len ){ |s|
s << self[ 0, cut_len ]
s << omission if omission
}
end
# Truncates the string to a given length *`truncate_to`*, trying to respect word boundaries.
#
# See *`.truncate`* for details and exceptions.
#
def truncate_at_word_boundary( truncate_to : Int32, *, omission : String = "…", sep_max_lose : Int32? = 10 )
return truncate( truncate_to, omission: omission, sep: /\b/, sep_max_lose: sep_max_lose )
end
end
from crystal.
Related Issues (20)
- Huge `JSON::ParseException` HOT 5
- `Number#humanize` and `Int#humanize_bytes` should separate number and unit by a space HOT 1
- Regression: Interrupted system call in CI HOT 6
- Is an html strip-tags method a worth stdlib addition? HOT 7
- Unwinding is slow on WSL HOT 8
- add something like ruby un.rb or cmake -E for cross platform scripts HOT 3
- regression: XPath swallows errors and raises opaque `error in [...] expression` instead HOT 1
- Debugging Windows binaries with LLDB doesn't break on access violation
- Manage compiler dependencies with `shards` HOT 6
- Passing `Proc`s with non-default calling conventions across libs HOT 4
- Standardizing the type for timeout values HOT 1
- Symbol casting to Enums does not work in subclass initializers HOT 5
- OpenSSL errors that don't involve `ERR_get_error`
- Config requirements for LLVM bindings
- Return type of `unbuffered_read`/`unbuffered_write` HOT 2
- Inconsistent `JSON::Serializable` behavior when parsing case-sensitive `Enum`s HOT 3
- Compiler complains that an implemented abstract module method must be implemented when calling `super` HOT 2
- Introduce platform-specific `FileDescriptor::Handle` HOT 4
- Explicitly returning a lib struct or tuple inside a `fun` results in a codegen error
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from crystal.