Search code examples
crystal-lang

How do I get a word inside a file at given position?


How to get a word inside a file at given position

def get_word(file, position)
  File.each_line(file).with_index do |line, line_number|
    if (line_number + 1) == position.line_number
      # How to get a word at position.column_number ?
    end
  end
end

This should work like this:

File: message.md

Dear people:

My name is [Ángeliño](#angelino).

Bye!

Calls: get_word

record Position, line_number : Int32, column_number : Int32

get_word("message.md", Position.new(1, 9))  # => people
get_word("message.md", Position.new(3, 20)) # => Ángeliño
get_word("message.md", Position.new(5, 3))  # => Bye!

Solution

  • Maybe, this will give you a hint. Please, be advised that this implementation never treats a punctuation mark as a part of a word, so the last example returns Bye instead of Bye!.

    def get_word_of(line : String, at position : Int)
      chunks = line.split(/(\p{P}|\p{Z})/)
    
      edge = 0
      hashes = chunks.map do |chunk|
        next if chunk.empty?
        {chunk => (edge + 1)..(edge += chunk.size)}
      end.compact
    
      candidate = hashes.find { |hash| hash.first_value.covers?(position) }
                        .try &.first_key
    
      candidate unless (candidate =~ /\A(?:\p{P}|\p{Z})+\Z/)
    end
    
    p get_word_of("Dear people:", 9)                       # => people
    p get_word_of("My name is [Ángeliño](#angelino).", 20) # => Ángeliño
    p get_word_of("Bye!", 3)                               # => Bye