Module: RemLint::Vocabulary

Defined in:
lib/remlint/vocabulary.rb

Overview

Lookups over the generated tables, reproducing Remind's own resolution rules rather than approximating them.

The three rules differ from each other, and each difference is a bug class if you get it wrong:

keywords   case-insensitive, abbreviable to a per-keyword minimum length
         (src/token.c FindToken)
functions  case-insensitive, exact -- no abbreviation
         (src/funcs.c FindBuiltinFunc)
$SysVars   case-insensitive, exact -- no abbreviation
         (src/var.c FindSysVar)

Defined Under Namespace

Classes: Function, Keyword, SysVar

Constant Summary collapse

CLAUSE_TYPES =

The clause keywords -- UNTIL, AT, WARN and so on -- appear inside a trigger rather than at the head of a line, so a rule looking at the first word of a command needs to tell the two apart.

%w[
  T_Month T_WkDay T_Ordinal T_Skip T_At T_Duration T_Until T_Warn
  T_Sched T_Scanfrom T_Through T_Once T_Priority T_Tag T_In T_Tz
  T_BackAdj T_Info T_NoQueue T_MaxOverdue T_CompleteThrough
  T_MaybeUncomputable T_OmitFunc
].freeze
KEYWORDS =
Tables::KEYWORD_ROWS.map { |row| Keyword.new(*row).freeze }.freeze
FUNCTIONS =
Tables::FUNCTION_ROWS.to_h do |row|
  function = Function.new(*row).freeze

  [function.name, function]
end.freeze
SYSVARS =
Tables::SYSVAR_ROWS.to_h do |row|
  sysvar = SysVar.new(*row).freeze

  [sysvar.name.downcase, sysvar]
end.freeze
KEYWORD_CACHE =
{}

Class Method Summary collapse

Class Method Details

.function(name) ⇒ Object



127
128
129
# File 'lib/remlint/vocabulary.rb', line 127

def function(name)
  FUNCTIONS[name.to_s.downcase]
end

.keyword(word) ⇒ Object

Resolve one whitespace-delimited word the way FindToken does: the first entry in table order whose name the word prefixes, provided the word is at least that entry's minimum abbreviation length. A trailing comma is ignored, as Remind's TokStrCmp ignores it.



111
112
113
114
115
116
117
118
119
# File 'lib/remlint/vocabulary.rb', line 111

def keyword(word)
  needle = word.to_s.downcase.delete_suffix(",")

  if needle.empty?
    nil
  else
    KEYWORD_CACHE.fetch(needle) { KEYWORD_CACHE[needle] = resolve(needle) }
  end
end

.resolve(needle) ⇒ Object



121
122
123
124
125
# File 'lib/remlint/vocabulary.rb', line 121

def resolve(needle)
  KEYWORDS.find do |candidate|
    needle.length >= candidate.minlen && candidate.name.downcase.start_with?(needle)
  end
end

.sysvar(name) ⇒ Object



131
132
133
# File 'lib/remlint/vocabulary.rb', line 131

def sysvar(name)
  SYSVARS[name.to_s.delete_prefix("$").downcase]
end