Class: RemLint::Rules::UnknownSubstitutionSequence
- Inherits:
-
RemLint::Rule
- Object
- RemLint::Rule
- RemLint::Rules::UnknownSubstitutionSequence
- Defined in:
- lib/remlint/rules/unknown_substitution_sequence.rb
Overview
% sequences Remind does not substitute.
Narrower than it first looks, and the narrowing is worth stating. The set
in dosubst.c is closed but wide: the switch is on UPPER(c), and
every one of the twenty-six letters and all ten digits is a case. So
there is no %z typo to catch -- %z is the seconds-since-epoch
sequence. What is left to report is punctuation, and the argument forms
that were opened and never closed.
It is worth reporting because the failure is invisible. The default:
branch emits the character and drops the percent: %~ prints ~, with
no error, no warning, and nothing to distinguish it from text somebody
meant to type.
Four sequences take an argument rather than a single character, and all four are recognised here so their contents are not mistaken for the sequence itself:
%<Header> an INFO header (silently empty when absent)
%{name} calls subst_name (warns only at warning level 05.00.03)
%(text) a translated string
%*x the alternate-mode modifier, then a real sequence
Leaving one of the first three unterminated is a warning from Remind at run time; reporting it here says the same thing without running the file.
A % at the very end of a body is not an error. It suppresses the
newline Remind would otherwise append -- dosubst("hello") is six
characters and dosubst("hello%") is five (remind.1: "if str does not
end with %, a newline character will be added"). Remind's own
tests/test.rem ends 160 bodies that way.
Only reminder bodies are checked. Elsewhere on a line a % is an
ordinary character -- BANNER % is the idiom for no banner at all.
Constant Summary collapse
- LETTERS =
From the
switch (UPPER(c))in src/dosubst.c. Every letter and every digit is a case; the punctuation is the part that is actually a set. ("A".."Z").to_a.freeze
- DIGITS =
("0".."9").to_a.freeze
- PUNCTUATION =
%w[! ? @ # : _ "].freeze
- LITERAL_PERCENT =
%%has no case of its own, but the default branch emits the second%-- so it is the working way to write a literal percent, and reporting it would be reporting the fix. "%"- SIMPLE =
(LETTERS + DIGITS + PUNCTUATION + [LITERAL_PERCENT]).freeze
- TRAILING =
A trailing
%suppresses the newline; the regex reports it as an empty body, because there is no character after the percent to report. ""- UNTERMINATED =
An opener with no closer before end of body. Remind warns about each of these at run time ("Unterminated %<...> substitution sequence").
{ "<" => ">", "{" => "}", "(" => ")" }.freeze
- SEQUENCE =
The whole sequence, in every form, so the scan advances past an argument rather than stopping inside it.
/%(?<modifier>\*?)(?<body><[^>]*>|\{[^}]*\}|\([^)]*\)|.|\z)/- ARGUMENT_FORMS =
/\A[<{(]/
Constants inherited from RemLint::Rule
Instance Attribute Summary
Attributes inherited from RemLint::Rule
Class Method Summary collapse
Instance Method Summary collapse
Methods inherited from RemLint::Rule
all, enabled_by_default?, find, inherited, #initialize, rule_name, #rule_name, #run
Constructor Details
This class inherits a constructor from RemLint::Rule
Class Method Details
.default_severity ⇒ Object
69 70 71 |
# File 'lib/remlint/rules/unknown_substitution_sequence.rb', line 69 def self.default_severity "warning" end |
.description ⇒ Object
73 74 75 |
# File 'lib/remlint/rules/unknown_substitution_sequence.rb', line 73 def self.description "A % sequence in a reminder body that Remind does not substitute." end |
Instance Method Details
#check ⇒ Object
77 78 79 80 81 82 83 84 85 |
# File 'lib/remlint/rules/unknown_substitution_sequence.rb', line 77 def check document.code_commands.each do |command| body = body_of(command) if body report(command, body.fetch(:text), body.fetch(:offset)) end end end |