import "luxe: string" for Str class StringUtil{ static directions{ if(!__directions){ var step_names = ["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"] __directions= step_names.map{|short| var shorts = "NESW" var base_directions = ["north","east","south","west"] if(short.count == 1){ return base_directions[shorts.indexOf(short)] } else if(short.count == 2) { return base_directions[shorts.indexOf(short[0])] + base_directions[shorts.indexOf(short[1])] } else { //assume 3 return base_directions[shorts.indexOf(short[0])] + "-" + base_directions[shorts.indexOf(short[1])] + base_directions[shorts.indexOf(short[2])] } }.toList } return __directions } static possesive(string){ if(string.endsWith("s")){ return "%(string)'" } else { return "%(string)'s" } } static plural(string){ if(string.endsWith("s")){ return "%(string)'" } else { return "%(string)s" } } //todo: this doesnt cover all cases perfectly, add more static a(string){ var firstChar = string[0] if(is_vowel(firstChar)){ return "an %(string)" } else { return "a %(string)" } } static is_vowel(char){ return "aeiou".contains(char) } static direction(index){ return directions[index] } //checks if a character (as codepoint is lowercase) static is_lower(char){ return Str.compare(Str.upper(char), char) != 0 } //checks if a character (as codepoint is uppercase) static is_upper(char){ return Str.compare(Str.lower(char), char) != 0 } static is_letter(char){ return is_lower(char) || is_upper(char) } static capitalize(string){ return Str.upper(string[0]) + string[1..-1] } //todo: this ignores words that arent preceeded by a space like (this) or "this". maybe fix that? static capitalize_all(string){ //split by words/stuff between words and capitalize everything, //capitalize function doesnt know what to do with separators so it wont touch them return WordSequence.new(string).map{|word| capitalize(word)}.join() } } class WordSequence is Sequence{ static new(string){ return new(string) {|c| return StringUtil.is_letter(c) } } construct new(string, letterCheck){ _string = string _check = letterCheck } iterate(iterator){ if(!iterator) iterator = [-1, -1, false] //fake value from -1 to -1 if(iterator[1] >= _string.count-1) return false //abort when at end var start = iterator[1]+1 var is_word = StringUtil.is_letter(_string[start]) var end = start + 1 //count up until you find something thats not a word/separator depending on what the first letter was while(end < _string.count && StringUtil.is_letter(_string[end]) == is_word){ end = end + 1 } end = end - 1 return [start, end, is_word] } iteratorValue(iterator){ return _string[iterator[0]..iterator[1]] } }