class Object
Constants
- CRYPTIC_DEFAULT_SHEETS
- CRYPTIC_LESS_HOME
Public Instance Methods
# File bin/cr, line 49 def add_default_sheet_if_none_exist unless is_there_any_sheet? puts "cr: first installed, add default sheet..." CRYPTIC_DEFAULT_SHEETS.values.each do |sheet| `git -C #{CRYPTIC_LESS_HOME} clone #{sheet}` end puts "cr: Done" end end
# File bin/cr, line 31 def blue(str) "\e[34m#{str}\e[0m" end
helper: for color
# File bin/cr, line 26 def bold(str) "\e[1m#{str}\e[0m" end
# File bin/cr, line 33 def cyan(str) "\e[36m#{str}\e[0m" end
Used for synonym jump Because we absolutely jump to a must-have word So we can directly lookup to it
Notice that, we must jump to a specific word definition So in the toml file, you must specify the precise word. If it has multiple meanings, for example
[blah] same = "XDG" # this is wrong [blah] same = "XDG.Download" # this is true
# File bin/cr, line 136 def directly_lookup(sheet,file,word) dict = load_dictionary(sheet,file.downcase) words = word.split('.') # [XDG Download] word = words.shift # XDG [Download] explain = words.first if explain.nil? info = dict[word] else info = dict[word][explain] end # Warn user this is the toml maintainer's fault if info.nil? puts red("WARN: Synonym jumps to a wrong place at `#{word}` Please consider fixing this in `#{file.downcase}.toml` of the sheet `#{sheet}`") exit end pp_info(word,info) return true # always true end
# File bin/cr, line 29 def green(str) "\e[32m#{str}\e[0m" end
# File bin/cr, line 281 def help puts <<-HELP cr: Cryptic Resolver. usage: cr -h => print this help cr -u (xx.com//repo.git) => update default sheet or add sheet from a git repo cr emacs => Edit macros: a feature-rich editor HELP end
core: logic
# File bin/cr, line 40 def is_there_any_sheet? unless Dir.exist? CRYPTIC_LESS_HOME Dir.mkdir CRYPTIC_LESS_HOME end !Dir.empty? CRYPTIC_LESS_HOME end
# File bin/cr, line 78 def load_dictionary(path,file) file = CRYPTIC_LESS_HOME + "/#{path}/#{file}.toml" if File.exist? file return Tomlrb.load_file file # gem 'tomlrb' # return TOML.load_file file # gem 'toml' else nil end end
Lookup the given word in a dictionary (a .toml file in a sheet) The core idea is that:
-
load the toml file and check whether it has the only one meaning.
1.1 If yes, then just print it using `pp_info` 1.2 If not, then collect all the meanings of the word, and use `pp_info`
-
if the word is `same` with another synonym, it will directly jump to
a word in this sheet, but maybe a different dictionary
# File bin/cr, line 167 def lookup(sheet, file, word) # only one meaning dict = load_dictionary(sheet,file) return false if dict.nil? # We want keys in toml be case-insenstive. # So we only can use array to find them, but this may leave performance problem when data grows. # If we use hash, the toml keys must be downcase, the situation where we really avoid. word = dict.keys.select {|k| k.downcase == word} .first info = dict[word] return false if info.nil? # Warn user if the info is empty. For example: # Emacs = { } if info.size == 0 puts red("WARN: Lack of everything of the given word Please consider fixing this in the sheet `#{sheet}`") exit end # Check whether it's a synonym for anther # If yes, we should lookup into this sheet again, but maybe # with a different file if same = info['same'] pp_sheet(sheet) # point out to user, this is a jump puts blue(bold(word)) + ' redirects to ' + blue(bold(same)) if same.chr.downcase == file # no need to load dictionary again pp_info(same,dict[same]) return true else return directly_lookup(sheet, same.chr, same) end end if info.has_key?('desc') pp_sheet(sheet) pp_info(word,info) return true end # multiple meanings in one sheet info = info.keys unless info.empty? pp_sheet(sheet) info.each do |meaning| pp_info(word,dict[word][meaning]) # last meaning doesn't show this separate line print "\n", blue(bold("OR")),"\n" unless info.last == meaning end return true else return false end end
Pretty print the info of the given word
A info looks like this
Emacs = { desc = "edit macros" full = "a feature-rich editor" see = ["Vim"] }
@param word [String] the keyword in TOML which matches with user's request @param info [Hash] the information of the given word (mapped to a keyword in TOML)
# File bin/cr, line 101 def pp_info(word,info) puts "\n #{word}: #{info['desc']}" if full = info['full'] print "\n ",full,"\n" end if see_also = info['see'] print "\n", purple("SEE ALSO ") see_also.each {|x| print underline(x),' '} puts end end
Make duplicatins a function
# File bin/cr, line 116 def pp_sheet(sheet) unless sheet.start_with?('cryptic_') puts green("sheet: #{sheet}") end end
# File bin/cr, line 32 def purple(str) "\e[35m#{str}\e[0m" end
# File bin/cr, line 28 def red(str) "\e[31m#{str}\e[0m" end
The core algorithm of `cr`
-
Search the default's first sheet first
-
Search the rest sheets in the cryptic sheets default dir
The `search` procedure is done via the `lookup` function. It will print the info while finding. If `lookup` always return false then means lacking of this word in our sheets.So a wel- comed contribution is prinetd on the screen.
# File bin/cr, line 235 def solve_word(word) add_default_sheet_if_none_exist word = word.downcase # downcase! would lead to frozen error in Ruby 2.7.2 # The index is the toml file we'll look into index = word.chr case index when '0'..'9' index = '0123456789' end # Default's first should be 1st to consider first_sheet = "cryptic_" + CRYPTIC_DEFAULT_SHEETS.keys[0].to_s # When Ruby3, We can use SHEETS.key(0) # cache lookup results results = [] results << lookup(first_sheet,index,word) # return if result == true # We should consider all sheets # Then else rest = Dir.children(CRYPTIC_LESS_HOME) rest.delete first_sheet rest.each do |sheet| results << lookup(sheet,index,word) # continue if result == false # We should consider all sheets end unless results.include? true puts <<-NotFound cr: Not found anything. You may use `cr -u` to update the sheets. Or you could contribute to our sheets: Thanks! computer: #{CRYPTIC_DEFAULT_SHEETS[:computer]} NotFound else return end end
# File bin/cr, line 27 def underline(str) "\e[4m#{str}\e[0m" end
# File bin/cr, line 60 def update_sheets(sheet_repo) return if false == is_there_any_sheet? if sheet_repo.nil? Dir.chdir CRYPTIC_LESS_HOME do Dir.children(CRYPTIC_LESS_HOME).each do |sheet| puts "cr: Wait to update #{sheet}..." `git -C ./#{sheet} pull` end end else `git -C #{CRYPTIC_LESS_HOME} clone #{sheet_repo}` end puts "cr: Done" end
# File bin/cr, line 30 def yellow(str) "\e[33m#{str}\e[0m" end