demotape 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-tests.yml +1 -1
  3. data/.gitignore +8 -0
  4. data/CHANGELOG.md +6 -0
  5. data/CONTRIBUTING.md +2 -2
  6. data/README.md +19 -10
  7. data/editors/sublime-text/DemoTape.sublime-syntax +1 -1
  8. data/editors/vim/ftdetect/demotape.vim +1 -1
  9. data/editors/vim/syntax/demotape.vim +1 -1
  10. data/editors/vscode/LICENSE.md +20 -0
  11. data/editors/vscode/README.md +12 -2
  12. data/editors/vscode/RELEASE_PROCESS.md +10 -0
  13. data/editors/vscode/demotape.tmLanguage.json +7 -6
  14. data/editors/vscode/icon.png +0 -0
  15. data/editors/vscode/package.json +20 -4
  16. data/editors/zed/extension.toml +12 -0
  17. data/editors/zed/grammars/demotape.wasm +0 -0
  18. data/editors/zed/languages/demotape/config.toml +11 -0
  19. data/editors/zed/languages/demotape/highlights.scm +70 -0
  20. data/editors/zed/package-lock.json +6 -0
  21. data/editors/zed/tree-sitter/Cargo.toml +26 -0
  22. data/editors/zed/tree-sitter/binding.gyp +19 -0
  23. data/editors/zed/tree-sitter/bindings/node/binding.cc +28 -0
  24. data/editors/zed/tree-sitter/bindings/node/index.js +19 -0
  25. data/editors/zed/tree-sitter/bindings/rust/build.rs +40 -0
  26. data/editors/zed/tree-sitter/bindings/rust/lib.rs +52 -0
  27. data/editors/zed/tree-sitter/grammar.js +227 -0
  28. data/editors/zed/tree-sitter/package-lock.json +36 -0
  29. data/editors/zed/tree-sitter/package.json +27 -0
  30. data/editors/zed/tree-sitter/queries/highlights.scm +70 -0
  31. data/editors/zed/tree-sitter/src/grammar.json +1123 -0
  32. data/editors/zed/tree-sitter/src/node-types.json +862 -0
  33. data/editors/zed/tree-sitter/src/parser.c +9337 -0
  34. data/editors/zed/tree-sitter/src/tree_sitter/parser.h +224 -0
  35. data/exe/demotape +1 -0
  36. data/lib/demo_tape/cli.rb +10 -2
  37. data/lib/demo_tape/command.rb +1 -1
  38. data/lib/demo_tape/ext/thor.rb +17 -0
  39. data/lib/demo_tape/version.rb +1 -1
  40. metadata +28 -7
  41. data/demotape_new.y.backup +0 -160
  42. data/demotape_simple_test.y +0 -32
@@ -0,0 +1,224 @@
1
+ #ifndef TREE_SITTER_PARSER_H_
2
+ #define TREE_SITTER_PARSER_H_
3
+
4
+ #ifdef __cplusplus
5
+ extern "C" {
6
+ #endif
7
+
8
+ #include <stdbool.h>
9
+ #include <stdint.h>
10
+ #include <stdlib.h>
11
+
12
+ #define ts_builtin_sym_error ((TSSymbol)-1)
13
+ #define ts_builtin_sym_end 0
14
+ #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
15
+
16
+ typedef uint16_t TSStateId;
17
+
18
+ #ifndef TREE_SITTER_API_H_
19
+ typedef uint16_t TSSymbol;
20
+ typedef uint16_t TSFieldId;
21
+ typedef struct TSLanguage TSLanguage;
22
+ #endif
23
+
24
+ typedef struct {
25
+ TSFieldId field_id;
26
+ uint8_t child_index;
27
+ bool inherited;
28
+ } TSFieldMapEntry;
29
+
30
+ typedef struct {
31
+ uint16_t index;
32
+ uint16_t length;
33
+ } TSFieldMapSlice;
34
+
35
+ typedef struct {
36
+ bool visible;
37
+ bool named;
38
+ bool supertype;
39
+ } TSSymbolMetadata;
40
+
41
+ typedef struct TSLexer TSLexer;
42
+
43
+ struct TSLexer {
44
+ int32_t lookahead;
45
+ TSSymbol result_symbol;
46
+ void (*advance)(TSLexer *, bool);
47
+ void (*mark_end)(TSLexer *);
48
+ uint32_t (*get_column)(TSLexer *);
49
+ bool (*is_at_included_range_start)(const TSLexer *);
50
+ bool (*eof)(const TSLexer *);
51
+ };
52
+
53
+ typedef enum {
54
+ TSParseActionTypeShift,
55
+ TSParseActionTypeReduce,
56
+ TSParseActionTypeAccept,
57
+ TSParseActionTypeRecover,
58
+ } TSParseActionType;
59
+
60
+ typedef union {
61
+ struct {
62
+ uint8_t type;
63
+ TSStateId state;
64
+ bool extra;
65
+ bool repetition;
66
+ } shift;
67
+ struct {
68
+ uint8_t type;
69
+ uint8_t child_count;
70
+ TSSymbol symbol;
71
+ int16_t dynamic_precedence;
72
+ uint16_t production_id;
73
+ } reduce;
74
+ uint8_t type;
75
+ } TSParseAction;
76
+
77
+ typedef struct {
78
+ uint16_t lex_state;
79
+ uint16_t external_lex_state;
80
+ } TSLexMode;
81
+
82
+ typedef union {
83
+ TSParseAction action;
84
+ struct {
85
+ uint8_t count;
86
+ bool reusable;
87
+ } entry;
88
+ } TSParseActionEntry;
89
+
90
+ struct TSLanguage {
91
+ uint32_t version;
92
+ uint32_t symbol_count;
93
+ uint32_t alias_count;
94
+ uint32_t token_count;
95
+ uint32_t external_token_count;
96
+ uint32_t state_count;
97
+ uint32_t large_state_count;
98
+ uint32_t production_id_count;
99
+ uint32_t field_count;
100
+ uint16_t max_alias_sequence_length;
101
+ const uint16_t *parse_table;
102
+ const uint16_t *small_parse_table;
103
+ const uint32_t *small_parse_table_map;
104
+ const TSParseActionEntry *parse_actions;
105
+ const char * const *symbol_names;
106
+ const char * const *field_names;
107
+ const TSFieldMapSlice *field_map_slices;
108
+ const TSFieldMapEntry *field_map_entries;
109
+ const TSSymbolMetadata *symbol_metadata;
110
+ const TSSymbol *public_symbol_map;
111
+ const uint16_t *alias_map;
112
+ const TSSymbol *alias_sequences;
113
+ const TSLexMode *lex_modes;
114
+ bool (*lex_fn)(TSLexer *, TSStateId);
115
+ bool (*keyword_lex_fn)(TSLexer *, TSStateId);
116
+ TSSymbol keyword_capture_token;
117
+ struct {
118
+ const bool *states;
119
+ const TSSymbol *symbol_map;
120
+ void *(*create)(void);
121
+ void (*destroy)(void *);
122
+ bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
123
+ unsigned (*serialize)(void *, char *);
124
+ void (*deserialize)(void *, const char *, unsigned);
125
+ } external_scanner;
126
+ const TSStateId *primary_state_ids;
127
+ };
128
+
129
+ /*
130
+ * Lexer Macros
131
+ */
132
+
133
+ #define START_LEXER() \
134
+ bool result = false; \
135
+ bool skip = false; \
136
+ bool eof = false; \
137
+ int32_t lookahead; \
138
+ goto start; \
139
+ next_state: \
140
+ lexer->advance(lexer, skip); \
141
+ start: \
142
+ skip = false; \
143
+ lookahead = lexer->lookahead;
144
+
145
+ #define ADVANCE(state_value) \
146
+ { \
147
+ state = state_value; \
148
+ goto next_state; \
149
+ }
150
+
151
+ #define SKIP(state_value) \
152
+ { \
153
+ skip = true; \
154
+ state = state_value; \
155
+ goto next_state; \
156
+ }
157
+
158
+ #define ACCEPT_TOKEN(symbol_value) \
159
+ result = true; \
160
+ lexer->result_symbol = symbol_value; \
161
+ lexer->mark_end(lexer);
162
+
163
+ #define END_STATE() return result;
164
+
165
+ /*
166
+ * Parse Table Macros
167
+ */
168
+
169
+ #define SMALL_STATE(id) id - LARGE_STATE_COUNT
170
+
171
+ #define STATE(id) id
172
+
173
+ #define ACTIONS(id) id
174
+
175
+ #define SHIFT(state_value) \
176
+ {{ \
177
+ .shift = { \
178
+ .type = TSParseActionTypeShift, \
179
+ .state = state_value \
180
+ } \
181
+ }}
182
+
183
+ #define SHIFT_REPEAT(state_value) \
184
+ {{ \
185
+ .shift = { \
186
+ .type = TSParseActionTypeShift, \
187
+ .state = state_value, \
188
+ .repetition = true \
189
+ } \
190
+ }}
191
+
192
+ #define SHIFT_EXTRA() \
193
+ {{ \
194
+ .shift = { \
195
+ .type = TSParseActionTypeShift, \
196
+ .extra = true \
197
+ } \
198
+ }}
199
+
200
+ #define REDUCE(symbol_val, child_count_val, ...) \
201
+ {{ \
202
+ .reduce = { \
203
+ .type = TSParseActionTypeReduce, \
204
+ .symbol = symbol_val, \
205
+ .child_count = child_count_val, \
206
+ __VA_ARGS__ \
207
+ }, \
208
+ }}
209
+
210
+ #define RECOVER() \
211
+ {{ \
212
+ .type = TSParseActionTypeRecover \
213
+ }}
214
+
215
+ #define ACCEPT_INPUT() \
216
+ {{ \
217
+ .type = TSParseActionTypeAccept \
218
+ }}
219
+
220
+ #ifdef __cplusplus
221
+ }
222
+ #endif
223
+
224
+ #endif // TREE_SITTER_PARSER_H_
data/exe/demotape CHANGED
@@ -7,5 +7,6 @@ require_relative "../lib/demo_tape/cli"
7
7
  # `run` is reserved with thor 🫠🙄🤦‍♂️
8
8
  argv = ARGV.dup
9
9
  argv[0] = "_run" if argv[0] == "run"
10
+ argv[1] = "_run" if argv[1] == "run"
10
11
 
11
12
  DemoTape::CLI.start(argv)
data/lib/demo_tape/cli.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "thor"
4
+ require_relative "ext/thor"
4
5
  require "thor/completion"
5
6
 
6
7
  module DemoTape
@@ -144,8 +145,15 @@ module DemoTape
144
145
 
145
146
  if file_path == ""
146
147
  file_path = "<stdin>"
147
- content = $stdin.read
148
- options[:output_path] = "stdin.mp4" if options.output_path.empty?
148
+
149
+ if $stdin.tty?
150
+ help
151
+ exit 1
152
+ else
153
+ content = $stdin.read
154
+ end
155
+
156
+ options[:output_path] = ["stdin.mp4"] if options.output_path.empty?
149
157
  else
150
158
  content = File.read(file_path)
151
159
  end
@@ -15,7 +15,7 @@ module DemoTape
15
15
  "Ctrl" => :control,
16
16
  "Alt" => :alt,
17
17
  "Option" => :alt,
18
- "Pause" => :pause,
18
+ # "Pause" => :pause,
19
19
  "Escape" => :escape,
20
20
  "Esc" => :escape,
21
21
  "Space" => :space,
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor/parser/argument"
4
+
5
+ class Thor
6
+ class Argument
7
+ def print_default
8
+ if (@type == :array) && @default.is_a?(Array)
9
+ @default.map do |item|
10
+ item.respond_to?(:dump) ? item.dump : item
11
+ end.join(" ")
12
+ else
13
+ @default
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DemoTape
4
- VERSION = "0.0.3"
4
+ VERSION = "0.0.4"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: demotape
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
@@ -267,18 +267,38 @@ files:
267
267
  - demotape.jsonc
268
268
  - demotape.y
269
269
  - demotape_ascii.rb
270
- - demotape_new.y.backup
271
- - demotape_simple_test.y
272
270
  - editors/sublime-text/Comments (DemoTape).tmPreferences
273
271
  - editors/sublime-text/DemoTape.sublime-completions
274
272
  - editors/sublime-text/DemoTape.sublime-syntax
275
273
  - editors/vim/README.md
276
274
  - editors/vim/ftdetect/demotape.vim
277
275
  - editors/vim/syntax/demotape.vim
276
+ - editors/vscode/LICENSE.md
278
277
  - editors/vscode/README.md
278
+ - editors/vscode/RELEASE_PROCESS.md
279
279
  - editors/vscode/demotape.tmLanguage.json
280
+ - editors/vscode/icon.png
280
281
  - editors/vscode/language-configuration.json
281
282
  - editors/vscode/package.json
283
+ - editors/zed/extension.toml
284
+ - editors/zed/grammars/demotape.wasm
285
+ - editors/zed/languages/demotape/config.toml
286
+ - editors/zed/languages/demotape/highlights.scm
287
+ - editors/zed/package-lock.json
288
+ - editors/zed/tree-sitter/Cargo.toml
289
+ - editors/zed/tree-sitter/binding.gyp
290
+ - editors/zed/tree-sitter/bindings/node/binding.cc
291
+ - editors/zed/tree-sitter/bindings/node/index.js
292
+ - editors/zed/tree-sitter/bindings/rust/build.rs
293
+ - editors/zed/tree-sitter/bindings/rust/lib.rs
294
+ - editors/zed/tree-sitter/grammar.js
295
+ - editors/zed/tree-sitter/package-lock.json
296
+ - editors/zed/tree-sitter/package.json
297
+ - editors/zed/tree-sitter/queries/highlights.scm
298
+ - editors/zed/tree-sitter/src/grammar.json
299
+ - editors/zed/tree-sitter/src/node-types.json
300
+ - editors/zed/tree-sitter/src/parser.c
301
+ - editors/zed/tree-sitter/src/tree_sitter/parser.h
282
302
  - exe/demotape
283
303
  - lib/demo_tape.rb
284
304
  - lib/demo_tape/bounds.rb
@@ -286,6 +306,7 @@ files:
286
306
  - lib/demo_tape/command.rb
287
307
  - lib/demo_tape/duration.rb
288
308
  - lib/demo_tape/exporter.rb
309
+ - lib/demo_tape/ext/thor.rb
289
310
  - lib/demo_tape/formatter.rb
290
311
  - lib/demo_tape/generator.rb
291
312
  - lib/demo_tape/lexer.rb
@@ -670,10 +691,10 @@ metadata:
670
691
  rubygems_mfa_required: 'true'
671
692
  homepage_uri: https://github.com/fnando/demotape
672
693
  bug_tracker_uri: https://github.com/fnando/demotape/issues
673
- source_code_uri: https://github.com/fnando/demotape/tree/v0.0.3
674
- changelog_uri: https://github.com/fnando/demotape/tree/v0.0.3/CHANGELOG.md
675
- documentation_uri: https://github.com/fnando/demotape/tree/v0.0.3/README.md
676
- license_uri: https://github.com/fnando/demotape/tree/v0.0.3/LICENSE.md
694
+ source_code_uri: https://github.com/fnando/demotape/tree/v0.0.4
695
+ changelog_uri: https://github.com/fnando/demotape/tree/v0.0.4/CHANGELOG.md
696
+ documentation_uri: https://github.com/fnando/demotape/tree/v0.0.4/README.md
697
+ license_uri: https://github.com/fnando/demotape/tree/v0.0.4/LICENSE.md
677
698
  rdoc_options: []
678
699
  require_paths:
679
700
  - lib
@@ -1,160 +0,0 @@
1
- class DemoTape::Parser
2
- rule
3
- # Top level: document is a flat list of tokens and contexts
4
- document: items { result = val[0].flatten.compact }
5
- | /* empty */ { result = [] }
6
-
7
- items: item { result = [val[0]] }
8
- | items item { result = val[0] << val[1] }
9
-
10
- # An item can be a token or a context
11
- item: COMMENT { result = make_token(:comment, val[0], @token_index - 1) }
12
- | NEWLINE { result = make_token(:newline, val[0], @token_index - 1) }
13
- | LEADING_SPACE { result = make_token(:leading_space, val[0], @token_index - 1) }
14
- | TRAILING_SPACE { result = make_token(:trailing_space, val[0], @token_index - 1) }
15
- | command_line { result = val[0] }
16
- | group_context { result = val[0] }
17
-
18
- # A command line: tokens terminated by newline
19
- command_line: command_tokens NEWLINE {
20
- result = [{
21
- type: :command,
22
- tokens: val[0],
23
- line: line_for_token_at(@command_start_index),
24
- column: column_for_token_at(@command_start_index)
25
- }, make_token(:newline, val[1], @token_index - 1)]
26
- }
27
-
28
- leading_space: LEADING_SPACE { result = make_token(:leading_space, val[0], @token_index - 1) }
29
-
30
- trailing_space: TRAILING_SPACE { result = make_token(:trailing_space, val[0], @token_index - 1) }
31
-
32
- # Group context: Group name do ... end
33
- group_context: IDENTIFIER SPACE IDENTIFIER SPACE DO NEWLINE group_body END {
34
- @command_start_index = @token_index - 8
35
- result = {
36
- type: :group,
37
- name: val[2],
38
- tokens: [
39
- make_token(:identifier, val[0], @token_index - 8),
40
- make_token(:space, val[1], @token_index - 7),
41
- make_token(:identifier, val[2], @token_index - 6),
42
- make_token(:space, val[3], @token_index - 5),
43
- make_token(:keyword, "do", @token_index - 4)
44
- ],
45
- body: val[6],
46
- line: line_for_token_at(@token_index - 8),
47
- column: column_for_token_at(@token_index - 8)
48
- }
49
- }
50
-
51
- group_body: /* empty */ { result = [] }
52
- | group_body item { result = val[0] << val[1] }
53
-
54
- # Command tokens: any sequence of tokens until newline
55
- command_tokens: command_token { @command_start_index = @token_index - 1; result = [val[0]] }
56
- | command_tokens SPACE command_token { result = val[0] << make_token(:space, val[1], @token_index - 2) << val[2] }
57
- | command_tokens optional_space COMMA optional_space command_token {
58
- result = val[0]
59
- result << make_token(:space, val[1], @token_index - 4) if val[1]
60
- result << make_token(:operator, ",", @token_index - 3)
61
- result << make_token(:space, val[3], @token_index - 2) if val[3]
62
- result << val[4]
63
- }
64
- | command_tokens PLUS command_token {
65
- result = val[0] << make_token(:operator, "+", @token_index - 2) << val[2]
66
- }
67
- | command_tokens AT duration {
68
- result = val[0] << make_token(:operator, "@", @token_index - 2) << val[2]
69
- }
70
-
71
- optional_space: SPACE { result = val[0] }
72
- | /* empty */ { result = nil }
73
-
74
- command_token: IDENTIFIER { result = make_token(:identifier, val[0], @token_index - 1) }
75
- | STRING { result = make_token(:string, val[0], @token_index - 1) }
76
- | NUMBER { result = make_token(:number, val[0], @token_index - 1) }
77
- | REGEX { result = make_token(:regex, val[0], @token_index - 1) }
78
-
79
- duration: NUMBER TIME_UNIT {
80
- result = make_token(:duration, "#{val[0]}#{val[1]}", @token_index - 2)
81
- }
82
-
83
- ---- header
84
- require_relative "token"
85
- require_relative "lexer"
86
- require_relative "ast"
87
-
88
- ---- inner
89
- def parse(str, file: "<unknown>")
90
- @file = file
91
- @lexer = DemoTape::Lexer.new
92
- @tokens = @lexer.tokenize(str)
93
- @token_index = 0
94
- do_parse
95
- end
96
-
97
- def next_token
98
- token = @tokens.shift
99
- @current_token_index = @token_index
100
- @token_index += 1
101
- token
102
- end
103
-
104
- def make_token(type, value, index)
105
- line_info = @lexer.line_map[index] || {}
106
- token_class = case type
107
- when :identifier then DemoTape::Token::Identifier
108
- when :string then DemoTape::Token::String
109
- when :number then DemoTape::Token::Number
110
- when :duration then DemoTape::Token::Duration
111
- when :regex then DemoTape::Token::Regex
112
- when :time_unit then DemoTape::Token::TimeUnit
113
- when :operator then DemoTape::Token::Operator
114
- when :space then DemoTape::Token::Space
115
- when :leading_space then DemoTape::Token::LeadingSpace
116
- when :trailing_space then DemoTape::Token::TrailingSpace
117
- when :keyword then DemoTape::Token::Keyword
118
- when :comment then DemoTape::Token::Comment
119
- when :newline then DemoTape::Token::Newline
120
- else DemoTape::Token::Base
121
- end
122
-
123
- token_class.new(
124
- value,
125
- line: line_info[:line],
126
- column: line_info[:column],
127
- raw: line_info[:raw]
128
- )
129
- end
130
-
131
- def line_for_token_at(index)
132
- line_info = @lexer.line_map[index] || {}
133
- line_info[:line]
134
- end
135
-
136
- def column_for_token_at(index)
137
- line_info = @lexer.line_map[index] || {}
138
- line_info[:column]
139
- end
140
-
141
- def collect_tokens(*values)
142
- values.flatten.compact.select { |v| v.is_a?(DemoTape::Token::Base) }
143
- end
144
-
145
- def on_error(token_id, token_value, value_stack)
146
- line_info = @lexer.line_map[@current_token_index] || {}
147
- line_num = line_info[:line] || "?"
148
- col_num = line_info[:column] || 1
149
- line_content = line_info[:content] || ""
150
-
151
- token_name = token_to_str(token_id) || token_id.to_s
152
-
153
- error_msg = "Unexpected token #{token_name.inspect} at #{@file}:#{line_num}:#{col_num}:\n"
154
- error_msg += " #{line_content.strip}\n"
155
- error_msg += " #{' ' * (col_num - line_content.length + line_content.strip.length - 1)}^"
156
-
157
- raise DemoTape::ParseError, error_msg
158
- end
159
-
160
- ---- footer
@@ -1,32 +0,0 @@
1
- class DemoTape::SimpleParser
2
- rule
3
- # Match lines - each line is either comment+newline or command tokens+newline
4
- document: lines { result = val[0].flatten }
5
- | /* empty */ { result = [] }
6
-
7
- lines: line { result = [val[0]] }
8
- | lines line { result = val[0] + val[1] }
9
-
10
- # A line ends with NEWLINE
11
- line: COMMENT NEWLINE { result = [[:comment, val[0]], [:newline, val[1]]] }
12
- | NEWLINE { result = [[:newline, val[0]]] }
13
- | line_tokens NEWLINE { result = [{ type: :command, tokens: val[0] }, [:newline, val[1]]] }
14
-
15
- # Line tokens: anything that's not a newline
16
- line_tokens: line_token { result = [val[0]] }
17
- | line_tokens line_token { result = val[0] << val[1] }
18
-
19
- line_token: IDENTIFIER { result = [:id, val[0]] }
20
- | STRING { result = [:str, val[0]] }
21
- | SPACE { result = [:sp, val[0]] }
22
- | LEADING_SPACE { result = [:lsp, val[0]] }
23
-
24
- ---- inner
25
- def parse(tokens)
26
- @tokens = tokens
27
- do_parse
28
- end
29
-
30
- def next_token
31
- @tokens.shift
32
- end