wccm 0.2.3__tar.gz
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.
- wccm-0.2.3/LICENSE +21 -0
- wccm-0.2.3/PKG-INFO +168 -0
- wccm-0.2.3/README.md +158 -0
- wccm-0.2.3/pyproject.toml +17 -0
- wccm-0.2.3/setup.cfg +4 -0
- wccm-0.2.3/src/wccm/config.json +52 -0
- wccm-0.2.3/src/wccm/formatter.py +161 -0
- wccm-0.2.3/src/wccm/info.json +1 -0
- wccm-0.2.3/src/wccm/infoParse.py +52 -0
- wccm-0.2.3/src/wccm/lexicon.json +1 -0
- wccm-0.2.3/src/wccm/parse.py +130 -0
- wccm-0.2.3/src/wccm/storage.py +12 -0
- wccm-0.2.3/src/wccm/wccm.py +69 -0
- wccm-0.2.3/src/wccm.egg-info/PKG-INFO +168 -0
- wccm-0.2.3/src/wccm.egg-info/SOURCES.txt +16 -0
- wccm-0.2.3/src/wccm.egg-info/dependency_links.txt +1 -0
- wccm-0.2.3/src/wccm.egg-info/entry_points.txt +2 -0
- wccm-0.2.3/src/wccm.egg-info/top_level.txt +1 -0
wccm-0.2.3/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 B1narymask
|
|
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.
|
wccm-0.2.3/PKG-INFO
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wccm
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Summary: Compact command-line conlang manager
|
|
5
|
+
Author: Wernasho
|
|
6
|
+
Requires-Python: >=3.8
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Dynamic: license-file
|
|
10
|
+
|
|
11
|
+
Wer's Compact Conlang Manager, or WCCM, is a simple command-line tool designed to make conlanging ever so slightly faster and easier by converting a simple, customizeable syntax into clean and readable conlang dictionaries.
|
|
12
|
+
|
|
13
|
+
I built this because spreadsheets had too much visual clutter and other existing tools were really overkill.
|
|
14
|
+
All you need to do is type your properties with shorthands you can customize, and you'll receive a nicely formatted text file.
|
|
15
|
+
|
|
16
|
+
For example, this:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Agná
|
|
20
|
+
$agˈna
|
|
21
|
+
%noun
|
|
22
|
+
#animals
|
|
23
|
+
?bird
|
|
24
|
+
~Masculine
|
|
25
|
+
+ágnaya
|
|
26
|
+
;gen :ágnand
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Turns into this:
|
|
30
|
+
```
|
|
31
|
+
Agná
|
|
32
|
+
\[agˈna] bird, plural: ágnaya
|
|
33
|
+
Gender: Masculine
|
|
34
|
+
POS: Noun
|
|
35
|
+
Semantic field: animals
|
|
36
|
+
Cases:
|
|
37
|
+
gen: ágnand
|
|
38
|
+
```
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
1. install Python 3.6 or newer from [python.org](https://python.org)
|
|
42
|
+
2. download or clone this repository
|
|
43
|
+
3. no additional packages are needed, uses only python standard library!
|
|
44
|
+
|
|
45
|
+
# Usage:
|
|
46
|
+
Open up your console/terminal inside the wccm folder, and run this command:
|
|
47
|
+
```bash
|
|
48
|
+
py wccm.py file.wccm
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Outputs to `Lexicon.txt`
|
|
52
|
+
|
|
53
|
+
# Syntax
|
|
54
|
+
|
|
55
|
+
WCCM uses symbols to represent different properties. Their order is irrelevant, as long as the plain word is always first.
|
|
56
|
+
|
|
57
|
+
## Lexicon
|
|
58
|
+
(Lexicon-related syntax goes in `.wccm` files).
|
|
59
|
+
|
|
60
|
+
| Symbol | Field | Example |
|
|
61
|
+
| ------------ | --------------------- | -------------------------- |
|
|
62
|
+
| (None) | Word | **Kat** |
|
|
63
|
+
| `$` | IPA | **$kæt** |
|
|
64
|
+
| `#` | Semantic field | **\#animal** |
|
|
65
|
+
| `~` | Gender | **~M** |
|
|
66
|
+
| `?` | Translation | **?Cat** |
|
|
67
|
+
| `+` | Plural form(s) | **+Cats** |
|
|
68
|
+
| `;` and `:` | Case name / case form | **;gen :cat's** |
|
|
69
|
+
| `=` | Synonym(s) | **=feline** |
|
|
70
|
+
| `!` | Antonym(s) | **!dog** |
|
|
71
|
+
| `%` | Part of speech | **%noun** |
|
|
72
|
+
| `*` | Etymology | **\*from 'kaltnaen' ** |
|
|
73
|
+
| `\|` and `/` | Conjugations | **\|3rd sg present /does** |
|
|
74
|
+
| `@` and `:` | Custom | **@class :animte** |
|
|
75
|
+
## Inventory
|
|
76
|
+
(Inventory-related information goes in `.cmi` files).
|
|
77
|
+
|
|
78
|
+
| Symbol | Field | Example |
|
|
79
|
+
| ------ | --------- | ------------ |
|
|
80
|
+
| `.` | consonant | **.tH** |
|
|
81
|
+
| `,` | vowel | **,3** |
|
|
82
|
+
| `^` | Tone | **\^rising** |
|
|
83
|
+
|
|
84
|
+
Don't like this set of symbols? That's completely fine! You can edit them anytime by going into `config.json`.
|
|
85
|
+
|
|
86
|
+
## IPA
|
|
87
|
+
I know that typing IPA symbols can be tedious if you don't have the tools, which is why I implemented a function to let you map a character to an IPA sound, to make writing transcriptions easier!
|
|
88
|
+
# Configuration
|
|
89
|
+
|
|
90
|
+
`config.json` lets you customize:
|
|
91
|
+
- what each symbol means (which property it represents)
|
|
92
|
+
- IPA character mapping (e.g., `:` -> `ː`)
|
|
93
|
+
- default output file
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"ipa": {
|
|
98
|
+
"S": "ʃ",
|
|
99
|
+
"T": "θ",
|
|
100
|
+
"R": "ɾ",
|
|
101
|
+
"B": "β",
|
|
102
|
+
"D": "ð",
|
|
103
|
+
"N": "ŋ",
|
|
104
|
+
"J": "ʲ",
|
|
105
|
+
"Z": "ʒ",
|
|
106
|
+
":": "ː",
|
|
107
|
+
"'": "ˈ",
|
|
108
|
+
"ny": "ɲ",
|
|
109
|
+
"W": "ʷ",
|
|
110
|
+
"H": "ʰ",
|
|
111
|
+
"A": "ɑ",
|
|
112
|
+
"E": "ə",
|
|
113
|
+
"I": "ɪ",
|
|
114
|
+
"3": "ɛ",
|
|
115
|
+
"O": "ɔ",
|
|
116
|
+
"U": "ʊ",
|
|
117
|
+
"^": "ʌ",
|
|
118
|
+
"X": "χ"
|
|
119
|
+
},
|
|
120
|
+
"props": {
|
|
121
|
+
"$": "ipa",
|
|
122
|
+
"#": "field",
|
|
123
|
+
"%": "pos",
|
|
124
|
+
"_": "comment",
|
|
125
|
+
"~": "gender",
|
|
126
|
+
"=": "synonym",
|
|
127
|
+
"!": "antonym",
|
|
128
|
+
"+": "plural",
|
|
129
|
+
"?": "meaning",
|
|
130
|
+
"*": "etymology",
|
|
131
|
+
";": "case",
|
|
132
|
+
"|": "conjugations",
|
|
133
|
+
"@": "custom"
|
|
134
|
+
},
|
|
135
|
+
"inv": {
|
|
136
|
+
".": "consonant",
|
|
137
|
+
",": "vowel",
|
|
138
|
+
"^": "tone"
|
|
139
|
+
},
|
|
140
|
+
"prefs": {
|
|
141
|
+
"output": {
|
|
142
|
+
"defaultFileName": "lexicon",
|
|
143
|
+
"defaultFormat": ".txt"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
For the IPA replacement mapping, the character on the left is the character that the program will replace. So, essentially, if your IPA is "SaTaZ", with the default configurations (the ones showed above) it would turn into "ʃaθaʒ". You can add/remove as many as you want! (As long as you don't map 1 character to 2 symbols or use digraphs).
|
|
150
|
+
|
|
151
|
+
Same goes for the properties, although it is very important that you do **not** alter the keywords, otherwise the tool will break.
|
|
152
|
+
|
|
153
|
+
As you might've guessed, you can also choose the default name and format of the output file! The name can be anything you want, and the file extension can be either `.txt` or `.md`. A `lexicon.json` file is always automatically generated, which is why `.json` isn't an option in preferences.
|
|
154
|
+
## Limitations
|
|
155
|
+
|
|
156
|
+
Currently, the case symbols (`;` and `:`) can't be customized, as well as the conjugation symbols (`|` and `/`).
|
|
157
|
+
If you ever want to remap a symbol, as said before, you're allowed (and encouraged) to do so! However, it is very important that you don't map `\` to anything. Since i don't want to confuse you with tech talk, basically, `\` is a special character and if you try to use it for mapping the configuration file is going to break.
|
|
158
|
+
|
|
159
|
+
Other than that, you should be able to change pretty much anything!
|
|
160
|
+
|
|
161
|
+
# About
|
|
162
|
+
|
|
163
|
+
WCCM started as just a little personal tool I developed because I'm stubborn and don't like any of the tools that already exist, and now I'm sharing it in case someone finds it useful as well.
|
|
164
|
+
|
|
165
|
+
# Feedback is appreciated!
|
|
166
|
+
|
|
167
|
+
This is my first time actually finishing and sharing a project, so I'd genuinely *love* to hear suggestions or ideas for future versions, as well as bug reports and other stuff like that.
|
|
168
|
+
You can contact me pretty much any time in [my twitter (I'm not calling it 'X')](https://x.com/wernasho)
|
wccm-0.2.3/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Wer's Compact Conlang Manager, or WCCM, is a simple command-line tool designed to make conlanging ever so slightly faster and easier by converting a simple, customizeable syntax into clean and readable conlang dictionaries.
|
|
2
|
+
|
|
3
|
+
I built this because spreadsheets had too much visual clutter and other existing tools were really overkill.
|
|
4
|
+
All you need to do is type your properties with shorthands you can customize, and you'll receive a nicely formatted text file.
|
|
5
|
+
|
|
6
|
+
For example, this:
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
Agná
|
|
10
|
+
$agˈna
|
|
11
|
+
%noun
|
|
12
|
+
#animals
|
|
13
|
+
?bird
|
|
14
|
+
~Masculine
|
|
15
|
+
+ágnaya
|
|
16
|
+
;gen :ágnand
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Turns into this:
|
|
20
|
+
```
|
|
21
|
+
Agná
|
|
22
|
+
\[agˈna] bird, plural: ágnaya
|
|
23
|
+
Gender: Masculine
|
|
24
|
+
POS: Noun
|
|
25
|
+
Semantic field: animals
|
|
26
|
+
Cases:
|
|
27
|
+
gen: ágnand
|
|
28
|
+
```
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
1. install Python 3.6 or newer from [python.org](https://python.org)
|
|
32
|
+
2. download or clone this repository
|
|
33
|
+
3. no additional packages are needed, uses only python standard library!
|
|
34
|
+
|
|
35
|
+
# Usage:
|
|
36
|
+
Open up your console/terminal inside the wccm folder, and run this command:
|
|
37
|
+
```bash
|
|
38
|
+
py wccm.py file.wccm
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Outputs to `Lexicon.txt`
|
|
42
|
+
|
|
43
|
+
# Syntax
|
|
44
|
+
|
|
45
|
+
WCCM uses symbols to represent different properties. Their order is irrelevant, as long as the plain word is always first.
|
|
46
|
+
|
|
47
|
+
## Lexicon
|
|
48
|
+
(Lexicon-related syntax goes in `.wccm` files).
|
|
49
|
+
|
|
50
|
+
| Symbol | Field | Example |
|
|
51
|
+
| ------------ | --------------------- | -------------------------- |
|
|
52
|
+
| (None) | Word | **Kat** |
|
|
53
|
+
| `$` | IPA | **$kæt** |
|
|
54
|
+
| `#` | Semantic field | **\#animal** |
|
|
55
|
+
| `~` | Gender | **~M** |
|
|
56
|
+
| `?` | Translation | **?Cat** |
|
|
57
|
+
| `+` | Plural form(s) | **+Cats** |
|
|
58
|
+
| `;` and `:` | Case name / case form | **;gen :cat's** |
|
|
59
|
+
| `=` | Synonym(s) | **=feline** |
|
|
60
|
+
| `!` | Antonym(s) | **!dog** |
|
|
61
|
+
| `%` | Part of speech | **%noun** |
|
|
62
|
+
| `*` | Etymology | **\*from 'kaltnaen' ** |
|
|
63
|
+
| `\|` and `/` | Conjugations | **\|3rd sg present /does** |
|
|
64
|
+
| `@` and `:` | Custom | **@class :animte** |
|
|
65
|
+
## Inventory
|
|
66
|
+
(Inventory-related information goes in `.cmi` files).
|
|
67
|
+
|
|
68
|
+
| Symbol | Field | Example |
|
|
69
|
+
| ------ | --------- | ------------ |
|
|
70
|
+
| `.` | consonant | **.tH** |
|
|
71
|
+
| `,` | vowel | **,3** |
|
|
72
|
+
| `^` | Tone | **\^rising** |
|
|
73
|
+
|
|
74
|
+
Don't like this set of symbols? That's completely fine! You can edit them anytime by going into `config.json`.
|
|
75
|
+
|
|
76
|
+
## IPA
|
|
77
|
+
I know that typing IPA symbols can be tedious if you don't have the tools, which is why I implemented a function to let you map a character to an IPA sound, to make writing transcriptions easier!
|
|
78
|
+
# Configuration
|
|
79
|
+
|
|
80
|
+
`config.json` lets you customize:
|
|
81
|
+
- what each symbol means (which property it represents)
|
|
82
|
+
- IPA character mapping (e.g., `:` -> `ː`)
|
|
83
|
+
- default output file
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"ipa": {
|
|
88
|
+
"S": "ʃ",
|
|
89
|
+
"T": "θ",
|
|
90
|
+
"R": "ɾ",
|
|
91
|
+
"B": "β",
|
|
92
|
+
"D": "ð",
|
|
93
|
+
"N": "ŋ",
|
|
94
|
+
"J": "ʲ",
|
|
95
|
+
"Z": "ʒ",
|
|
96
|
+
":": "ː",
|
|
97
|
+
"'": "ˈ",
|
|
98
|
+
"ny": "ɲ",
|
|
99
|
+
"W": "ʷ",
|
|
100
|
+
"H": "ʰ",
|
|
101
|
+
"A": "ɑ",
|
|
102
|
+
"E": "ə",
|
|
103
|
+
"I": "ɪ",
|
|
104
|
+
"3": "ɛ",
|
|
105
|
+
"O": "ɔ",
|
|
106
|
+
"U": "ʊ",
|
|
107
|
+
"^": "ʌ",
|
|
108
|
+
"X": "χ"
|
|
109
|
+
},
|
|
110
|
+
"props": {
|
|
111
|
+
"$": "ipa",
|
|
112
|
+
"#": "field",
|
|
113
|
+
"%": "pos",
|
|
114
|
+
"_": "comment",
|
|
115
|
+
"~": "gender",
|
|
116
|
+
"=": "synonym",
|
|
117
|
+
"!": "antonym",
|
|
118
|
+
"+": "plural",
|
|
119
|
+
"?": "meaning",
|
|
120
|
+
"*": "etymology",
|
|
121
|
+
";": "case",
|
|
122
|
+
"|": "conjugations",
|
|
123
|
+
"@": "custom"
|
|
124
|
+
},
|
|
125
|
+
"inv": {
|
|
126
|
+
".": "consonant",
|
|
127
|
+
",": "vowel",
|
|
128
|
+
"^": "tone"
|
|
129
|
+
},
|
|
130
|
+
"prefs": {
|
|
131
|
+
"output": {
|
|
132
|
+
"defaultFileName": "lexicon",
|
|
133
|
+
"defaultFormat": ".txt"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
For the IPA replacement mapping, the character on the left is the character that the program will replace. So, essentially, if your IPA is "SaTaZ", with the default configurations (the ones showed above) it would turn into "ʃaθaʒ". You can add/remove as many as you want! (As long as you don't map 1 character to 2 symbols or use digraphs).
|
|
140
|
+
|
|
141
|
+
Same goes for the properties, although it is very important that you do **not** alter the keywords, otherwise the tool will break.
|
|
142
|
+
|
|
143
|
+
As you might've guessed, you can also choose the default name and format of the output file! The name can be anything you want, and the file extension can be either `.txt` or `.md`. A `lexicon.json` file is always automatically generated, which is why `.json` isn't an option in preferences.
|
|
144
|
+
## Limitations
|
|
145
|
+
|
|
146
|
+
Currently, the case symbols (`;` and `:`) can't be customized, as well as the conjugation symbols (`|` and `/`).
|
|
147
|
+
If you ever want to remap a symbol, as said before, you're allowed (and encouraged) to do so! However, it is very important that you don't map `\` to anything. Since i don't want to confuse you with tech talk, basically, `\` is a special character and if you try to use it for mapping the configuration file is going to break.
|
|
148
|
+
|
|
149
|
+
Other than that, you should be able to change pretty much anything!
|
|
150
|
+
|
|
151
|
+
# About
|
|
152
|
+
|
|
153
|
+
WCCM started as just a little personal tool I developed because I'm stubborn and don't like any of the tools that already exist, and now I'm sharing it in case someone finds it useful as well.
|
|
154
|
+
|
|
155
|
+
# Feedback is appreciated!
|
|
156
|
+
|
|
157
|
+
This is my first time actually finishing and sharing a project, so I'd genuinely *love* to hear suggestions or ideas for future versions, as well as bug reports and other stuff like that.
|
|
158
|
+
You can contact me pretty much any time in [my twitter (I'm not calling it 'X')](https://x.com/wernasho)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "wccm"
|
|
7
|
+
version = "0.2.3"
|
|
8
|
+
description = "Compact command-line conlang manager"
|
|
9
|
+
authors = [{ name = "Wernasho" }]
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
|
|
13
|
+
[project.scripts]
|
|
14
|
+
wccm = "wccm.wccm:main"
|
|
15
|
+
|
|
16
|
+
[tool.setuptools.package-data]
|
|
17
|
+
wccm = ["*.json"]
|
wccm-0.2.3/setup.cfg
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ipa": {
|
|
3
|
+
"S": "ʃ",
|
|
4
|
+
"R": "ɾ",
|
|
5
|
+
"B": "β",
|
|
6
|
+
"D": "ð",
|
|
7
|
+
"N": "ŋ",
|
|
8
|
+
"J": "ʲ",
|
|
9
|
+
"Z": "ʒ",
|
|
10
|
+
":": "ː",
|
|
11
|
+
"'": "ˈ",
|
|
12
|
+
"ny": "ɲ",
|
|
13
|
+
"W": "ʷ",
|
|
14
|
+
"H": "ʰ",
|
|
15
|
+
"A": "ɑ",
|
|
16
|
+
"T": "θ",
|
|
17
|
+
"E": "ə",
|
|
18
|
+
"I": "ɪ",
|
|
19
|
+
"3": "ɛ",
|
|
20
|
+
"O": "ɔ",
|
|
21
|
+
"U": "ʊ",
|
|
22
|
+
"^": "ʌ",
|
|
23
|
+
"X": "χ"
|
|
24
|
+
},
|
|
25
|
+
"props": {
|
|
26
|
+
"$": "ipa",
|
|
27
|
+
"#": "field",
|
|
28
|
+
"%": "pos",
|
|
29
|
+
"//": "comment",
|
|
30
|
+
"~": "gender",
|
|
31
|
+
"=": "synonym",
|
|
32
|
+
"!": "antonym",
|
|
33
|
+
"+": "plural",
|
|
34
|
+
"?": "meaning",
|
|
35
|
+
"*": "etymology",
|
|
36
|
+
";": "case",
|
|
37
|
+
"|": "conjugations",
|
|
38
|
+
"@": "custom"
|
|
39
|
+
},
|
|
40
|
+
"inv": {
|
|
41
|
+
".": "consonant",
|
|
42
|
+
",": "vowel",
|
|
43
|
+
"^": "tone",
|
|
44
|
+
"-": "romanization"
|
|
45
|
+
},
|
|
46
|
+
"prefs": {
|
|
47
|
+
"output": {
|
|
48
|
+
"defaultFileName": "lexicon",
|
|
49
|
+
"defaultFormat": ".txt"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
from .storage import load
|
|
2
|
+
|
|
3
|
+
def Format(entry):
|
|
4
|
+
text = f'{entry["word"]}'
|
|
5
|
+
|
|
6
|
+
if "ipa" in entry:
|
|
7
|
+
text += f' [{entry["ipa"]}]\n'
|
|
8
|
+
|
|
9
|
+
if "meaning" in entry:
|
|
10
|
+
if len(entry["meaning"]) >= 2:
|
|
11
|
+
text+= "Meanings:\n"
|
|
12
|
+
for m in entry["meaning"]:
|
|
13
|
+
text += f' - {m}\n'
|
|
14
|
+
else:
|
|
15
|
+
text+=f"Meaning: {entry["meaning"][0]}\n"
|
|
16
|
+
|
|
17
|
+
if "plural" in entry:
|
|
18
|
+
text += f'plural: "{entry["plural"]}"'
|
|
19
|
+
|
|
20
|
+
text += '\n'
|
|
21
|
+
|
|
22
|
+
if "gender" in entry:
|
|
23
|
+
text += f'Gender: {entry["gender"]}\n'
|
|
24
|
+
|
|
25
|
+
if "synonym" in entry:
|
|
26
|
+
text += "Synonyms: \n"
|
|
27
|
+
for syn in entry["synonym"]:
|
|
28
|
+
text += f" - {syn}\n"
|
|
29
|
+
|
|
30
|
+
if "antonym" in entry:
|
|
31
|
+
text += "Antonyms: \n"
|
|
32
|
+
for ant in entry["antonym"]:
|
|
33
|
+
text += f" - {ant}\n"
|
|
34
|
+
|
|
35
|
+
if "pos" in entry:
|
|
36
|
+
if len(entry["pos"]) == 2:
|
|
37
|
+
text+="Parts of speech:\n"
|
|
38
|
+
text+=f" {entry["pos"][0]}, {entry["pos"][1]}\n"
|
|
39
|
+
elif len(entry["pos"]) == 1:
|
|
40
|
+
text += f'Part Of Speech:'
|
|
41
|
+
text+=f" {entry["pos"]}"
|
|
42
|
+
else:
|
|
43
|
+
text+="Parts of speech:\n"
|
|
44
|
+
for pos in entry["pos"]:
|
|
45
|
+
text+=f" {pos}"
|
|
46
|
+
|
|
47
|
+
if "field" in entry:
|
|
48
|
+
text += f'Semantic field: {entry["field"]}\n'
|
|
49
|
+
|
|
50
|
+
if "cases" in entry:
|
|
51
|
+
text += 'Cases:\n'
|
|
52
|
+
for case, form in entry["cases"].items():
|
|
53
|
+
text += f' - {case}: {form}\n'
|
|
54
|
+
|
|
55
|
+
if "conjugations" in entry:
|
|
56
|
+
text += 'Conjugations:\n'
|
|
57
|
+
for conjugation, form in entry["conjugations"].items():
|
|
58
|
+
text+=f" - {conjugation}: {form}\n"
|
|
59
|
+
|
|
60
|
+
if "custom" in entry:
|
|
61
|
+
for custom, prop in entry["custom"].items():
|
|
62
|
+
text+=f"{custom}: {prop}"
|
|
63
|
+
|
|
64
|
+
print("Done! formatting complete!")
|
|
65
|
+
return text
|
|
66
|
+
|
|
67
|
+
def markdown(entry):
|
|
68
|
+
text = f'{entry["word"]}'
|
|
69
|
+
|
|
70
|
+
if "ipa" in entry:
|
|
71
|
+
text += f' *\\[{entry["ipa"]}]*'
|
|
72
|
+
text += '\n'
|
|
73
|
+
if "meaning" in entry:
|
|
74
|
+
if len(entry["meaning"]) >= 2:
|
|
75
|
+
text+= "**Meanings:**\n"
|
|
76
|
+
for m in entry["meaning"]:
|
|
77
|
+
text += f' - *{m}*\n'
|
|
78
|
+
else:
|
|
79
|
+
text+=f"**Meaning:** {entry["meaning"][0]}"
|
|
80
|
+
|
|
81
|
+
if "plural" in entry:
|
|
82
|
+
text += f'plural: "{entry["plural"]}"'
|
|
83
|
+
|
|
84
|
+
text += '\n'
|
|
85
|
+
|
|
86
|
+
if "gender" in entry:
|
|
87
|
+
text += f'**Gender:** {entry["gender"]}\n'
|
|
88
|
+
|
|
89
|
+
if "synonym" in entry:
|
|
90
|
+
text += "**Synonyms:** \n"
|
|
91
|
+
for syn in entry["synonym"]:
|
|
92
|
+
text += f" - *{syn}*\n"
|
|
93
|
+
|
|
94
|
+
if "antonym" in entry:
|
|
95
|
+
text += "**Antonyms:** \n"
|
|
96
|
+
for ant in entry["antonym"]:
|
|
97
|
+
text += f" - *{ant}*\n"
|
|
98
|
+
|
|
99
|
+
if "pos" in entry:
|
|
100
|
+
text += f'**Part(s) Of Speech:**'
|
|
101
|
+
if len(entry["pos"]) == 2:
|
|
102
|
+
text+=f" {entry["pos"][0]}, {entry["pos"][1]}"
|
|
103
|
+
elif len(entry["pos"]) == 1:
|
|
104
|
+
text+=f" {entry["pos"]}"
|
|
105
|
+
else:
|
|
106
|
+
for pos in entry["pos"]:
|
|
107
|
+
text+=f" {pos},"
|
|
108
|
+
text+="\n"
|
|
109
|
+
|
|
110
|
+
if "field" in entry:
|
|
111
|
+
text += f'**Semantic field:** \\{entry["field"]}\n'
|
|
112
|
+
|
|
113
|
+
if "cases" in entry:
|
|
114
|
+
text += '**Cases:**\n'
|
|
115
|
+
for case, form in entry["cases"].items():
|
|
116
|
+
text += f' - **{case}:** {form}\n'
|
|
117
|
+
|
|
118
|
+
if "conjugations" in entry:
|
|
119
|
+
text += '**Conjugations:**\n'
|
|
120
|
+
for conjugation, form in entry["conjugations"].items():
|
|
121
|
+
text+=f" - **{conjugation}:** {form}\n"
|
|
122
|
+
|
|
123
|
+
if "custom" in entry:
|
|
124
|
+
for custom, prop in entry["custom"].items():
|
|
125
|
+
text+=f"- **{custom}:** {prop}"
|
|
126
|
+
# print("Done! formatting complete!")
|
|
127
|
+
return text
|
|
128
|
+
|
|
129
|
+
def inv_f(dic):
|
|
130
|
+
text = ""
|
|
131
|
+
if "consonant" in dic:
|
|
132
|
+
text += "Consonants: \n"
|
|
133
|
+
for sound in dic["consonant"]:
|
|
134
|
+
text+= f" - {sound}\n"
|
|
135
|
+
|
|
136
|
+
if "vowel" in dic:
|
|
137
|
+
text += "Vowels: \n"
|
|
138
|
+
for sound in dic["vowel"]:
|
|
139
|
+
text += f" - {sound}\n"
|
|
140
|
+
|
|
141
|
+
if "tone" in dic:
|
|
142
|
+
text+= "Tones: "
|
|
143
|
+
for tone in dic["tone"]:
|
|
144
|
+
text +=f"{tone} "
|
|
145
|
+
|
|
146
|
+
if "romanization" in dic:
|
|
147
|
+
text += "Romanization:\n"
|
|
148
|
+
for ipa_symbol, roman in dic["romanization"].items():
|
|
149
|
+
text += f" - {ipa_symbol} → {roman}\n"
|
|
150
|
+
# print("Done! formatting complete!")
|
|
151
|
+
return text
|
|
152
|
+
|
|
153
|
+
if __name__ == '__main__':
|
|
154
|
+
entries = load()
|
|
155
|
+
|
|
156
|
+
T = ""
|
|
157
|
+
for entry in entries:
|
|
158
|
+
T += Format(entry) + "\n"
|
|
159
|
+
|
|
160
|
+
with open("lexicon.txt", "w", encoding="utf-8") as f:
|
|
161
|
+
f.write(T)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from .parse import ipa_replace
|
|
2
|
+
from .storage import config_load
|
|
3
|
+
|
|
4
|
+
config = config_load() # loads configurations from config.json
|
|
5
|
+
|
|
6
|
+
# function that parses the custom inventory syntax
|
|
7
|
+
def parse_inv(text, config):
|
|
8
|
+
props = config["inv"]
|
|
9
|
+
ipa = config["ipa"]
|
|
10
|
+
|
|
11
|
+
lines = text.splitlines()
|
|
12
|
+
inventory = {}
|
|
13
|
+
inventory["romanization"] = {}
|
|
14
|
+
inventory["vowel"] = []
|
|
15
|
+
inventory["consonant"] = []
|
|
16
|
+
inventory["tone"] = []
|
|
17
|
+
for line in lines:
|
|
18
|
+
line = line.strip()
|
|
19
|
+
if not line:
|
|
20
|
+
continue
|
|
21
|
+
symbol = line[0]
|
|
22
|
+
|
|
23
|
+
if symbol in props:
|
|
24
|
+
value = line[1:].strip()
|
|
25
|
+
prop_name = props[symbol]
|
|
26
|
+
|
|
27
|
+
key = prop_name
|
|
28
|
+
inventory[key]
|
|
29
|
+
if key == "romanization":
|
|
30
|
+
value = line[1:].strip()
|
|
31
|
+
try:
|
|
32
|
+
roman, ipa_symbol = value.split(":", 1)
|
|
33
|
+
ipa_symbol = ipa_symbol.strip()
|
|
34
|
+
ipa_symbol = ipa_replace(ipa_symbol, ipa)
|
|
35
|
+
roman = roman.strip()
|
|
36
|
+
|
|
37
|
+
if ipa_symbol and roman:
|
|
38
|
+
inventory["romanization"][roman] = ipa_symbol
|
|
39
|
+
|
|
40
|
+
except ValueError:
|
|
41
|
+
raise ValueError(f"Invalid romanization data: {line}")
|
|
42
|
+
|
|
43
|
+
elif key == "vowel" or key == "consonant" or key == "tone":
|
|
44
|
+
inventory[key].append(ipa_replace(value, ipa))
|
|
45
|
+
|
|
46
|
+
elif key not in inventory:
|
|
47
|
+
inventory[key] = []
|
|
48
|
+
if type(key) == list:
|
|
49
|
+
pass
|
|
50
|
+
#save(inventory, "info.json") # saves entries for... why do I save? Oh whatever it's already there.
|
|
51
|
+
print("Done! parse complete!")
|
|
52
|
+
return inventory
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from .storage import config_load
|
|
3
|
+
x = sys.argv[1]
|
|
4
|
+
settings = config_load()
|
|
5
|
+
def ipa_replace(text, config):
|
|
6
|
+
result = ""
|
|
7
|
+
i = 0
|
|
8
|
+
keys = sorted(config.keys(), key=len, reverse=True)
|
|
9
|
+
while i < len(text):
|
|
10
|
+
matched = False
|
|
11
|
+
for k in keys:
|
|
12
|
+
if text.startswith(k, i):
|
|
13
|
+
result += config[k]
|
|
14
|
+
i += len(k)
|
|
15
|
+
matched = True
|
|
16
|
+
break
|
|
17
|
+
if not matched:
|
|
18
|
+
result += text[i]
|
|
19
|
+
i += 1
|
|
20
|
+
return result
|
|
21
|
+
|
|
22
|
+
def LISTadd(entry, key, val):
|
|
23
|
+
if key not in entry:
|
|
24
|
+
entry[key] = []
|
|
25
|
+
entry[key].append(val)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def parse(name, text, config):
|
|
29
|
+
if not name.endswith(".wccm"):
|
|
30
|
+
print("Error: please use a .wccm file.")
|
|
31
|
+
exit()
|
|
32
|
+
|
|
33
|
+
props = config["props"]
|
|
34
|
+
IPA = config["ipa"]
|
|
35
|
+
symbol = sorted(props.keys(), key=len, reverse=True)
|
|
36
|
+
lines = text.splitlines()
|
|
37
|
+
entries = []
|
|
38
|
+
current = None
|
|
39
|
+
|
|
40
|
+
for line in lines:
|
|
41
|
+
line = line.strip()
|
|
42
|
+
if not line:
|
|
43
|
+
continue
|
|
44
|
+
|
|
45
|
+
# try to match any symbol at the start of the line
|
|
46
|
+
matched_symbol = None
|
|
47
|
+
for s in symbol:
|
|
48
|
+
if line.startswith(s):
|
|
49
|
+
matched_symbol = s
|
|
50
|
+
break
|
|
51
|
+
|
|
52
|
+
if matched_symbol:
|
|
53
|
+
value = line[len(matched_symbol):].strip()
|
|
54
|
+
prop_name = props[matched_symbol]
|
|
55
|
+
|
|
56
|
+
# check the first character of the line is mapped to anything
|
|
57
|
+
#if symbol in props:
|
|
58
|
+
# value = line[1:].strip()
|
|
59
|
+
# prop_name = props[symbol]
|
|
60
|
+
|
|
61
|
+
if current is None:
|
|
62
|
+
current = {}
|
|
63
|
+
|
|
64
|
+
if prop_name == "ipa":
|
|
65
|
+
current["ipa_raw"] = value
|
|
66
|
+
current["ipa"] = ipa_replace(value, IPA) # IPA mapping thing
|
|
67
|
+
|
|
68
|
+
elif prop_name == "field":
|
|
69
|
+
LISTadd(current, "field", value)
|
|
70
|
+
elif prop_name == "gender":
|
|
71
|
+
current["gender"] = value
|
|
72
|
+
elif prop_name == "pos":
|
|
73
|
+
LISTadd(current, "pos", value)
|
|
74
|
+
elif prop_name == "meaning":
|
|
75
|
+
LISTadd(current, "meaning", value)
|
|
76
|
+
elif prop_name == "plural":
|
|
77
|
+
current["plural"] = value
|
|
78
|
+
elif prop_name == "synonym":
|
|
79
|
+
LISTadd(current, "synonym", value)
|
|
80
|
+
elif prop_name == "antonym":
|
|
81
|
+
LISTadd(current, "antonym", value)
|
|
82
|
+
elif prop_name == "etymology":
|
|
83
|
+
current["etymology"] = value
|
|
84
|
+
|
|
85
|
+
# special case for grammatical cases (using ';')
|
|
86
|
+
elif prop_name == "cases":
|
|
87
|
+
case_, form = value.split(":", 1)
|
|
88
|
+
case_ = case_.strip()
|
|
89
|
+
form = form.strip()
|
|
90
|
+
|
|
91
|
+
if not case_ or not form:
|
|
92
|
+
raise ValueError(f"Invalid case data: {value}")
|
|
93
|
+
|
|
94
|
+
if "cases" not in current:
|
|
95
|
+
current["cases"] = {}
|
|
96
|
+
current["cases"][case_] = form
|
|
97
|
+
|
|
98
|
+
# special case 2, using '|' for conjugations
|
|
99
|
+
elif prop_name == "conjugations":
|
|
100
|
+
conjugation, form = value.split("/", 1)
|
|
101
|
+
conjugation = conjugation.strip()
|
|
102
|
+
form = form.strip()
|
|
103
|
+
|
|
104
|
+
if "conjugations" not in current:
|
|
105
|
+
current["conjugations"] = {}
|
|
106
|
+
current["conjugations"][conjugation] = form
|
|
107
|
+
|
|
108
|
+
if not conjugation or not form:
|
|
109
|
+
raise ValueError(f"Invalid conjugation data: {value}")
|
|
110
|
+
|
|
111
|
+
# special case 3: custom properties
|
|
112
|
+
elif prop_name == "custom":
|
|
113
|
+
custom, val = value.split(":", 1)
|
|
114
|
+
custom = custom.strip()
|
|
115
|
+
val = val.strip()
|
|
116
|
+
|
|
117
|
+
if "custom" not in current:
|
|
118
|
+
current["custom"] = {}
|
|
119
|
+
current["custom"][custom] = val
|
|
120
|
+
elif prop_name == "comment": continue
|
|
121
|
+
else:
|
|
122
|
+
# No property symbol found -> New word
|
|
123
|
+
if current:
|
|
124
|
+
entries.append(current)
|
|
125
|
+
current = {"word": line}
|
|
126
|
+
|
|
127
|
+
if current:
|
|
128
|
+
entries.append(current)
|
|
129
|
+
|
|
130
|
+
return entries
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import importlib.resources
|
|
3
|
+
def save(data, file="lexicon.json"):
|
|
4
|
+
with importlib.resources.open_text("wccm", file or "lexicon.json") as f:
|
|
5
|
+
json.dump(data, f, indent=2, ensure_ascii=False)
|
|
6
|
+
def load():
|
|
7
|
+
with importlib.resources.open_text("wccm", "lexicon.json") as f:
|
|
8
|
+
return json.load(f)
|
|
9
|
+
|
|
10
|
+
def config_load():
|
|
11
|
+
with importlib.resources.open_text("wccm", "config.json") as f:
|
|
12
|
+
return json.load(f)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from .parse import parse
|
|
2
|
+
from .formatter import Format, markdown, inv_f
|
|
3
|
+
import sys
|
|
4
|
+
from .storage import save, config_load
|
|
5
|
+
from .infoParse import parse_inv
|
|
6
|
+
|
|
7
|
+
def main():
|
|
8
|
+
|
|
9
|
+
config = config_load()
|
|
10
|
+
arg = sys.argv[1]
|
|
11
|
+
if len(sys.argv) >= 2:
|
|
12
|
+
output = sys.argv[2]
|
|
13
|
+
|
|
14
|
+
else:
|
|
15
|
+
output = f"{config["prefs"]["output"]["defaultFileName"]}.{config["prefs"]["output"]["defaultFormat"]}"
|
|
16
|
+
|
|
17
|
+
text = ""
|
|
18
|
+
|
|
19
|
+
if not arg:
|
|
20
|
+
print("Usage: py wccm.py file.wccm output.txt or py wccm.py file.cmi output.txt")
|
|
21
|
+
exit()
|
|
22
|
+
|
|
23
|
+
elif not (arg.endswith(".wccm") or arg.endswith(".cmi")):
|
|
24
|
+
print("Please use a valid file extension. Valid extensions: \n.wccm\n.cmi")
|
|
25
|
+
exit()
|
|
26
|
+
|
|
27
|
+
cm = False
|
|
28
|
+
|
|
29
|
+
if arg.endswith(".wccm"): cm = True
|
|
30
|
+
|
|
31
|
+
if not (output.endswith(".txt") or output.endswith(".md")):
|
|
32
|
+
print("Please select a valid output extension: .md or .txt")
|
|
33
|
+
print("a 'lexicon.json' file is automatically generated, if that's what you wish.")
|
|
34
|
+
exit()
|
|
35
|
+
|
|
36
|
+
with open(arg, "r", encoding="utf-8") as f:
|
|
37
|
+
text = f.read()
|
|
38
|
+
if cm:
|
|
39
|
+
entries = parse(arg, text, config)
|
|
40
|
+
formatted_text = ""
|
|
41
|
+
if not output or output.endswith(".txt"):
|
|
42
|
+
for entry in entries:
|
|
43
|
+
formatted_text += Format(entry) + "\n\n" + "----" + "\n"
|
|
44
|
+
elif output.endswith(".md"):
|
|
45
|
+
for entry in entries:
|
|
46
|
+
formatted_text += markdown(entry) + "\n\n" + "----" + "\n"
|
|
47
|
+
|
|
48
|
+
if not output:
|
|
49
|
+
with open(f"{config["prefs"]["output"]["defaultFileName"]}.{config["prefs"]["output"]["defaultFormat"]}", "w", encoding="utf-8") as f:
|
|
50
|
+
f.write(formatted_text)
|
|
51
|
+
elif output.endswith(".txt"):
|
|
52
|
+
with open(output, "w", encoding="utf-8") as f:
|
|
53
|
+
f.write(formatted_text)
|
|
54
|
+
elif output.endswith(".md"):
|
|
55
|
+
with open(output, "w", encoding="utf-8") as f:
|
|
56
|
+
f.write(formatted_text)
|
|
57
|
+
# saves data to master.json for... reasons...?? Idk man this is already here and I'm too lazy to change it
|
|
58
|
+
#save(entries)
|
|
59
|
+
|
|
60
|
+
print(f"Done! Created {output} with {len(entries)} entries.")
|
|
61
|
+
else:
|
|
62
|
+
inv = parse_inv(text, config)
|
|
63
|
+
formatted = inv_f(inv)
|
|
64
|
+
|
|
65
|
+
save(inv, "info.json")
|
|
66
|
+
|
|
67
|
+
with open(output, "w", encoding="utf-8") as f:
|
|
68
|
+
f.write(formatted)
|
|
69
|
+
print(f"Done! created {output}.")
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wccm
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Summary: Compact command-line conlang manager
|
|
5
|
+
Author: Wernasho
|
|
6
|
+
Requires-Python: >=3.8
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Dynamic: license-file
|
|
10
|
+
|
|
11
|
+
Wer's Compact Conlang Manager, or WCCM, is a simple command-line tool designed to make conlanging ever so slightly faster and easier by converting a simple, customizeable syntax into clean and readable conlang dictionaries.
|
|
12
|
+
|
|
13
|
+
I built this because spreadsheets had too much visual clutter and other existing tools were really overkill.
|
|
14
|
+
All you need to do is type your properties with shorthands you can customize, and you'll receive a nicely formatted text file.
|
|
15
|
+
|
|
16
|
+
For example, this:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Agná
|
|
20
|
+
$agˈna
|
|
21
|
+
%noun
|
|
22
|
+
#animals
|
|
23
|
+
?bird
|
|
24
|
+
~Masculine
|
|
25
|
+
+ágnaya
|
|
26
|
+
;gen :ágnand
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Turns into this:
|
|
30
|
+
```
|
|
31
|
+
Agná
|
|
32
|
+
\[agˈna] bird, plural: ágnaya
|
|
33
|
+
Gender: Masculine
|
|
34
|
+
POS: Noun
|
|
35
|
+
Semantic field: animals
|
|
36
|
+
Cases:
|
|
37
|
+
gen: ágnand
|
|
38
|
+
```
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
1. install Python 3.6 or newer from [python.org](https://python.org)
|
|
42
|
+
2. download or clone this repository
|
|
43
|
+
3. no additional packages are needed, uses only python standard library!
|
|
44
|
+
|
|
45
|
+
# Usage:
|
|
46
|
+
Open up your console/terminal inside the wccm folder, and run this command:
|
|
47
|
+
```bash
|
|
48
|
+
py wccm.py file.wccm
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Outputs to `Lexicon.txt`
|
|
52
|
+
|
|
53
|
+
# Syntax
|
|
54
|
+
|
|
55
|
+
WCCM uses symbols to represent different properties. Their order is irrelevant, as long as the plain word is always first.
|
|
56
|
+
|
|
57
|
+
## Lexicon
|
|
58
|
+
(Lexicon-related syntax goes in `.wccm` files).
|
|
59
|
+
|
|
60
|
+
| Symbol | Field | Example |
|
|
61
|
+
| ------------ | --------------------- | -------------------------- |
|
|
62
|
+
| (None) | Word | **Kat** |
|
|
63
|
+
| `$` | IPA | **$kæt** |
|
|
64
|
+
| `#` | Semantic field | **\#animal** |
|
|
65
|
+
| `~` | Gender | **~M** |
|
|
66
|
+
| `?` | Translation | **?Cat** |
|
|
67
|
+
| `+` | Plural form(s) | **+Cats** |
|
|
68
|
+
| `;` and `:` | Case name / case form | **;gen :cat's** |
|
|
69
|
+
| `=` | Synonym(s) | **=feline** |
|
|
70
|
+
| `!` | Antonym(s) | **!dog** |
|
|
71
|
+
| `%` | Part of speech | **%noun** |
|
|
72
|
+
| `*` | Etymology | **\*from 'kaltnaen' ** |
|
|
73
|
+
| `\|` and `/` | Conjugations | **\|3rd sg present /does** |
|
|
74
|
+
| `@` and `:` | Custom | **@class :animte** |
|
|
75
|
+
## Inventory
|
|
76
|
+
(Inventory-related information goes in `.cmi` files).
|
|
77
|
+
|
|
78
|
+
| Symbol | Field | Example |
|
|
79
|
+
| ------ | --------- | ------------ |
|
|
80
|
+
| `.` | consonant | **.tH** |
|
|
81
|
+
| `,` | vowel | **,3** |
|
|
82
|
+
| `^` | Tone | **\^rising** |
|
|
83
|
+
|
|
84
|
+
Don't like this set of symbols? That's completely fine! You can edit them anytime by going into `config.json`.
|
|
85
|
+
|
|
86
|
+
## IPA
|
|
87
|
+
I know that typing IPA symbols can be tedious if you don't have the tools, which is why I implemented a function to let you map a character to an IPA sound, to make writing transcriptions easier!
|
|
88
|
+
# Configuration
|
|
89
|
+
|
|
90
|
+
`config.json` lets you customize:
|
|
91
|
+
- what each symbol means (which property it represents)
|
|
92
|
+
- IPA character mapping (e.g., `:` -> `ː`)
|
|
93
|
+
- default output file
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"ipa": {
|
|
98
|
+
"S": "ʃ",
|
|
99
|
+
"T": "θ",
|
|
100
|
+
"R": "ɾ",
|
|
101
|
+
"B": "β",
|
|
102
|
+
"D": "ð",
|
|
103
|
+
"N": "ŋ",
|
|
104
|
+
"J": "ʲ",
|
|
105
|
+
"Z": "ʒ",
|
|
106
|
+
":": "ː",
|
|
107
|
+
"'": "ˈ",
|
|
108
|
+
"ny": "ɲ",
|
|
109
|
+
"W": "ʷ",
|
|
110
|
+
"H": "ʰ",
|
|
111
|
+
"A": "ɑ",
|
|
112
|
+
"E": "ə",
|
|
113
|
+
"I": "ɪ",
|
|
114
|
+
"3": "ɛ",
|
|
115
|
+
"O": "ɔ",
|
|
116
|
+
"U": "ʊ",
|
|
117
|
+
"^": "ʌ",
|
|
118
|
+
"X": "χ"
|
|
119
|
+
},
|
|
120
|
+
"props": {
|
|
121
|
+
"$": "ipa",
|
|
122
|
+
"#": "field",
|
|
123
|
+
"%": "pos",
|
|
124
|
+
"_": "comment",
|
|
125
|
+
"~": "gender",
|
|
126
|
+
"=": "synonym",
|
|
127
|
+
"!": "antonym",
|
|
128
|
+
"+": "plural",
|
|
129
|
+
"?": "meaning",
|
|
130
|
+
"*": "etymology",
|
|
131
|
+
";": "case",
|
|
132
|
+
"|": "conjugations",
|
|
133
|
+
"@": "custom"
|
|
134
|
+
},
|
|
135
|
+
"inv": {
|
|
136
|
+
".": "consonant",
|
|
137
|
+
",": "vowel",
|
|
138
|
+
"^": "tone"
|
|
139
|
+
},
|
|
140
|
+
"prefs": {
|
|
141
|
+
"output": {
|
|
142
|
+
"defaultFileName": "lexicon",
|
|
143
|
+
"defaultFormat": ".txt"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
For the IPA replacement mapping, the character on the left is the character that the program will replace. So, essentially, if your IPA is "SaTaZ", with the default configurations (the ones showed above) it would turn into "ʃaθaʒ". You can add/remove as many as you want! (As long as you don't map 1 character to 2 symbols or use digraphs).
|
|
150
|
+
|
|
151
|
+
Same goes for the properties, although it is very important that you do **not** alter the keywords, otherwise the tool will break.
|
|
152
|
+
|
|
153
|
+
As you might've guessed, you can also choose the default name and format of the output file! The name can be anything you want, and the file extension can be either `.txt` or `.md`. A `lexicon.json` file is always automatically generated, which is why `.json` isn't an option in preferences.
|
|
154
|
+
## Limitations
|
|
155
|
+
|
|
156
|
+
Currently, the case symbols (`;` and `:`) can't be customized, as well as the conjugation symbols (`|` and `/`).
|
|
157
|
+
If you ever want to remap a symbol, as said before, you're allowed (and encouraged) to do so! However, it is very important that you don't map `\` to anything. Since i don't want to confuse you with tech talk, basically, `\` is a special character and if you try to use it for mapping the configuration file is going to break.
|
|
158
|
+
|
|
159
|
+
Other than that, you should be able to change pretty much anything!
|
|
160
|
+
|
|
161
|
+
# About
|
|
162
|
+
|
|
163
|
+
WCCM started as just a little personal tool I developed because I'm stubborn and don't like any of the tools that already exist, and now I'm sharing it in case someone finds it useful as well.
|
|
164
|
+
|
|
165
|
+
# Feedback is appreciated!
|
|
166
|
+
|
|
167
|
+
This is my first time actually finishing and sharing a project, so I'd genuinely *love* to hear suggestions or ideas for future versions, as well as bug reports and other stuff like that.
|
|
168
|
+
You can contact me pretty much any time in [my twitter (I'm not calling it 'X')](https://x.com/wernasho)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/wccm/config.json
|
|
5
|
+
src/wccm/formatter.py
|
|
6
|
+
src/wccm/info.json
|
|
7
|
+
src/wccm/infoParse.py
|
|
8
|
+
src/wccm/lexicon.json
|
|
9
|
+
src/wccm/parse.py
|
|
10
|
+
src/wccm/storage.py
|
|
11
|
+
src/wccm/wccm.py
|
|
12
|
+
src/wccm.egg-info/PKG-INFO
|
|
13
|
+
src/wccm.egg-info/SOURCES.txt
|
|
14
|
+
src/wccm.egg-info/dependency_links.txt
|
|
15
|
+
src/wccm.egg-info/entry_points.txt
|
|
16
|
+
src/wccm.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
wccm
|