Class: Todoloo::Parser
- Inherits:
-
Parslet::Parser
- Object
- Parslet::Parser
- Todoloo::Parser
- Defined in:
- lib/todoloo/parser.rb
Overview
Constant Summary collapse
- TASK_TYPES =
%w[TODO NOTE FIXME HBD HACK XXX]
- MIN_INDENTATION_BEYOND_TYPE_START =
1
Class Method Summary collapse
-
.rule(name, *args, **kwargs, &block) ⇒ Object
Extension to automatically define ‘?` predicate rules.
Instance Method Summary collapse
-
#column_offset_of_capture(name, context) ⇒ Object
Calculates zero-based column offset for the given capture.
- #comment_continuation ⇒ Object
- #ignore_code_text(parser, count) ⇒ Object
- #indentation(parser, count) ⇒ Object
-
#parse_and_transform(text, path: "") ⇒ Object
Returns a list of tasks.
- #safe_parse(text) ⇒ Object
Class Method Details
.rule(name, *args, **kwargs, &block) ⇒ Object
Extension to automatically define ‘?` predicate rules
28 29 30 31 32 33 34 35 |
# File 'lib/todoloo/parser.rb', line 28 def self.rule(name, *args, **kwargs, &block) if name.to_s.end_with?("?") super else super # Define the original rule super("#{name}?") { public_send(name).maybe } end end |
Instance Method Details
#column_offset_of_capture(name, context) ⇒ Object
Calculates zero-based column offset for the given capture. Use only within dynamic blocks
115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/todoloo/parser.rb', line 115 def column_offset_of_capture(name, context) case name when :type # FIXME: Not sure yet why this is even necessary... _, col_index = context.captures[:type][:type].line_and_column else _, col_index = context.captures[name].line_and_column end col_index - 1 end |
#comment_continuation ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/todoloo/parser.rb', line 88 def comment_continuation dynamic do |_source, context| parser = match('[\n]') comment_start = column_offset_of_capture(:comment_start, context) # Match any non comment content before the comment starts parser = ignore_code_text(parser, comment_start) # Consume the characther that the comment opened with, like a `#` or `//` parser >>= str(context.captures[:comment_start]).ignore parser >>= (spacing? >> task_type).absent? required_indentation = column_offset_of_capture(:type, context) - comment_start - context.captures[:comment_start].length + MIN_INDENTATION_BEYOND_TYPE_START parser = indentation(parser, required_indentation) # parser >>= task_type.absent? parser >>= description_text parser end end |
#ignore_code_text(parser, count) ⇒ Object
127 128 129 130 131 132 133 |
# File 'lib/todoloo/parser.rb', line 127 def ignore_code_text(parser, count) if count.positive? parser >> code_text.repeat(count, count).ignore else parser end end |
#indentation(parser, count) ⇒ Object
135 136 137 138 139 |
# File 'lib/todoloo/parser.rb', line 135 def indentation(parser, count) return parser unless count.positive? parser >> space.repeat(count, count) end |
#parse_and_transform(text, path: "") ⇒ Object
Returns a list of tasks
8 9 10 11 12 13 14 15 16 17 18 |
# File 'lib/todoloo/parser.rb', line 8 def parse_and_transform(text, path: "") tree = parse(text) pp tree if Todoloo.debug? Transformer.new.apply(tree).map do |hash| line, column = hash.fetch(:type).line_and_column Task.from_hash(hash.merge(path: path, line: line, column: column)) end end |
#safe_parse(text) ⇒ Object
20 21 22 23 24 25 |
# File 'lib/todoloo/parser.rb', line 20 def safe_parse(text) parse(text) rescue Parslet::ParseFailed => e puts e.parse_failure_cause.ascii_tree nil end |