rtext 0.4.0 → 0.5.0

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 (48) hide show
  1. data/CHANGELOG +20 -0
  2. data/{README → README.rdoc} +5 -1
  3. data/RText_Protocol +444 -0
  4. data/Rakefile +10 -10
  5. data/lib/rtext/completer.rb +32 -26
  6. data/lib/rtext/context_builder.rb +113 -59
  7. data/lib/rtext/default_loader.rb +73 -8
  8. data/lib/rtext/default_service_provider.rb +30 -14
  9. data/lib/rtext/frontend/config.rb +58 -0
  10. data/lib/rtext/frontend/connector.rb +233 -0
  11. data/lib/rtext/frontend/connector_manager.rb +81 -0
  12. data/lib/rtext/frontend/context.rb +56 -0
  13. data/lib/rtext/generic.rb +13 -0
  14. data/lib/rtext/instantiator.rb +30 -7
  15. data/lib/rtext/language.rb +54 -27
  16. data/lib/rtext/link_detector.rb +57 -0
  17. data/lib/rtext/message_helper.rb +77 -0
  18. data/lib/rtext/parser.rb +19 -68
  19. data/lib/rtext/serializer.rb +18 -3
  20. data/lib/rtext/service.rb +182 -118
  21. data/lib/rtext/tokenizer.rb +102 -0
  22. data/test/completer_test.rb +327 -70
  23. data/test/context_builder_test.rb +671 -91
  24. data/test/instantiator_test.rb +153 -0
  25. data/test/integration/backend.out +10 -0
  26. data/test/integration/crash_on_request_editor.rb +12 -0
  27. data/test/integration/ecore_editor.rb +50 -0
  28. data/test/integration/frontend.log +25138 -0
  29. data/test/integration/model/invalid_encoding.invenc +2 -0
  30. data/test/integration/model/test.crash_on_request +18 -0
  31. data/test/integration/model/test.crashing_backend +18 -0
  32. data/test/integration/model/test.dont_open_socket +0 -0
  33. data/test/integration/model/test.invalid_cmd_line +0 -0
  34. data/test/integration/model/test.not_in_rtext +0 -0
  35. data/test/integration/model/test_large_with_errors.ect3 +43523 -0
  36. data/test/integration/model/test_metamodel.ect +18 -0
  37. data/test/integration/model/test_metamodel2.ect +5 -0
  38. data/test/integration/model/test_metamodel_error.ect2 +3 -0
  39. data/test/integration/model/test_metamodel_ok.ect2 +18 -0
  40. data/test/integration/test.rb +684 -0
  41. data/test/link_detector_test.rb +276 -0
  42. data/test/message_helper_test.rb +118 -0
  43. data/test/rtext_test.rb +4 -1
  44. data/test/serializer_test.rb +96 -1
  45. data/test/tokenizer_test.rb +125 -0
  46. metadata +36 -10
  47. data/RText_Plugin_Implementation_Guide +0 -268
  48. data/lib/rtext_plugin/connection_manager.rb +0 -59
@@ -0,0 +1,125 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
+
3
+ require 'test/unit'
4
+ require 'rtext/tokenizer'
5
+ require 'rtext/generic'
6
+
7
+ class TokenizerTest < Test::Unit::TestCase
8
+ include RText::Tokenizer
9
+
10
+ def test_simple
11
+ assert_tokens [
12
+ Token.new(:identifier, "TestNode", 1, 1, 8),
13
+ Token.new(:integer, 1, 1, 10, 10),
14
+ Token.new(",", nil, 1, 11, 11),
15
+ Token.new(:identifier, "bla", 1, 13, 15),
16
+ Token.new(",", nil, 1, 16, 16),
17
+ Token.new(:float, 0.4, 1, 18, 20),
18
+ Token.new(",", nil, 1, 21, 21),
19
+ Token.new(:label, "label", 1, 23, 28),
20
+ Token.new(:integer, 4, 1, 30, 30),
21
+ Token.new(",", nil, 1, 31, 31),
22
+ Token.new(:string, "string", 1, 33, 40),
23
+ Token.new(:newline, nil, 1, nil, nil)
24
+ ], "TestNode 1, bla, 0.4, label: 4, \"string\""
25
+ end
26
+
27
+ def test_more
28
+ assert_tokens [
29
+ Token.new(:identifier, "TestNode", 1, 1, 8),
30
+ Token.new(:boolean, true, 1, 10, 13),
31
+ Token.new(",", nil, 1, 14, 14),
32
+ Token.new(:integer, 0xfaa, 1, 16, 20),
33
+ Token.new(:integer, -3, 1, 22, 23),
34
+ Token.new(:reference, "/a/b", 1, 25, 28),
35
+ Token.new(:newline, nil, 1, nil, nil)
36
+ ], <<-END
37
+ TestNode true, 0xfaa -3 /a/b
38
+ END
39
+ end
40
+
41
+ def test_comments_and_annotation
42
+ assert_tokens [
43
+ Token.new(:comment, " comment", 1, 1, 9),
44
+ Token.new(:newline, nil, 1, nil, nil),
45
+ Token.new(:annotation, " annotation", 2, 1, 12),
46
+ Token.new(:newline, nil, 2, nil, nil),
47
+ Token.new(:identifier, "TestNode", 3, 1, 8),
48
+ Token.new(:comment, "comment2", 3, 10, 18),
49
+ Token.new(:newline, nil, 3, nil, nil)
50
+ ], <<-END
51
+ # comment
52
+ @ annotation
53
+ TestNode #comment2
54
+ END
55
+ end
56
+
57
+ def test_generic
58
+ tokens = do_tokenize("<name>")
59
+ assert_equal :generic, tokens.first.kind
60
+ assert_equal "name", tokens.first.value.string
61
+ assert_equal 1, tokens.first.line
62
+ assert_equal 1, tokens.first.scol
63
+ assert_equal 6, tokens.first.ecol
64
+ end
65
+
66
+ def test_generic_bad
67
+ tokens = do_tokenize("<a>b>")
68
+ assert_equal :generic, tokens.first.kind
69
+ assert_equal "a", tokens.first.value.string
70
+ assert_equal 1, tokens.first.line
71
+ assert_equal 1, tokens.first.scol
72
+ assert_equal 3, tokens.first.ecol
73
+ assert_equal :identifier, tokens[1].kind
74
+ assert_equal :error, tokens[2].kind
75
+ end
76
+
77
+ def test_generic_percent
78
+ tokens = do_tokenize("<%name%>")
79
+ assert_equal :generic, tokens.first.kind
80
+ assert_equal "name", tokens.first.value.string
81
+ assert_equal 1, tokens.first.line
82
+ assert_equal 1, tokens.first.scol
83
+ assert_equal 8, tokens.first.ecol
84
+ end
85
+
86
+ def test_generic_percent_angle_close
87
+ tokens = do_tokenize("<% a > b < c %>")
88
+ assert_equal :generic, tokens.first.kind
89
+ assert_equal " a > b < c ", tokens.first.value.string
90
+ assert_equal 1, tokens.first.line
91
+ assert_equal 1, tokens.first.scol
92
+ assert_equal 15, tokens.first.ecol
93
+ end
94
+
95
+ def test_generic_percent_bad
96
+ tokens = do_tokenize("<%= a %> b %>")
97
+ assert_equal :generic, tokens.first.kind
98
+ assert_equal "= a ", tokens.first.value.string
99
+ assert_equal 1, tokens.first.line
100
+ assert_equal 1, tokens.first.scol
101
+ assert_equal 8, tokens.first.ecol
102
+ assert_equal :identifier, tokens[1].kind
103
+ assert_equal :error, tokens[2].kind
104
+ end
105
+
106
+ def test_error
107
+ assert_tokens [
108
+ Token.new(:error, "\"open", 1, 1, 5),
109
+ Token.new(:newline, nil, 1, nil, nil)
110
+ ], <<-END
111
+ "open
112
+ END
113
+ end
114
+
115
+ def do_tokenize(str)
116
+ tokenize(str, /\A\/[\/\w]+/)
117
+ end
118
+
119
+ def assert_tokens(expected, str)
120
+ tokens = tokenize(str, /\A\/[\/\w]+/)
121
+ assert_equal(expected, tokens)
122
+ end
123
+
124
+ end
125
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rtext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-09 00:00:00.000000000 Z
12
+ date: 2012-12-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rgen
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 0.6.0
21
+ version: 0.6.1
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,46 +26,72 @@ dependencies:
26
26
  requirements:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
- version: 0.6.0
29
+ version: 0.6.1
30
30
  description: RText can be used to derive textual languages from an RGen metamodel
31
31
  with very little effort.
32
32
  email: martin dot thiede at gmx de
33
33
  executables: []
34
34
  extensions: []
35
35
  extra_rdoc_files:
36
- - README
36
+ - README.rdoc
37
37
  - CHANGELOG
38
38
  - MIT-LICENSE
39
39
  - RText_Users_Guide
40
- - RText_Plugin_Implementation_Guide
40
+ - RText_Protocol
41
41
  files:
42
42
  - lib/rtext/completer.rb
43
43
  - lib/rtext/context_builder.rb
44
44
  - lib/rtext/default_loader.rb
45
45
  - lib/rtext/default_service_provider.rb
46
+ - lib/rtext/frontend/config.rb
47
+ - lib/rtext/frontend/connector.rb
48
+ - lib/rtext/frontend/connector_manager.rb
49
+ - lib/rtext/frontend/context.rb
50
+ - lib/rtext/generic.rb
46
51
  - lib/rtext/instantiator.rb
47
52
  - lib/rtext/language.rb
53
+ - lib/rtext/link_detector.rb
54
+ - lib/rtext/message_helper.rb
48
55
  - lib/rtext/parser.rb
49
56
  - lib/rtext/serializer.rb
50
57
  - lib/rtext/service.rb
51
- - lib/rtext_plugin/connection_manager.rb
58
+ - lib/rtext/tokenizer.rb
52
59
  - test/completer_test.rb
53
60
  - test/context_builder_test.rb
54
61
  - test/instantiator_test.rb
62
+ - test/integration/backend.out
63
+ - test/integration/crash_on_request_editor.rb
64
+ - test/integration/ecore_editor.rb
65
+ - test/integration/frontend.log
66
+ - test/integration/model/invalid_encoding.invenc
67
+ - test/integration/model/test.crashing_backend
68
+ - test/integration/model/test.crash_on_request
69
+ - test/integration/model/test.dont_open_socket
70
+ - test/integration/model/test.invalid_cmd_line
71
+ - test/integration/model/test.not_in_rtext
72
+ - test/integration/model/test_large_with_errors.ect3
73
+ - test/integration/model/test_metamodel.ect
74
+ - test/integration/model/test_metamodel2.ect
75
+ - test/integration/model/test_metamodel_error.ect2
76
+ - test/integration/model/test_metamodel_ok.ect2
77
+ - test/integration/test.rb
78
+ - test/link_detector_test.rb
79
+ - test/message_helper_test.rb
55
80
  - test/rtext_test.rb
56
81
  - test/serializer_test.rb
57
- - README
82
+ - test/tokenizer_test.rb
83
+ - README.rdoc
58
84
  - CHANGELOG
59
85
  - MIT-LICENSE
60
86
  - RText_Users_Guide
61
- - RText_Plugin_Implementation_Guide
87
+ - RText_Protocol
62
88
  - Rakefile
63
89
  homepage: http://ruby-gen.org
64
90
  licenses: []
65
91
  post_install_message:
66
92
  rdoc_options:
67
93
  - --main
68
- - README
94
+ - README.rdoc
69
95
  - -x
70
96
  - test
71
97
  require_paths:
@@ -1,268 +0,0 @@
1
- =RText Plugin Implementation Guide
2
-
3
- RText editors consist of a frontend and a backend. Most of the logic is implemented
4
- within the backend while the frontend is kept as thin as possible. This should simplify
5
- the task of writing a frontend and promote development of RText frontends for different
6
- editing environments.
7
-
8
- This guide explains how to build a RText frontend which will typically be a plugin for an
9
- existing editor.
10
-
11
-
12
- ==Plugin Responsibilies
13
-
14
- Here is a rough overview of what a RText plugin has to do:
15
-
16
- * find the .rtext config file for a given RText model file
17
- * start the corresponding backend process if not started already
18
- * provide a way to reload the model and issue the refresh command to the backend
19
- * implement syntax highlighting for the generic RText syntax
20
- * forward auto completion requests to the backend, let the user choose from the returned options
21
- and insert the option chosen
22
- * forward element search requests to the backend, let the user choose from the matched elements
23
- and jump to the element chosen
24
- * forward reference target requests to the backend, let the user choose from the targets found
25
- and jump to the target chosen
26
- * query the backend for model problems and display them to the user
27
- * stop the backend process when it's no longer needed
28
-
29
-
30
- ==Plugin Implementation Hints
31
-
32
- The plugin implementation could include the following entities.
33
-
34
- ===Command
35
-
36
- A command issued by the plugin and sent to the backend service. See the section about the
37
- Frontend/Backend Communication Protocol below for details about available commands.
38
-
39
-
40
- ===Connector
41
-
42
- A connector represents the connection to a running backend process.
43
- Each connector/process is associated with a specific .rtext file and a specific service specification
44
- within this file. See the RText Users Guide for details about the .rtext config file.
45
-
46
- When the backend service is started, it outputs the UDP port it is listening on. The connector
47
- should use this port to send commands to the backend.
48
-
49
- The connector should send commands to the backend. It should assign invocation ids and keep the
50
- invocation until a response is received or a timeout has occured.
51
-
52
- When the backend responds, the connector should associate the response packages with the previous
53
- request using the invocation id. It should also join fragmented response packages and send an
54
- internal notification when a response has been fully received.
55
-
56
-
57
- ===Connector Manager
58
-
59
- The connector manager should be able to return a connector for a given RText model file.
60
-
61
- It needs to identify the backend process to which to connect by means of the .rtext config file and
62
- a contained service specification (one .rtext files may contain service specifications for starting
63
- different backend services depending on the model file name).
64
-
65
- For this, it needs to find the first .rtext config file containing a service specification matching
66
- the given RText model file name. See the RText Users guide for details about the .rtext config file
67
- and the way how they are found in the filesystem.
68
-
69
- Once the .rtext file/service specification is found it can be used as a key for a lookup for
70
- already established connections. The plugin should avoid starting the same process twice. All
71
- RText model files with the same file extension and belonging to the same .rtext file should
72
- use the same process.
73
-
74
- The process should be kept running as long as editing is in progress. This will greatly
75
- reduce response times as the model can be kept in memory and only the changed parts need
76
- to be reloaded.
77
-
78
- When the plugin lifecycle ends, the connector manager should send the "stop" command to the
79
- backend processes.
80
-
81
-
82
- ==Frontend/Backend Communication Protocol
83
-
84
- Communication takes place via plain text transmitted via UDP. There are requests by
85
- the frontend and responses by the backend. In both cases the text is interpreted as
86
- a set of lines (separated by \n or \r\n).
87
-
88
-
89
- ===Request
90
-
91
- The request consists of a command id, an invocation id and the command parameters.
92
- The invocation id is repeated within the response to allow proper association with the
93
- request. Command parameters are command specific (see below).
94
-
95
- Requests can not span more than one UDP package and thus are limited to the UDP payload size.
96
-
97
- line 1: <command id>
98
- line 2: <invocation id>
99
- line 3..n: <command parameters>
100
-
101
-
102
- ===Response
103
-
104
- Each response contains the invocation id of the request in the first line.
105
- Since it could be splitted over several UDP packages it contains an indication
106
- in the second line if more packages are following ("more") or this is the last package
107
- ("last"). The rest of the response is a fragment of the command result data. All fragments
108
- of a set of response packages with the same invocation id need to be joined.
109
-
110
- Note that there are no mechanisms to protect agains package loss or reordering since
111
- this protocol is intended to be used on local socket connections only.
112
-
113
- line 1: <invocation id>
114
- line 2: "more" | "last"
115
- line 3..n: <command result data>
116
-
117
-
118
- ===Command: Refresh
119
-
120
- The refresh command tells the backend to reload the model from the file system. Frontends
121
- could issue this command after a model file has been changed in the file system or on
122
- an explicit user request.
123
-
124
- Request Format:
125
- command id: "refresh"
126
- no parameters
127
-
128
- Response Format:
129
- no result data
130
-
131
-
132
- ===Command: Complete
133
-
134
- This command is a request by the frontend to show auto completion options at a given
135
- location within a file. The location is expressed using a set of context lines and the cursor
136
- column position in the current line.
137
-
138
- Context lines are lines from an RText file which contain a (context) command and all
139
- the parent commands wrapped around it. Any sibling commands can be omitted as well as
140
- any lines containing closing braces and brackets. The order of lines is the same as in the RText file.
141
-
142
- Here is an example. Consider the following RText file with the cursor in the line of "Command3" at
143
- the time when the auto completion command is issued.
144
-
145
- Command1 {
146
- Command2 {
147
- role1: [
148
- Command3 <== cursor in this line
149
- Command4
150
- ]
151
- }
152
- Command5
153
- }
154
-
155
- The context lines in this case would be the following.
156
-
157
- Command1 {
158
- Command2 {
159
- role1: [
160
- Command3
161
-
162
- The current line is always the last of the context lines.
163
-
164
- Note that all siblings of the command and parent commands have been stripped off, as well as
165
- any closing braces or brackets.
166
-
167
- The purpose of this special context line format is to keep the task of extracting the
168
- context in the frontend simple and the amount of data transmitted to the backend low.
169
- It's also a way to keep the parsing time of the context low in the backend and thus to minimize
170
- the user noticable delay.
171
-
172
- Request Format:
173
- command id: "complete"
174
- param line 1: cursor column position in the current line
175
- param line 2..n: context lines
176
-
177
- Response Format:
178
- result line 1..n: <completion string>;<extra info string>
179
-
180
-
181
- ===Command: Show Problems
182
-
183
- This command is a request by the frontend to determine and return all problems present in the current model.
184
- The command implicitly reloads the model from the filesystem before checking for problems.
185
-
186
- Request Format:
187
- command id: "show_problems"
188
- no parameters
189
-
190
- Response Format:
191
- result line 1: <file name>
192
- result line 2..n <line number>;<message>
193
-
194
- Note that the file name is repeated only once for all problems within a file to reduce the amout of
195
- result data which needs to be transmitted.
196
-
197
-
198
- ===Command: Show Problems 2
199
-
200
- Since protocol version 1
201
-
202
- Like the first version but provides progress information while the model is loaded and problem severity.
203
-
204
- Request Format:
205
- command id: "show_problems2"
206
- no parameters
207
-
208
- Response Format:
209
- result line 1..n: progress:<[0..100]>
210
- result line n+1: <file name>
211
- result line n+2..m <[diwef]>;<line number>;<message>
212
-
213
- Progress is expressed by a value between 0 and 100. The backend may choose to return any number
214
- of progress lines. It should start with 0 and end with 100 and progress should not go backwards.
215
-
216
- Problem severity is expressed with one of the following flags: d (debug), i (info), w (warn), e (error), f (fatal)
217
-
218
-
219
- ===Command: Reference Targets
220
-
221
- This command is used to retrieve the targets of a given reference. The reference location is expressed
222
- by means of a set of context lines and the cursor column position in the current line. The cursor
223
- column position must be within the string representing the reference. The format of the context lines
224
- is the same as the one described with the "Complete" command (see above).
225
-
226
- Note that the service provider is free to define how a reference is represented. In particular it
227
- can interpret the command identifier as a reference and use this mechanism to show incoming references
228
- (reverse references).
229
-
230
- As references can be ambiguous, the result is a list of possible targets. Each target consists of the
231
- filename and line number of the target element as well as the text to be displayed to the user in case
232
- there are more than one targets to choose from.
233
-
234
- Request Format:
235
- command id: "get_reference_targets"
236
- param line 1: cursor column position in the current line
237
- param line 2..n: context lines
238
-
239
- Response Format:
240
- result line 1..n: <file name>;<line number>;<display name>
241
-
242
-
243
- ===Command: Find Elements
244
-
245
- This command returns a set of model elements matching a search pattern. The format of the
246
- pattern depends on the service provider. In a simple case, for example, the pattern could be the
247
- beginning of the element names.
248
-
249
- Request Format:
250
- command id: "get_elements"
251
- param line 1: <seach pattern>
252
-
253
- Response Format:
254
- result line 1..n: <display name>;<file name>;<line number>
255
-
256
-
257
- ===Command: Stop
258
-
259
- This command is normally invoked when the frontend terminates or otherwise needs to terminate
260
- the backend service. When receiving this command, the backend will terminate.
261
-
262
- Request Format:
263
- command id: "stop"
264
- no parameters
265
-
266
- Response Format:
267
- no result data
268
-