rsyntaxtree 1.3.2 → 1.4.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.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +6 -0
- data/.gitignore +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +34 -0
- data/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.md +115 -52
- data/bin/rsyntaxtree +107 -19
- data/docs/_examples/054.md +22 -0
- data/docs/_examples/055.md +24 -0
- data/docs/_examples/056.md +27 -0
- data/docs/assets/img/054.png +0 -0
- data/docs/assets/img/055.png +0 -0
- data/docs/assets/img/056.png +0 -0
- data/docs/assets/svg/054.svg +50 -0
- data/docs/assets/svg/055.svg +53 -0
- data/docs/assets/svg/056.svg +73 -0
- data/docs/documentation.md +89 -0
- data/docs/documentation_ja.md +90 -1
- data/lib/rsyntaxtree/base_graph.rb +5 -5
- data/lib/rsyntaxtree/element.rb +3 -2
- data/lib/rsyntaxtree/elementlist.rb +3 -5
- data/lib/rsyntaxtree/format_converter.rb +65 -0
- data/lib/rsyntaxtree/markup_parser.rb +13 -2
- data/lib/rsyntaxtree/string_parser.rb +1 -1
- data/lib/rsyntaxtree/svg_graph.rb +9 -2
- data/lib/rsyntaxtree/tikz_generator.rb +131 -0
- data/lib/rsyntaxtree/utils.rb +1 -1
- data/lib/rsyntaxtree/version.rb +1 -1
- data/lib/rsyntaxtree.rb +42 -24
- data/rsyntaxtree.gemspec +2 -0
- data/syntree.svg +41 -0
- data/test/cli_test.rb +262 -0
- data/test/format_converter_test.rb +129 -0
- data/test/node_styling_test.rb +239 -0
- data/test/tikz_test.rb +89 -0
- metadata +51 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0e09c9414509d88c6bb4d1bc9b8acdb5384094e642a1fb4765c62a4ffe6a4ba0
|
|
4
|
+
data.tar.gz: c4f617a630db5edf5373ceeeb4c03b889cc84d548201a4746f448386db2efebe
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3d1e620f2662c43e3c1c66b55750ae252fa90e978ddfebed0fc5937cc8265014f3fc02aed3ee3627b4a2de264709c58e2e076884c1f0c869c8868db9dcf42237
|
|
7
|
+
data.tar.gz: 7f6f5d8ccb8b0f3f50363e5e1809ec32461e677458ec4b53bfbe383ef48889ed6ff8f2fda1edfc47fafcf4747857fcf260a1007d083733e20aeb4eefaf987b00
|
data/.github/FUNDING.yml
ADDED
data/.gitignore
CHANGED
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.0.0
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [1.4.0] - 2026-01
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Per-node coloring with `@color:` syntax (named colors and hex colors)
|
|
7
|
+
- Penn Treebank format support with escaped parentheses (`\(`, `\)`)
|
|
8
|
+
- Standard input support for piping tree data
|
|
9
|
+
- Configuration file support (`.rsyntaxtreerc`)
|
|
10
|
+
- Config file validation with helpful error messages
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Triangle connector now correctly draws from parent to child (not child to grandchild)
|
|
14
|
+
|
|
15
|
+
### Documentation
|
|
16
|
+
- Added TikZ output limitations section
|
|
17
|
+
- Improved README with Features section
|
|
18
|
+
- Added examples for per-node coloring (054, 055, 056)
|
|
19
|
+
|
|
20
|
+
## [1.3.2] - 2024
|
|
21
|
+
|
|
22
|
+
- Garbage collection friendly implementation
|
|
23
|
+
|
|
24
|
+
## [1.3.1] - 2024
|
|
25
|
+
|
|
26
|
+
- Bug fixes and improvements
|
|
27
|
+
|
|
28
|
+
## [1.3.0] - 2024
|
|
29
|
+
|
|
30
|
+
- TikZ/forest LaTeX output support
|
|
31
|
+
|
|
32
|
+
## Previous versions
|
|
33
|
+
|
|
34
|
+
See commit history for earlier changes.
|
data/Gemfile
CHANGED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2007-2026 Yoichiro Hasebe
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
|
@@ -1,27 +1,76 @@
|
|
|
1
1
|
<img src='https://github.com/yohasebe/rsyntaxtree/blob/master/img/rsyntaxtree.png?raw=true' style='width: 256px;' />
|
|
2
2
|
|
|
3
|
-
**RSyntaxTree** is a graphical syntax tree generator for linguistic research
|
|
3
|
+
**RSyntaxTree** is a graphical syntax tree generator for linguistic research.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<p>
|
|
6
|
+
<a href="https://yohasebe.com/rsyntaxtree"><strong>Web App</strong></a> ·
|
|
7
|
+
<a href="https://yohasebe.github.io/rsyntaxtree/examples"><strong>Example Gallery</strong></a> ·
|
|
8
|
+
<a href="https://yohasebe.github.io/rsyntaxtree/documentation"><strong>Documentation</strong></a>
|
|
9
|
+
</p>
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
## Features
|
|
8
12
|
|
|
9
|
-
-
|
|
10
|
-
- [日本語ドキュメント](https://yohasebe.github.io/rsyntaxtree/documentation_ja)
|
|
13
|
+
RSyntaxTree provides a rich set of features for creating publication-quality syntax trees:
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
### Basic Syntax
|
|
16
|
+
|
|
17
|
+
Use bracket notation to define tree structures:
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
[S [NP the cat] [VP [V sleeps]]]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Text Decoration
|
|
24
|
+
|
|
25
|
+
Apply various text styles to node labels:
|
|
26
|
+
|
|
27
|
+
- **Bold**: `**text**`
|
|
28
|
+
- *Italic*: `*text*`
|
|
29
|
+
- Subscript: `_text_`
|
|
30
|
+
- Superscript: `__text__`
|
|
31
|
+
- Overline/Underline/Strikethrough: `=text=`, `-text-`, `~text~`
|
|
32
|
+
|
|
33
|
+
### Per-Node Coloring
|
|
34
|
+
|
|
35
|
+
Apply custom colors to individual nodes using `@color:` syntax:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
[S [@red:NP the cat] [@blue:VP sleeps]]
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Supports named colors (`red`, `blue`, `green`, etc.) and hex colors (`@#FF5733:`).
|
|
42
|
+
|
|
43
|
+
### Enclosures and Triangles
|
|
44
|
+
|
|
45
|
+
- **Brackets**: `[#NP text]` → draws brackets around the node
|
|
46
|
+
- **Rectangle**: `[##NP text]` → draws a rectangle around the node
|
|
47
|
+
- **Triangle**: `[^NP the quick fox]` → draws a triangle connector
|
|
48
|
+
|
|
49
|
+
Combine with colors: `[#@red:NP text]`, `[^@blue:VP phrase]`
|
|
50
|
+
|
|
51
|
+
### Path Drawing
|
|
52
|
+
|
|
53
|
+
Connect nodes with lines or arrows:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
[S [NP+1 text] [VP [V+>1 connects]]]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Multiple Output Formats
|
|
60
|
+
|
|
61
|
+
Generate trees in PNG, SVG, PDF, JPG, or GIF format.
|
|
13
62
|
|
|
14
63
|
## Web Interface
|
|
15
64
|
|
|
16
65
|
<img src='https://github.com/yohasebe/rsyntaxtree/blob/master/img/rsyntaxtree-web-screenshot.png?raw=true' width='700px'/>
|
|
17
66
|
|
|
18
|
-
|
|
67
|
+
A working web interface is available at <https://yohasebe.com/rsyntaxtree>.
|
|
19
68
|
|
|
20
|
-
You can run RSyntaxTree's web interface on your local machine using Docker Desktop. See [RSyntaxTree Web UI](https://github.com/yohasebe/rsyntaxtree_web)
|
|
69
|
+
You can also run RSyntaxTree's web interface on your local machine using Docker Desktop. See [RSyntaxTree Web UI](https://github.com/yohasebe/rsyntaxtree_web).
|
|
21
70
|
|
|
22
71
|
## Examples
|
|
23
72
|
|
|
24
|
-
See [RSyntaxTree Example Gallery](https://yohasebe.github.io/rsyntaxtree/examples)
|
|
73
|
+
See [RSyntaxTree Example Gallery](https://yohasebe.github.io/rsyntaxtree/examples) for examples covering:
|
|
25
74
|
|
|
26
75
|
- Generative Grammar
|
|
27
76
|
- Combinatory Categorial Grammar
|
|
@@ -30,9 +79,7 @@ See [RSyntaxTree Example Gallery](https://yohasebe.github.io/rsyntaxtree/example
|
|
|
30
79
|
- Construction Grammar
|
|
31
80
|
- Pragmatics
|
|
32
81
|
- Phonology
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
**NOTE**: Some tree structures in the example gallery are experimental in the sense that they are not drawn according to conventions of the field.
|
|
82
|
+
- and more
|
|
36
83
|
|
|
37
84
|
**Input text**
|
|
38
85
|
|
|
@@ -57,13 +104,13 @@ See [RSyntaxTree Example Gallery](https://yohasebe.github.io/rsyntaxtree/example
|
|
|
57
104
|
|
|
58
105
|
## Installation
|
|
59
106
|
|
|
60
|
-
```
|
|
107
|
+
```bash
|
|
61
108
|
gem install rsyntaxtree
|
|
62
109
|
```
|
|
63
110
|
|
|
64
111
|
### macOS Installation Notice
|
|
65
112
|
|
|
66
|
-
**Important for macOS users:** If you
|
|
113
|
+
**Important for macOS users:** If you encounter build errors for native extensions (`gobject-introspection`, `cairo-gobject`, `gio2`), run the following commands before installing RSyntaxTree:
|
|
67
114
|
|
|
68
115
|
```bash
|
|
69
116
|
gem install gobject-introspection -- --with-ldflags="-Wl,-undefined,dynamic_lookup"
|
|
@@ -71,69 +118,85 @@ gem install cairo-gobject -- --with-ldflags="-Wl,-undefined,dynamic_lookup"
|
|
|
71
118
|
gem install gio2 -- --with-ldflags="-Wl,-undefined,dynamic_lookup"
|
|
72
119
|
```
|
|
73
120
|
|
|
74
|
-
|
|
121
|
+
Then install RSyntaxTree:
|
|
75
122
|
|
|
76
123
|
```bash
|
|
77
124
|
gem install rsyntaxtree
|
|
78
125
|
```
|
|
79
126
|
|
|
80
|
-
Alternatively,
|
|
127
|
+
Alternatively, use the [Docker image](https://hub.docker.com/r/yohasebe/rsyntaxtree) or the [web interface](https://yohasebe.com/rsyntaxtree).
|
|
81
128
|
|
|
82
129
|
## Usage
|
|
83
130
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
For the command-line interface, type `$rsyntaxtree -h` after installation. Here's what you get:
|
|
131
|
+
### Command Line
|
|
87
132
|
|
|
88
133
|
```text
|
|
89
|
-
RSyntaxTree, (linguistic) syntax tree generator written in Ruby.
|
|
90
|
-
|
|
91
134
|
Usage:
|
|
92
|
-
1) rsyntaxtree [options] "[
|
|
93
|
-
2) rsyntaxtree [options] "
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
-u, --outfilename=<s> Output file base name (default: syntree)
|
|
97
|
-
-f, --format=<s> Output format: png, gif, jpg, pdf, or svg (default: png)
|
|
98
|
-
-l, --leafstyle=<s> visual style of tree leaves: auto, triangle, bar, or nothing (default: auto)
|
|
99
|
-
-n, --fontstyle=<s> Font style (available when ttf font is specified): sans, serif, cjk, mono (default: sans)
|
|
100
|
-
-t, --font=<s> Path to a ttf font used to generate tree (optional)
|
|
101
|
-
-s, --fontsize=<i> Size: 8-26 (default: 16)
|
|
102
|
-
-i, --linewidth=<i> Size: 1-5 (default: 1)
|
|
103
|
-
-v, --vheight=<f> Connector Height: 0.5-5.0 (default: 2.0)
|
|
104
|
-
-c, --color=<s> Color text and bars: modern, traditional, or off (default: modern)
|
|
105
|
-
-y, --symmetrize=<s> Generate radically symmetrical, balanced tree: on or off (default: off)
|
|
106
|
-
-r, --transparent=<s> Make background transparent: on or off (default: off)
|
|
107
|
-
-p, --polyline=<s> draw polyline connectors: on or off (default: off)
|
|
108
|
-
-d, --hide-default-connectors=<s> make default connectors transparent: on or off (default: off)
|
|
109
|
-
-h, --help This is a custom help message
|
|
110
|
-
-e, --version Print version and exit
|
|
135
|
+
1) rsyntaxtree [options] "[S [NP text] [VP here]]"
|
|
136
|
+
2) rsyntaxtree [options] "(S (NP text) (VP here))" # Penn Treebank format
|
|
137
|
+
3) rsyntaxtree [options] "/path/to/text/file"
|
|
138
|
+
4) echo "[S [NP text] [VP here]]" | rsyntaxtree [options]
|
|
111
139
|
```
|
|
112
140
|
|
|
113
|
-
|
|
141
|
+
### Options
|
|
114
142
|
|
|
115
|
-
|
|
143
|
+
| Option | Description | Default |
|
|
144
|
+
|--------|-------------|---------|
|
|
145
|
+
| `-o, --outdir` | Output directory | `./` |
|
|
146
|
+
| `-f, --format` | Output format: png, gif, jpg, pdf, svg | `png` |
|
|
147
|
+
| `-l, --leafstyle` | Leaf style: auto, triangle, bar, nothing | `auto` |
|
|
148
|
+
| `-n, --fontstyle` | Font style: sans, serif, cjk, mono | `sans` |
|
|
149
|
+
| `-s, --fontsize` | Font size: 8-26 | `16` |
|
|
150
|
+
| `-c, --color` | Color mode: modern, traditional, off | `modern` |
|
|
151
|
+
| `-y, --symmetrize` | Symmetrical tree: on, off | `off` |
|
|
152
|
+
| `-p, --polyline` | Polyline connectors: on, off | `off` |
|
|
116
153
|
|
|
117
|
-
|
|
154
|
+
Run `rsyntaxtree -h` for the full list of options.
|
|
118
155
|
|
|
156
|
+
### Input Formats
|
|
157
|
+
|
|
158
|
+
- **Bracket notation**: `[S [NP text] [VP here]]`
|
|
159
|
+
- **Penn Treebank format**: `(S (NP text) (VP here))` - automatically converted
|
|
160
|
+
- **Standard input**: `echo "[S [NP text]]" | rsyntaxtree`
|
|
161
|
+
|
|
162
|
+
### Configuration File
|
|
163
|
+
|
|
164
|
+
RSyntaxTree supports configuration files (`.rsyntaxtreerc`) in YAML format. Place the file in your home directory or current working directory.
|
|
165
|
+
|
|
166
|
+
```yaml
|
|
167
|
+
# ~/.rsyntaxtreerc
|
|
168
|
+
format: svg
|
|
169
|
+
color: modern
|
|
170
|
+
fontsize: 18
|
|
119
171
|
```
|
|
120
|
-
|
|
172
|
+
|
|
173
|
+
CLI options override config file settings.
|
|
174
|
+
|
|
175
|
+
## Documentation
|
|
176
|
+
|
|
177
|
+
For detailed documentation on syntax and markup:
|
|
178
|
+
|
|
179
|
+
- [Documentation in English](https://yohasebe.github.io/rsyntaxtree/documentation)
|
|
180
|
+
- [日本語ドキュメント](https://yohasebe.github.io/rsyntaxtree/documentation_ja)
|
|
181
|
+
- [Example Gallery](https://yohasebe.github.io/rsyntaxtree/examples)
|
|
182
|
+
|
|
183
|
+
## References
|
|
184
|
+
|
|
185
|
+
Please use the following BibTeX entry when citing RSyntaxTree:
|
|
186
|
+
|
|
187
|
+
```bibtex
|
|
188
|
+
@misc{rsyntaxtree,
|
|
121
189
|
author = {Yoichiro Hasebe},
|
|
122
|
-
title = {RSyntaxTree: A graphical syntax tree image generator}
|
|
190
|
+
title = {RSyntaxTree: A graphical syntax tree image generator},
|
|
123
191
|
url = {https://yohasebe.com/rsyntaxtree},
|
|
124
|
-
year = {
|
|
192
|
+
year = {2026}
|
|
125
193
|
}
|
|
126
194
|
```
|
|
127
195
|
|
|
128
|
-
## Development
|
|
129
|
-
|
|
130
|
-
For the latest updates and downloads please visit <http://github.com/yohasebe/rsyntaxtree>
|
|
131
|
-
|
|
132
196
|
## Author
|
|
133
197
|
|
|
134
|
-
Yoichiro Hasebe <yohasebe@gmail.com>
|
|
198
|
+
Yoichiro Hasebe (<yohasebe@gmail.com>)
|
|
135
199
|
|
|
136
200
|
## License
|
|
137
201
|
|
|
138
202
|
RSyntaxTree is distributed under the [MIT License](http://www.opensource.org/licenses/mit-license.php).
|
|
139
|
-
|
data/bin/rsyntaxtree
CHANGED
|
@@ -2,9 +2,85 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'optimist'
|
|
5
|
+
require 'yaml'
|
|
5
6
|
|
|
6
7
|
require_relative '../lib/rsyntaxtree'
|
|
7
8
|
require_relative '../lib/rsyntaxtree/utils'
|
|
9
|
+
require_relative '../lib/rsyntaxtree/format_converter'
|
|
10
|
+
|
|
11
|
+
# Valid configuration keys and their validators
|
|
12
|
+
CONFIG_VALIDATORS = {
|
|
13
|
+
outdir: ->(v) { FileTest.directory?(v) ? nil : "must be an existing directory path" },
|
|
14
|
+
outfilename: ->(v) { v.is_a?(String) ? nil : "must be a string" },
|
|
15
|
+
format: ->(v) { /\A(png|jpg|gif|pdf|svg)\z/ =~ v.to_s ? nil : "must be png, jpg, gif, pdf, or svg" },
|
|
16
|
+
leafstyle: ->(v) { /\A(auto|triangle|bar|nothing)\z/ =~ v.to_s ? nil : "must be auto, triangle, bar, or nothing" },
|
|
17
|
+
fontstyle: ->(v) { /\A(sans|serif|cjk|mono)\z/ =~ v.to_s ? nil : "must be sans, serif, cjk, or mono" },
|
|
18
|
+
font: ->(v) { v.nil? || File.exist?(v) ? nil : "must be path to an existing ttf font" },
|
|
19
|
+
fontsize: ->(v) { v.is_a?(Integer) && v >= 8 && v <= 26 ? nil : "must be in the range of 8-26" },
|
|
20
|
+
linewidth: ->(v) { v.is_a?(Integer) && v >= 1 && v <= 5 ? nil : "must be in the range of 1-5" },
|
|
21
|
+
vheight: ->(v) { v.is_a?(Numeric) && v >= 0.5 && v <= 5.0 ? nil : "must be in the range of 0.5-5.0" },
|
|
22
|
+
color: ->(v) { /\A(modern|traditional|on|off|true|false)\z/ =~ v.to_s ? nil : "must be modern, traditional, or off" },
|
|
23
|
+
symmetrize: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" },
|
|
24
|
+
transparent: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" },
|
|
25
|
+
polyline: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" },
|
|
26
|
+
hide_default_connectors: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" }
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
# Validate configuration and return errors/warnings
|
|
30
|
+
def validate_config(config, source_path)
|
|
31
|
+
errors = []
|
|
32
|
+
warnings = []
|
|
33
|
+
|
|
34
|
+
config.each do |key, value|
|
|
35
|
+
key_sym = key.to_sym
|
|
36
|
+
if CONFIG_VALIDATORS.key?(key_sym)
|
|
37
|
+
error_msg = CONFIG_VALIDATORS[key_sym].call(value)
|
|
38
|
+
if error_msg
|
|
39
|
+
errors << "Error in #{source_path}: '#{key}' #{error_msg} (got: #{value.inspect})"
|
|
40
|
+
end
|
|
41
|
+
else
|
|
42
|
+
warnings << "Warning: unknown option '#{key}' in #{source_path}"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
{ errors: errors, warnings: warnings }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Load configuration from .rsyntaxtreerc files
|
|
50
|
+
def load_config
|
|
51
|
+
config = {}
|
|
52
|
+
all_errors = []
|
|
53
|
+
all_warnings = []
|
|
54
|
+
|
|
55
|
+
config_files = [
|
|
56
|
+
File.join(Dir.home, '.rsyntaxtreerc'),
|
|
57
|
+
File.join(Dir.pwd, '.rsyntaxtreerc')
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
config_files.each do |path|
|
|
61
|
+
if File.exist?(path)
|
|
62
|
+
file_config = YAML.safe_load(File.read(path), symbolize_names: true) || {}
|
|
63
|
+
validation = validate_config(file_config, path)
|
|
64
|
+
all_errors.concat(validation[:errors])
|
|
65
|
+
all_warnings.concat(validation[:warnings])
|
|
66
|
+
config.merge!(file_config)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
{ config: config, errors: all_errors, warnings: all_warnings }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
loaded = load_config
|
|
74
|
+
file_config = loaded[:config]
|
|
75
|
+
|
|
76
|
+
# Show warnings for unknown keys
|
|
77
|
+
loaded[:warnings].each { |w| warn w }
|
|
78
|
+
|
|
79
|
+
# Exit with errors for invalid values
|
|
80
|
+
unless loaded[:errors].empty?
|
|
81
|
+
loaded[:errors].each { |e| warn e }
|
|
82
|
+
exit 1
|
|
83
|
+
end
|
|
8
84
|
|
|
9
85
|
opts = Optimist.options do
|
|
10
86
|
version "RSyntaxTree #{RSyntaxTree::VERSION} (c) 2024 Yoichiro Hasebe"
|
|
@@ -12,14 +88,16 @@ opts = Optimist.options do
|
|
|
12
88
|
RSyntaxTree, (linguistic) syntax tree generator written in Ruby.
|
|
13
89
|
|
|
14
90
|
Usage:
|
|
15
|
-
1) rsyntaxtree [options] "[
|
|
16
|
-
2) rsyntaxtree [options] "
|
|
91
|
+
1) rsyntaxtree [options] "[S [NP text] [VP here]]"
|
|
92
|
+
2) rsyntaxtree [options] "(S (NP text) (VP here))" # Penn TreeBank format
|
|
93
|
+
3) rsyntaxtree [options] "/path/to/text/file"
|
|
94
|
+
4) echo "[S [NP text] [VP here]]" | rsyntaxtree [options]
|
|
17
95
|
where [options] are:
|
|
18
96
|
BANNER
|
|
19
97
|
|
|
20
98
|
opt :outdir, "Output directory", default: "./"
|
|
21
99
|
opt :outfilename, "Output file base name", default: "syntree"
|
|
22
|
-
opt :format, "Output format: png, pdf, or svg", default: "png"
|
|
100
|
+
opt :format, "Output format: png, jpg, gif, pdf, or svg", default: "png"
|
|
23
101
|
opt :leafstyle, "visual style of tree leaves: auto, triangle, bar, or nothing", default: "auto"
|
|
24
102
|
opt :fontstyle, "Font style (available when ttf font is specified): sans, serif, cjk, mono", default: "sans"
|
|
25
103
|
opt :font, "Path to a ttf font used to generate tree (optional)", type: String
|
|
@@ -48,17 +126,38 @@ Optimist.die :transparent, "must be either on or off" unless /\A(on|off|true|fal
|
|
|
48
126
|
Optimist.die :polyline, "must be either on or off" unless /\A(on|off|true|false)\z/ =~ opts[:polyline]
|
|
49
127
|
Optimist.die :hide_default_connectors, "must be either on or off" unless /\A(on|off|true|false)\z/ =~ opts[:hide_default_connectors]
|
|
50
128
|
|
|
129
|
+
# Merge config file options with CLI options (CLI takes precedence)
|
|
51
130
|
string_opts = {}
|
|
131
|
+
|
|
132
|
+
# First, apply config file defaults
|
|
133
|
+
file_config.each do |key, value|
|
|
134
|
+
string_opts[key.to_sym] = value
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Then, apply CLI options (overrides config file)
|
|
52
138
|
opts.each do |key, value|
|
|
53
|
-
|
|
139
|
+
key_sym = key.to_sym
|
|
140
|
+
# Skip internal optimist keys and nil font
|
|
141
|
+
next if key.to_s.start_with?('_') || (key == :font && !value)
|
|
142
|
+
# Only override if explicitly given on CLI or not in config
|
|
143
|
+
if opts[:"#{key}_given"] || !file_config.key?(key_sym)
|
|
144
|
+
string_opts[key_sym] = value
|
|
145
|
+
end
|
|
54
146
|
end
|
|
55
147
|
|
|
56
148
|
data = if ARGV[0] && File.exist?(File.expand_path(ARGV[0]))
|
|
57
149
|
File.read ARGV[0]
|
|
58
|
-
|
|
150
|
+
elsif ARGV[0]
|
|
59
151
|
ARGV[0]
|
|
152
|
+
elsif !$stdin.tty?
|
|
153
|
+
$stdin.read
|
|
154
|
+
else
|
|
155
|
+
nil
|
|
60
156
|
end
|
|
61
157
|
|
|
158
|
+
# Auto-convert Penn TreeBank format to bracket notation
|
|
159
|
+
data = RSyntaxTree::FormatConverter.to_bracket(data) if data
|
|
160
|
+
|
|
62
161
|
begin
|
|
63
162
|
RSyntaxTree::RSGenerator.check_data(data)
|
|
64
163
|
rescue RSTError => e
|
|
@@ -72,20 +171,9 @@ begin
|
|
|
72
171
|
ext = string_opts[:format]
|
|
73
172
|
outfilename = string_opts[:outfilename] || "syntree"
|
|
74
173
|
filepath = File.expand_path(string_opts[:outdir]) + "/#{outfilename}." + ext
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
outfile.write rsg.draw_pdf
|
|
79
|
-
outfile.close
|
|
80
|
-
when "png"
|
|
81
|
-
outfile = File.new(filepath, "wb")
|
|
82
|
-
outfile.write rsg.draw_png
|
|
83
|
-
outfile.close
|
|
84
|
-
when "svg"
|
|
85
|
-
outfile = File.new(filepath, "wb")
|
|
86
|
-
outfile.write rsg.draw_svg
|
|
87
|
-
outfile.close
|
|
88
|
-
end
|
|
174
|
+
draw_method = "draw_#{ext}"
|
|
175
|
+
output = rsg.send(draw_method)
|
|
176
|
+
File.binwrite(filepath, output)
|
|
89
177
|
rescue RSTError => e
|
|
90
178
|
puts e
|
|
91
179
|
exit
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "054"
|
|
3
|
+
color: "on"
|
|
4
|
+
caption: "Per-node coloring (named colors)"
|
|
5
|
+
category: "Miscellaneous"
|
|
6
|
+
polyline: "off"
|
|
7
|
+
symmetrization: "off"
|
|
8
|
+
connector: "auto"
|
|
9
|
+
connector_height: "2.0"
|
|
10
|
+
linewidth: "1"
|
|
11
|
+
hide_default_connectors: "off"
|
|
12
|
+
font: "Noto Sans"
|
|
13
|
+
---
|
|
14
|
+
```
|
|
15
|
+
[S
|
|
16
|
+
[@red:NP the dog]
|
|
17
|
+
[@blue:VP
|
|
18
|
+
[@green:V runs]
|
|
19
|
+
[@orange:Adv quickly]
|
|
20
|
+
]
|
|
21
|
+
]
|
|
22
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "055"
|
|
3
|
+
color: "on"
|
|
4
|
+
caption: "Per-leaf coloring (hex colors)"
|
|
5
|
+
category: "Miscellaneous"
|
|
6
|
+
polyline: "off"
|
|
7
|
+
symmetrization: "off"
|
|
8
|
+
connector: "auto"
|
|
9
|
+
connector_height: "2.0"
|
|
10
|
+
linewidth: "1"
|
|
11
|
+
hide_default_connectors: "off"
|
|
12
|
+
font: "Noto Sans"
|
|
13
|
+
---
|
|
14
|
+
```
|
|
15
|
+
[S
|
|
16
|
+
[NP
|
|
17
|
+
[Det @#E63946:the]
|
|
18
|
+
[N @#457B9D:cat]
|
|
19
|
+
]
|
|
20
|
+
[VP
|
|
21
|
+
[V @#2A9D8F:sleeps]
|
|
22
|
+
]
|
|
23
|
+
]
|
|
24
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "056"
|
|
3
|
+
color: "on"
|
|
4
|
+
caption: "Per-node coloring with enclosure and triangle"
|
|
5
|
+
category: "Miscellaneous"
|
|
6
|
+
polyline: "off"
|
|
7
|
+
symmetrization: "off"
|
|
8
|
+
connector: "auto"
|
|
9
|
+
connector_height: "2.0"
|
|
10
|
+
linewidth: "1"
|
|
11
|
+
hide_default_connectors: "off"
|
|
12
|
+
font: "Noto Sans"
|
|
13
|
+
---
|
|
14
|
+
```
|
|
15
|
+
[S
|
|
16
|
+
[#@red:NP
|
|
17
|
+
[^@blue:N the quick brown fox]
|
|
18
|
+
]
|
|
19
|
+
[#@green:VP
|
|
20
|
+
[V jumps]
|
|
21
|
+
[PP
|
|
22
|
+
[P over]
|
|
23
|
+
[^@purple:NP the lazy dog]
|
|
24
|
+
]
|
|
25
|
+
]
|
|
26
|
+
]
|
|
27
|
+
```
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<?xml version="1.0" standalone="no"?>
|
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
3
|
+
<svg width="466.2" height="605.25" viewBox="-15.200000000000001, 0, 481.4, 616.5" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
+
<defs>
|
|
5
|
+
<marker id="arrow" markerUnits="userSpaceOnUse" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="15.200000000000001" markerHeight="15.200000000000001" orient="auto">
|
|
6
|
+
<path d="M 0 0 L 10 5 L 0 10" fill="#CC79A7"/>
|
|
7
|
+
</marker>
|
|
8
|
+
<marker id="arrowBackward" markerUnits="userSpaceOnUse" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="15.200000000000001" markerHeight="15.200000000000001" orient="auto">
|
|
9
|
+
<path d="M 0 0 L 10 5 L 0 10 z" fill="#CC79A7"/>
|
|
10
|
+
</marker>
|
|
11
|
+
<marker id="arrowForward" markerUnits="userSpaceOnUse" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="15.200000000000001" markerHeight="15.200000000000001" orient="auto">
|
|
12
|
+
<path d="M 10 0 L 0 5 L 10 10 z" fill="#CC79A7"/>
|
|
13
|
+
</marker>
|
|
14
|
+
<marker id="arrowBothways" markerUnits="userSpaceOnUse" viewBox="0 0 30 10" refX="15" refY="5" markerWidth="45.6" markerHeight="15.200000000000001" orient="auto">
|
|
15
|
+
<path d="M 0 5 L 10 0 L 10 5 L 20 5 L 20 0 L 30 5 L 20 10 L 20 5 L 10 5 L 10 10 z" fill="#CC79A7"/>
|
|
16
|
+
</marker>
|
|
17
|
+
<pattern id="hatchBlack" x="10" y="10" width="10" height="10" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
|
|
18
|
+
<line x1="0" y="0" x2="0" y2="10" stroke="black" stroke-width="4"></line>
|
|
19
|
+
</pattern>
|
|
20
|
+
<pattern id="hatchForNode" x="10" y="10" width="10" height="10" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
|
|
21
|
+
<line x1="0" y="0" x2="0" y2="10" stroke="#0072B2" stroke-width="4"></line>
|
|
22
|
+
</pattern>
|
|
23
|
+
<pattern id="hatchForLeaf" x="10" y="10" width="10" height="10" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
|
|
24
|
+
<line x1="0" y="0" x2="0" y2="10" stroke="#009E73" stroke-width="4"></line>
|
|
25
|
+
</pattern>
|
|
26
|
+
</defs>
|
|
27
|
+
<text white-space='pre' alignment-baseline='text-top' style='fill: #0072B2; storoke-width: 0; font-size: 32px;' x='184.925' y='67.5'><tspan x='184.925' y='67.5' style="" text-decoration="" font-family="'Noto Sans', 'Noto Sans JP', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif">S</tspan>
|
|
28
|
+
</text>
|
|
29
|
+
<text white-space='pre' alignment-baseline='text-top' style='fill: red; storoke-width: 0; font-size: 32px;' x='56.69999999999999' y='238.5'><tspan x='56.69999999999999' y='238.5' style="" text-decoration="" font-family="'Noto Sans', 'Noto Sans JP', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif">NP</tspan>
|
|
30
|
+
</text>
|
|
31
|
+
<text white-space='pre' alignment-baseline='text-top' style='fill: #009E73; storoke-width: 0; font-size: 32px;' x='15.199999999999989' y='409.5'><tspan x='15.199999999999989' y='409.5' style="" text-decoration="" font-family="'Noto Sans', 'Noto Sans JP', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif">the<tspan style='fill:none;'>■</tspan>dog</tspan>
|
|
32
|
+
</text>
|
|
33
|
+
<text white-space='pre' alignment-baseline='text-top' style='fill: blue; storoke-width: 0; font-size: 32px;' x='290.65000000000003' y='238.5'><tspan x='290.65000000000003' y='238.5' style="" text-decoration="" font-family="'Noto Sans', 'Noto Sans JP', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif">VP</tspan>
|
|
34
|
+
</text>
|
|
35
|
+
<text white-space='pre' alignment-baseline='text-top' style='fill: green; storoke-width: 0; font-size: 32px;' x='226.0' y='409.5'><tspan x='226.0' y='409.5' style="" text-decoration="" font-family="'Noto Sans', 'Noto Sans JP', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif">V</tspan>
|
|
36
|
+
</text>
|
|
37
|
+
<text white-space='pre' alignment-baseline='text-top' style='fill: #009E73; storoke-width: 0; font-size: 32px;' x='202.0' y='580.5'><tspan x='202.0' y='580.5' style="" text-decoration="" font-family="'Noto Sans', 'Noto Sans JP', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif">runs</tspan>
|
|
38
|
+
</text>
|
|
39
|
+
<text white-space='pre' alignment-baseline='text-top' style='fill: orange; storoke-width: 0; font-size: 32px;' x='354.8' y='409.5'><tspan x='354.8' y='409.5' style="" text-decoration="" font-family="'Noto Sans', 'Noto Sans JP', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif">Adv</tspan>
|
|
40
|
+
</text>
|
|
41
|
+
<text white-space='pre' alignment-baseline='text-top' style='fill: #009E73; storoke-width: 0; font-size: 32px;' x='330.8' y='580.5'><tspan x='330.8' y='580.5' style="" text-decoration="" font-family="'Noto Sans', 'Noto Sans JP', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif">quickly</tspan>
|
|
42
|
+
</text>
|
|
43
|
+
<line style='fill: none; stroke:black; stroke-width:2; stroke-linejoin:round; stroke-linecap:round;' x1='78.19999999999999' y1='182.25' x2='193.925' y2='95.625' />
|
|
44
|
+
<line style='fill: none; stroke:black; stroke-width:2; stroke-linejoin:round; stroke-linecap:round;' x1='309.65000000000003' y1='182.25' x2='193.925' y2='95.625' />
|
|
45
|
+
<polygon style='fill: none; stroke: black; stroke-width:2; stroke-linejoin:round;stroke-linecap:round;' points='15.199999999999989 353.25 141.2 353.25 78.19999999999999 266.625' />
|
|
46
|
+
<line style='fill: none; stroke:black; stroke-width:2; stroke-linejoin:round; stroke-linecap:round;' x1='236.0' y1='353.25' x2='309.65000000000003' y2='266.625' />
|
|
47
|
+
<line style='fill: none; stroke:black; stroke-width:2; stroke-linejoin:round; stroke-linecap:round;' x1='383.3' y1='353.25' x2='309.65000000000003' y2='266.625' />
|
|
48
|
+
<line style='fill: none; stroke:black; stroke-width:2; stroke-linejoin:round; stroke-linecap:round;' x1='236.0' y1='524.25' x2='236.0' y2='437.625' />
|
|
49
|
+
<line style='fill: none; stroke:black; stroke-width:2; stroke-linejoin:round; stroke-linecap:round;' x1='383.3' y1='524.25' x2='383.3' y2='437.625' />
|
|
50
|
+
</svg>
|