Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle array access syntax on strings with emoji #34

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions motion/core_ext/string/access.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,33 @@ def last(limit = 1)
from(-limit)
end
end

# Emojis pose a problem for array-like access of a string. If you try to
# grab one register you'll get am error: "You can't cut a surrogate in two in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "you'll get am error"

# an encoding that is not UTF-16 (IndexError)"
# Calling split(''), which splits the string into array of characters, works
# correctly even with emojis. So to make this method work as expected for
# strings, first split it then join.

# These are the method definitions of String#[]. The first three match the
# method definition of an array so only apply the patch if the arguments
# look like that.
# - str[index] => new_str or nil
# - str[start, length] => new_str or nil
# - str[range] => new_str or nil
# - str[regexp] => new_str or nil
# - str[regexp, capture] => new_str or nil
# - str[match_str] => new_str or nil
alias_method :bracket_access_original, :[]

def [](*args)
unless args[0].is_a?(Numeric) || args[0].is_a?(Range)
return bracket_access_original(*args)
end

# Could be nil, string (one character), or array of characters
characters = split('')[*args]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a test for each of those three cases?


characters.is_a?(Array) ? characters.join : characters
end
end
5 changes: 5 additions & 0 deletions spec/motion-support/core_ext/string/access_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,10 @@
hash["hello123".first(5)] = true
hash.keys.should == %w(hello)
end

it "should handle emojis" do
"😊 hello"[0].should == "😊"
"😊 hello".last(5).should == "hello"
end
end
end