├── .gitattributes
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── all-packages.bat
├── all-packages.conf
├── extra-packages.bat
├── extra-packages.conf
├── preset-packages.bat
├── preset-packages.conf
├── rime-install
├── rime-install-bootstrap.bat
├── rime-install-config.bat
├── rime-install.bat
└── scripts
├── bootstrap.sh
├── fetch-package.sh
├── frontend.sh
├── install-packages.sh
├── minimal-build.sh
├── recipe.sh
├── resolver.sh
├── selector.sh
├── split-packages.sh
├── styles.sh
└── update-package.sh
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | *.bat text eol=crlf
3 | *.conf text eol=lf
4 | *.sh text eol=lf
5 | rime-install text eol=lf
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | /package
3 | /output
4 | plum-*.tar.gz
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(SRCDIR),)
2 | SRCDIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
3 | endif
4 |
5 | # Tips: you can set OUTPUT to Rime user directory in the command line
6 | ifeq ($(OUTPUT),)
7 | OUTPUT := $(SRCDIR)/output
8 | endif
9 |
10 | ifeq ($(PREFIX),)
11 | PREFIX := /usr
12 | endif
13 |
14 | ifeq ($(RIME_DATA_DIR),)
15 | RIME_DATA_DIR := $(PREFIX)/share/rime-data
16 | endif
17 |
18 | .DEFAULT_GOAL := preset
19 |
20 | preset extra all: clean
21 | bash $(SRCDIR)/scripts/install-packages.sh :$@ $(OUTPUT)
22 |
23 | minimal: clean
24 | bash $(SRCDIR)/scripts/minimal-build.sh $(OUTPUT)
25 |
26 | preset-bin: preset
27 | $(MAKE) build
28 |
29 | all-bin: all
30 | $(MAKE) build
31 |
32 | minimal-bin: minimal
33 | $(MAKE) build
34 |
35 | build:
36 | rime_deployer --build $(OUTPUT)
37 | rm $(OUTPUT)/user.yaml
38 |
39 | install:
40 | @echo "Installing Rime data to '$(DESTDIR)$(RIME_DATA_DIR)'."
41 | @install -d $(DESTDIR)$(RIME_DATA_DIR)
42 | @install -m 644 $(OUTPUT)/*.* $(DESTDIR)$(RIME_DATA_DIR)
43 | @if [ -d "$(OUTPUT)/build" ]; then \
44 | install -d $(DESTDIR)$(RIME_DATA_DIR)/build; \
45 | install -m 644 $(OUTPUT)/build/*.* $(DESTDIR)$(RIME_DATA_DIR)/build; \
46 | fi
47 | @if [ -d "$(OUTPUT)/opencc" ]; then \
48 | install -d $(DESTDIR)$(RIME_DATA_DIR)/opencc; \
49 | install -m 644 $(OUTPUT)/opencc/*.* $(DESTDIR)$(RIME_DATA_DIR)/opencc; \
50 | fi
51 |
52 | clean:
53 | rm -rf $(OUTPUT) > /dev/null 2>&1 || true
54 |
55 | VERSION = $(shell date "+%Y%m%d")
56 |
57 | # A source tarball that includes all data packages.
58 | # To reproduce package contents of the release, set `no_update=1`:
59 | # tar xzf plum-YYYYMMDD.tar.gz
60 | # cd plum
61 | # no_update=1 make
62 | # sudo make install
63 | dist:
64 | $(MAKE) OUTPUT=$(OUTPUT) all
65 | tar czf plum-$(VERSION).tar.gz \
66 | --exclude=.git \
67 | --exclude=output \
68 | --exclude='plum-*.tar.gz' \
69 | -C .. plum
70 |
71 | .PHONY: preset extra all minimal \
72 | preset-bin all-bin minimal-bin \
73 | build install clean dist
74 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # 東風破 /plum/
4 |
5 | Rime configuration manager and input schema repository
6 |
7 | ## Project home
8 |
9 | [rime.im](https://rime.im)
10 |
11 | ## Introduction
12 |
13 | **/plum/** is a configuration manager for [Rime](https://rime.im) input method engine.
14 |
15 | /// **東風破** 是 [中州韻輸入法引擎](https://rime.im) 的配置管理工具。///
16 |
17 | It's designed for Rime users to install and update the default configuration and a collection
18 | of data packages maintained by [Rime Developers](https://github.com/rime).
19 |
20 | It also works perfectly well with personal configuration hosted on GitHub and input schema packages
21 | from third-party developers.
22 |
23 | A **Rime input schema** (**Rime 輸入方案**) defines the rules of a specific "input method", or in technical terms
24 | how user input sequences are interpreted by the Rime input method engine.
25 | It consists of a configuration file named `.schema.yaml`, and usually an optional
26 | **Rime dictionary** (**韻書**) file named `*.dict.yaml`.
27 |
28 | A package may contain one or several interrelated input schemata and their affiliated Rime dictionaries.
29 | A package is also good for publishing general configuration files and data files used by Rime.
30 |
31 | In /plum/ terms, a re-usable piece of configuration is known as a **recipe** (**配方**), denoted by the "℞" symbol.
32 |
33 | A data package itself can be a recipe, this is the common case.
34 | In the future, /plum/ will support more fine-grained recipes that allow you to select what to install from a package,
35 | or even take parameters like the target input schema to customize.
36 |
37 | ## Packages
38 |
39 | This is an index of the packages maintained by Rime Developers as separate projects.
40 |
41 | These packages aim to offer a sensible default configuration for most users, and support various
42 | Chinese input methods including those based on modern dialects and historical Chinese phonology.
43 |
44 | /// **配方一覽** ///
45 |
46 | ### Essentials
47 |
48 | - ℞ [`prelude`](https://github.com/rime/rime-prelude): 基礎配置 / the prelude package, providing Rime's default settings
49 | - ℞ [`essay`](https://github.com/rime/rime-essay): 八股文 / a shared vocabulary and language model
50 |
51 | ### Phonetic-based input methods
52 |
53 | Modern Standard Mandarin
54 |
55 | - ℞ [`luna-pinyin`](https://github.com/rime/rime-luna-pinyin): 朙月拼音 / Pinyin input method for Traditional Chinese
56 | - ℞ [`terra-pinyin`](https://github.com/rime/rime-terra-pinyin): 地球拼音 / School-taught Pinyin, with tone marks
57 | - ℞ [`bopomofo`](https://github.com/rime/rime-bopomofo): 注音 / Zhuyin (aka. Bopomofo)
58 | - ℞ [`pinyin-simp`](https://github.com/rime/rime-pinyin-simp): 袖珍簡化字拼音
59 |
60 | Derivatives of Pinyin
61 |
62 | - ℞ [`double-pinyin`](https://github.com/rime/rime-double-pinyin): 雙拼 / Double Pinyin (ZiRanMa, ABC, flyPY, MSPY, PYJJ variants)
63 | - ℞ [`combo-pinyin`](https://github.com/rime/rime-combo-pinyin): 宮保拼音 / [Combo Pinyin](https://github.com/rime/home/wiki/ComboPinyin), a chord-typing input method
64 | - ℞ [`stenotype`](https://github.com/rime/rime-stenotype): 打字速記法 / a stenographic system derived from ABC Easy Shorthand
65 |
66 | Other modern varieties of Chinese
67 |
68 | - ℞ [`cantonese`](https://github.com/rime/rime-cantonese): 粵語拼音 / Cantonese
69 | - ℞ [`jyutping`](https://github.com/rime/rime-jyutping): 粵拼(無聲調) / Cantonese (without tones)
70 | - ℞ [`wugniu`](https://github.com/rime/rime-wugniu): 上海吳語 / Wu (Shanghainese)
71 | - ℞ [`soutzoe`](https://github.com/rime/rime-soutzoe): 蘇州吳語 / Wu (Suzhounese)
72 |
73 | Middle Chinese
74 |
75 | - ℞ [`middle-chinese`](https://github.com/rime/rime-middle-chinese): 中古漢語拼音 / Middle Chinese Romanization
76 |
77 | ### Shape-based input methods
78 |
79 | - ℞ [`stroke`](https://github.com/rime/rime-stroke): 五筆畫 / five strokes
80 | - ℞ [`cangjie`](https://github.com/rime/rime-cangjie): 倉頡輸入法 / Cangjie input method
81 | - ℞ [`quick`](https://github.com/rime/rime-quick): 速成 / Simplified Cangjie
82 | - ℞ [`wubi`](https://github.com/rime/rime-wubi): 五筆字型
83 | - ℞ [`array`](https://github.com/rime/rime-array): 行列輸入法
84 | - ℞ [`scj`](https://github.com/rime/rime-scj): 快速倉頡
85 |
86 | ### Miscellaneous
87 |
88 | - ℞ [`emoji`](https://github.com/rime/rime-emoji): 繪文字 / input emoji with English or Chinese Pinyin keywords
89 | - ℞ [`ipa`](https://github.com/rime/rime-ipa): 國際音標 / International Phonetic Alphabet
90 |
91 | ## Usage
92 |
93 | To prepare your Rime configuration for [ibus-rime](https://github.com/rime/ibus-rime),
94 | [Squirrel](https://github.com/rime/squirrel), you can get started by running
95 |
96 | ```sh
97 | curl -fsSL https://raw.githubusercontent.com/rime/plum/master/rime-install | bash
98 | ```
99 |
100 | /// 用法:Linux、macOS 系統,在終端輸入以上命令行,安裝配置管理器及預設配方。 ///
101 |
102 | Paste the command line in Linux terminal or macOS `Terminal.app` and hit enter.
103 |
104 | The one-liner runs the `rime-install` script to download preset packages and install
105 | source files to Rime user directory. (Yet it doesn't enable new schemas for you)
106 |
107 | For [Weasel](https://github.com/rime/weasel), please refer to the [Windows bootstrap script](#windows) section for initial setup.
108 |
109 | ## Advanced usage
110 |
111 | Alternatively, you can specify a configuration among `:preset`, `:extra` and `:all` (note the colon):
112 |
113 | ```sh
114 | curl -fsSL https://raw.githubusercontent.com/rime/plum/master/rime-install | bash -s -- :preset
115 | ```
116 |
117 | This is equivalent to cloning this repo and running the local copy of `rime-install`:
118 |
119 | ```sh
120 | git clone --depth 1 https://github.com/rime/plum.git
121 | cd plum
122 | bash rime-install :preset
123 | ```
124 |
125 | You can then add packages from all the great Rime developers on GitHub by specifying
126 | a list of package names or refer to packages by `/`:
127 |
128 | ```sh
129 | bash rime-install jyutping lotem/rime-zhung acevery/rime-zhengma
130 |
131 | # optionally, specific a branch by appending "@"
132 | bash rime-install jyutping@master lotem/rime-zhung@master
133 | ```
134 |
135 | Lastly, it's also possible to install other author's Rime configuration from a
136 | `*-packages.conf` file hosted on GitHub. For example:
137 |
138 |
139 | ```sh
140 | bash rime-install https://github.com/lotem/rime-forge/raw/master/lotem-packages.conf
141 |
142 | # or in short form: "//"
143 | bash rime-install lotem/rime-forge/lotem-packages.conf
144 |
145 | # or specify a branch: "/@/"
146 | bash rime-install lotem/rime-forge@master/lotem-packages.conf
147 | ```
148 |
149 | For third-party Rime distributions, specify the `rime_frontend` variable in the command line:
150 |
151 | ```sh
152 | rime_frontend=fcitx-rime bash rime-install
153 | ```
154 |
155 | or set `rime_dir` to Rime user directory
156 |
157 | ```sh
158 | rime_dir="$HOME/.config/fcitx/rime" bash rime-install
159 | ```
160 |
161 | To update /plum/ itself, run
162 |
163 | ```sh
164 | bash rime-install plum
165 | ```
166 |
167 | ## Interactively select packages to install
168 |
169 | Specify the `--select` flag as the first argument to `rime-install`,
170 | then add configurations (`:preset` is the default) and/or individual packages to display in the menu.
171 |
172 | ```sh
173 | bash rime-install --select :extra
174 |
175 | bash rime-install --select :all lotem/rime-forge/lotem-packages.conf
176 | ```
177 |
178 | [Screenshot](https://github.com/rime/home/raw/master/images/rime-install-select.png) of usage example
179 |
180 |
181 | ## Windows bootstrap script
182 |
183 | To get started on Windows, download the [bootstrap bundle][bootstrap-bundle],
184 | unpack the ZIP archive and run `rime-install-bootstrap.bat` for initial setup.
185 |
186 | It will fetch the latest installer script `rime-install.bat` an create a shortcut to it,
187 | which can then be copied or moved anywhere for easier access.
188 |
189 | /// Windows 用家可以通過 [小狼毫](https://rime.im/download/#windows) 0.11 以上「輸入法設定/獲取更多輸入方案」調用配置管理器。///
190 |
191 | /// 或者下載獨立的 [啓動工具包][bootstrap-bundle]。///
192 |
193 | [bootstrap-bundle]: https://github.com/rime/plum-windows-bootstrap/archive/master.zip
194 |
195 | ### Use built-in ZIP package installer
196 |
197 | You can use the installer script to download and install ZIP packages from GitHub, in a number of ways:
198 |
199 | 1. Double-click the shortcut to bring up an interactive package installer, then input package name, `/` or GitHub URL for the package.
200 |
201 | 2. Run `rime-install.bat` in the command line. The command takes a list of packages to install as arguments.
202 |
203 | ```batch
204 | rime-install :preset combo-pinyin jyutping wubi
205 | ```
206 |
207 | 3. Drag downloaded ZIP packages from GitHub onto the shortcut to do offline install.
208 |
209 | You can find ZIP packages downloaded by the installer script in `%TEMP%` folder (can be customized via variable `download_cache_dir`).
210 |
211 | To manually download ZIP package from a GitHub repository, click the button *Clone or download*, then *Download ZIP*.
212 |
213 | ### Use git for incremental updates (optional)
214 |
215 | If [Git for Windows](https://gitforwindows.org/) is installed in the default location or is available in your `PATH`,
216 | the script will use git-bash to install or update packages.
217 |
218 | Use the following command to install Git for Windows, if you are new to git.
219 |
220 | ```batch
221 | rime-install git
222 | ```
223 |
224 | You can set more options in `rime-install-config.bat` in the same directory as `rime-install.bat`, for example:
225 |
226 | ```batch
227 | set plum_dir=%APPDATA%\plum
228 | set rime_dir=%APPDATA%\Rime
229 | set use_plum=1
230 | ```
231 |
232 | ## Install as shared data
233 |
234 | The `Makefile` builds and installs Rime data as a software on Unix systems.
235 |
236 | For downstream packagers for the package management systems of the OS, it's recommend to create
237 | separate packages for the /plum/ configuration manager (possibly named `rime-plum` or `rime-install`)
238 | and the data package(s) (possibly named `rime-data`, or `rime-data-*` if separated into many)
239 | created by the make targets.
240 |
241 | ### Build dependencies
242 |
243 | - git
244 | - librime>=1.3 (for `rime_deployer`)
245 |
246 | ### Run-time dependencies
247 |
248 | - librime>=1.3
249 | - opencc>=1.0.2
250 |
251 | ### Build and install
252 |
253 | The default make target uses `git` command to download the latest packages from GitHub.
254 |
255 | ```sh
256 | make
257 | sudo make install
258 | ```
259 |
260 | You can optionally build the by default enabled input schemas to binaries.
261 | This saves user's time building those files on first startup.
262 |
263 | ```sh
264 | make preset-bin
265 | ```
266 |
267 | ## License
268 |
269 | Code in the `rime/plum` repository is licensed under **LGPLv3**.
270 | Please refer to the `LICENSE` file in the project root directory.
271 |
272 | **Note** that make targets provided by the `Makefile` may include files downloaded by the
273 | configuration manager. Individual packages can be released under different licenses.
274 | Please refer to their respective `LICENSE` files.
275 | The license compatible with all the maintained packages is **GPLv3**.
276 |
277 | ## Credits
278 |
279 | We are grateful to the makers of the following open source projects:
280 |
281 | - [Android Pinyin IME](https://source.android.com/) (Apache 2.0)
282 | - [Chewing / 新酷音](http://chewing.im/) (LGPL)
283 | - [ibus-table](https://github.com/acevery/ibus-table) (LGPL)
284 | - [OpenCC / 開放中文轉換](https://github.com/BYVoid/OpenCC) (Apache 2.0)
285 | - [moedict / 萌典](https://www.moedict.tw) (CC0 1.0)
286 | - [Rime 翰林院 / Rime Academy](https://github.com/rime-aca) (GPLv3)
287 |
288 | Also to the inventors of the following input methods:
289 |
290 | - Cangjie / 倉頡輸入法 by 朱邦復
291 | - Array input method / 行列輸入法 by 廖明德
292 | - Wubi / 五筆字型 by 王永民
293 | - Scj / 快速倉頡 by 麥志洪
294 | - Middle Chinese Romanization / 中古漢語拼音 by 古韻
295 |
296 | ## Contributors
297 |
298 | This software is a result of collective effort. It was set up by the following
299 | people by contributing files, patches and pull-requests. See also the
300 | [contributors](https://github.com/rime/plum/graphs/contributors) page for a
301 | list of open-source collaborators.
302 |
303 | - [佛振](https://github.com/lotem)
304 | - [Kunki Chou](https://github.com/kunki)
305 | - [雪齋](https://github.com/LEOYoon-Tsaw)
306 | - [Patrick Tschang](https://github.com/Patricivs)
307 | - [Joseph J.C. Tang](https://github.com/jinntrance)
308 | - [lxk](http://101reset.com)
309 | - [Ye Zhou](https://github.com/zhouye)
310 | - Jiehong Ma
311 | - StarSasumi
312 | - 古韻
313 | - 寒寒豆
314 | - 四季的風
315 | - 上海閒話abc
316 | - 吳語越音
317 |
--------------------------------------------------------------------------------
/all-packages.bat:
--------------------------------------------------------------------------------
1 | set package_list=
2 | call preset-packages.bat
3 | call extra-packages.bat
4 |
--------------------------------------------------------------------------------
/all-packages.conf:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | package_list=()
4 |
5 | source "${root_dir:-.}"/preset-packages.conf
6 | source "${root_dir:-.}"/extra-packages.conf
7 |
--------------------------------------------------------------------------------
/extra-packages.bat:
--------------------------------------------------------------------------------
1 | set package_list=%package_list%^
2 | array^
3 | cantonese^
4 | combo-pinyin^
5 | double-pinyin^
6 | emoji^
7 | ipa^
8 | jyutping^
9 | middle-chinese^
10 | pinyin-simp^
11 | quick^
12 | scj^
13 | soutzoe^
14 | stenotype^
15 | wubi^
16 | wugniu^
17 |
--------------------------------------------------------------------------------
/extra-packages.conf:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | package_list+=(
4 | array
5 | cantonese
6 | combo-pinyin
7 | double-pinyin
8 | emoji
9 | ipa
10 | jyutping
11 | middle-chinese
12 | pinyin-simp
13 | quick
14 | scj
15 | soutzoe
16 | stenotype
17 | wubi
18 | wugniu
19 | )
20 |
--------------------------------------------------------------------------------
/preset-packages.bat:
--------------------------------------------------------------------------------
1 | set package_list=%package_list%^
2 | bopomofo^
3 | cangjie^
4 | essay^
5 | luna-pinyin^
6 | prelude^
7 | stroke^
8 | terra-pinyin^
9 |
--------------------------------------------------------------------------------
/preset-packages.conf:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | package_list+=(
4 | bopomofo
5 | cangjie
6 | essay
7 | luna-pinyin
8 | prelude
9 | stroke
10 | terra-pinyin
11 | )
12 |
--------------------------------------------------------------------------------
/rime-install:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if [[ -z "${plum_repo}" ]]; then
4 | plum_repo='rime/plum'
5 | fi
6 |
7 | if [[ -z "${plum_dir}" ]]; then
8 | # am I in a working copy already?
9 | plum_dir="$(dirname "$(readlink -f "$0")")"
10 | if ! [[ -f "${plum_dir}"/scripts/install-packages.sh ]]; then
11 | # make a copy of plum in a subdirectory
12 | plum_dir='plum'
13 | fi
14 | fi
15 |
16 | if ! [[ -e "${plum_dir}" ]]; then
17 | git clone --depth 1 "https://github.com/${plum_repo}.git" "${plum_dir}"
18 | fi
19 |
20 | if ! [[ "$0" -ef "${plum_dir}"/rime-install ]]; then
21 | # run the newer version of rime-install
22 | "${plum_dir}"/rime-install "$@"
23 | exit
24 | fi
25 |
26 | export root_dir="${plum_dir}"
27 | source "${root_dir}"/scripts/bootstrap.sh
28 | require 'styles'
29 |
30 | if [[ -z "${rime_dir}" ]]; then
31 | # Output to Rime user directory
32 | require 'frontend'
33 | guess_rime_user_dir # exports `rime_dir`
34 | fi
35 |
36 | if [[ "$1" == '--select' ]]; then
37 | shift
38 | interactive=1
39 | fi
40 |
41 | if [[ $# -eq 0 ]]; then
42 | targets=(':preset')
43 | else
44 | targets=("$@")
45 | fi
46 |
47 | if [[ -n "${interactive}" ]]; then
48 | require 'selector'
49 | select_packages "${targets[@]}"
50 | targets=("${selected_packages[@]}")
51 | fi
52 |
53 | for target in "${targets[@]}"; do
54 | if [[ "${target}" == 'plum' ]]; then
55 | echo $(print_result 'Updating plum at') "'${plum_dir}'"
56 | (cd "${plum_dir}"; git pull)
57 | continue
58 | fi
59 |
60 | "${root_dir}"/scripts/install-packages.sh "${target}" "${rime_dir:-.}"
61 | done
62 |
--------------------------------------------------------------------------------
/rime-install-bootstrap.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | setlocal
4 |
5 | set root_dir=%~dp0
6 | set PATH=%root_dir%;%PATH%
7 |
8 | set script_path=%root_dir%rime-install.bat
9 | set config_path=%root_dir%rime-install-config.bat
10 |
11 | rem download rime-install.bat if missing
12 | if exist "%script_path%" goto end_download
13 |
14 | where /q curl
15 | if %errorlevel% equ 0 (
16 | set downloader=curl -fsSL
17 | set save_to=-o
18 | goto downloader_found
19 | )
20 |
21 | where /q powershell
22 | if %errorlevel% equ 0 (
23 | set downloader=powershell Invoke-WebRequest
24 | set save_to=-OutFile
25 | goto downloader_found
26 | )
27 |
28 | echo Error: downloader not found.
29 | exit /b 1
30 | :downloader_found
31 |
32 | set script_url=https://raw.githubusercontent.com/rime/plum/master/rime-install.bat
33 | set config_url=https://github.com/rime/plum/raw/master/rime-install-config.bat
34 |
35 | echo Downloading rime-install.bat ...
36 | %downloader% "%script_url%" %save_to% "%script_path%"
37 | if errorlevel 1 (
38 | echo Error downloading rime-install.bat
39 | exit /b 1
40 | )
41 |
42 | if exist "%config_path%" goto end_download
43 |
44 | echo Downloading rime-install-config.bat template ...
45 | %downloader% "%config_url%" %save_to% "%config_path%"
46 | if errorlevel 1 (
47 | echo Error downloading rime-install-config.bat
48 | exit /b 1
49 | )
50 |
51 | :end_download
52 |
53 | set link_name=Rime package installer
54 |
55 | rem create shortcut
56 | powershell "$s=(New-Object -COM WScript.Shell).CreateShortcut('%root_dir%%link_name%.lnk');$s.TargetPath='\"%ComSpec%\"';$s.Arguments='/k \"%script_path%\"';$s.WorkingDirectory='%root_dir%';$s.Save()"
57 |
--------------------------------------------------------------------------------
/rime-install-config.bat:
--------------------------------------------------------------------------------
1 | rem Location of download cache
2 | rem set download_cache_dir=%TEMP%
3 |
4 | rem Do not update packages; only download missing files.
5 | rem CAUTION: may suffer from incomplete downloads.
6 | rem set no_update=1
7 |
8 | rem Location of Rime configuration manager and downloaded packages
9 | rem set plum_dir=%APPDATA%\plum
10 |
11 | rem Location of Rime user directory
12 | rem set rime_dir=%APPDATA%\Rime
13 |
14 | set key=HKEY_CURRENT_USER\SOFTWARE\Rime\Weasel
15 | set name=RimeUserDir
16 | for /f "tokens=2*" %%a in ('reg query "%key%" /v "%name%"') do set rime_dir=%%b
17 |
18 | rem Disable /plum/ bash script; use batch installer only.
19 | rem set use_plum=0
20 |
--------------------------------------------------------------------------------
/rime-install.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | setlocal enabledelayedexpansion
4 |
5 | title Rime package installer
6 |
7 | set root_dir=%~dp0
8 | set PATH=%root_dir%;%PATH%
9 |
10 | set config_file=%~dp0\rime-install-config.bat
11 | if exist "%config_file%" call "%config_file%"
12 |
13 | if not defined rime_dir set rime_dir=%APPDATA%\Rime
14 | if not defined download_cache_dir set download_cache_dir=%TEMP%
15 | if not exist "%download_cache_dir%" mkdir "%download_cache_dir%"
16 |
17 | echo.
18 | echo Rime package installer
19 | echo.
20 | echo Working directory: %CD%
21 | echo Package installer directory: %root_dir%
22 | echo Download cache directory: %download_cache_dir%
23 | echo Rime user directory: %rime_dir%
24 | echo.
25 |
26 | if defined ProgramFiles(x86) (set arch=64) else (set arch=32)
27 |
28 | call :find_7z
29 | call :find_git_bash
30 | call :find_downloader
31 |
32 | if not defined use_plum if "%has_git_bash%" == "1" set use_plum=1
33 |
34 | :process_arguments
35 | if "%1" == "" set batch_interactive=1
36 |
37 | if "%1" == "--select" if "%use_plum" == "1" (
38 | call :install_with_plum %*
39 | exit /b !errorlevel!
40 | )
41 |
42 | set /a installed_packages=0
43 |
44 | :next
45 | if "%batch_interactive%" == "1" (
46 | set package=
47 | echo. && (set /p package=Enter package name, URL, user/repo or downloaded ZIP to install: )
48 | ) else (
49 | set package=%1
50 | shift
51 | )
52 | if "%package%" == "" goto finish
53 |
54 | call :install_package
55 | if errorlevel 1 exit /b %errorlevel%
56 | goto next
57 |
58 | :install_package
59 | if "%package%" == "7z" (
60 | call :install_7z
61 | exit /b %errorlevel%
62 | ) else if "%package%" == "git" (
63 | call :install_git
64 | exit /b %errorlevel%
65 | ) else if "%package%" == "plum" (
66 | call :install_with_plum plum
67 | exit /b %errorlevel%
68 | ) else if "%package:.zip=%.zip" == "%package%" (
69 | if "https://github.com/%package:https://github.com/=%" == "%package%" (
70 | set user_repo_path=%package:https://github.com/=%
71 | set archive_name=%package:*/archive/=%
72 | for /f "tokens=1 usebackq delims=." %%g in ('!archive_name!') do set branch=%%g
73 | call set package_repo=%%user_repo_path:/archive/!archive_name!=%%
74 | call :download_package
75 | ) else (
76 | set package_file=%package%
77 | call :install_zip_package
78 | )
79 | goto :after_install_package
80 | )
81 |
82 | :prefer_plum_installer
83 | if "%use_plum%" == "1" (
84 | call :install_with_plum %package%
85 | goto after_install_package
86 | )
87 | :fallback_to_builtin_installer
88 | set branch=
89 | if "https://github.com/%package:https://github.com/=%" == "%package%" (
90 | set user_repo_path=%package:https://github.com/=%
91 | if not "%package:/tree/=%" == "%package%" (
92 | set branch=%package:*/tree/=%
93 | )
94 | if defined branch (
95 | call set package_repo=%%user_repo_path:/tree/!branch!=%%
96 | ) else (
97 | set package_repo=!user_repo_path!
98 | )
99 | call :download_package
100 | ) else if "%package:-packages.bat=%-packages.bat" == "%package%" (
101 | call "%package%"
102 | call :install_package_group
103 | ) else if ":%package::=%" == "%package%" (
104 | call "%package::=%-packages.bat"
105 | call :install_package_group
106 | ) else if not "%package:/=%" == "%package%" (
107 | for /f "tokens=1,2 usebackq delims=@" %%g in ('%package%') do (
108 | set package_repo=%%g
109 | set branch=%%h
110 | )
111 | call :download_package
112 | ) else (
113 | for /f "tokens=1,2 usebackq delims=@" %%g in ('%package%') do (
114 | set user_repo_path=%%g
115 | set branch=%%h
116 | )
117 | set package_repo=rime/rime-!user_repo_path:rime-=!
118 | call :download_package
119 | )
120 | :after_install_package
121 | if not errorlevel 1 set /a installed_packages+=1
122 | exit /b %errorlevel%
123 |
124 | :download_package
125 | if not defined downloader (
126 | set error_message=Downloader not found.
127 | goto error
128 | )
129 | call :install_7z /needed
130 | if errorlevel 1 exit /b %errorlevel%
131 | if not defined branch (
132 | for /f "tokens=2 usebackq delims=:, " %%g in (`
133 | %downloader% https://api.github.com/repos/%package_repo% ^| findstr default_branch
134 | `) do set branch=%%~g
135 | )
136 | set package_url=https://github.com/%package_repo%/archive/%branch%.zip
137 | echo.
138 | echo Downloading %package_url% ...
139 | echo.
140 | set package_file=%download_cache_dir%\%package_repo:*/=%-%branch%.zip
141 | if "%no_update%" == "1" if exist "%package_file%" goto skip_download_package
142 | %downloader% "%package_url%" %save_to% "%package_file%"
143 | if errorlevel 1 (
144 | set error_message=Error downloading %package_url%
145 | goto error
146 | )
147 | :skip_download_package
148 | call :install_zip_package
149 | exit /b %errorlevel%
150 |
151 | :install_zip_package
152 | call :install_7z /needed
153 | if errorlevel 1 exit /b %errorlevel%
154 | echo.
155 | echo Unpacking %package_file% ...
156 | echo.
157 | for %%f in (%package_file%) do set package_dir=%%~nf
158 | set unpack_package_dir=%TEMP%\%package_dir%
159 | rem clean up obsolete files in target directory
160 | if exist "%unpack_package_dir%" rmdir /s /q "%unpack_package_dir%"
161 | rem unzip package
162 | 7z x "%package_file%" -o"%TEMP%" -y
163 | if errorlevel 1 (
164 | set error_message=Error unpacking package %package_file%
165 | goto error
166 | )
167 | if not exist "%rime_dir%" (
168 | mkdir "%rime_dir%"
169 | if errorlevel 1 (
170 | set error_message=Error creating rime user directory: %rime_dir%
171 | goto error
172 | )
173 | )
174 | rem install files from the unzipped package
175 | pushd "%unpack_package_dir%"
176 | for %%f in (
177 | *.yaml
178 | *.txt
179 | opencc\*.json
180 | opencc\*.ocd
181 | opencc\*.txt
182 | ) do (
183 | echo.
184 | echo Installing %%f ...
185 | echo.
186 | set target_file=%rime_dir%\%%f
187 | for %%t in (!target_file!) do set target_dir=%%~dpt
188 | if not exist "!target_dir!" mkdir "!target_dir!"
189 | copy /y "%%f" "!target_file!"
190 | if errorlevel 1 (
191 | popd
192 | set error_message=Error installing files from package %package%
193 | goto error
194 | )
195 | )
196 | popd
197 | exit /b
198 |
199 | :install_package_group
200 | if not defined package_list (
201 | set error_message=package_list is undefined in %package%
202 | goto error
203 | )
204 | for %%p in (%package_list%) do (
205 | set package=%%p
206 | call :install_package
207 | if errorlevel 1 exit /b !errorlevel!
208 | )
209 | exit /b
210 |
211 | :install_with_plum
212 | call :install_git /needed
213 | if errorlevel 1 exit /b %errorlevel%
214 |
215 | set WSLENV=plum_dir:rime_dir
216 |
217 | if defined plum_dir if exist "%plum_dir%"/rime-install (
218 | bash "%plum_dir%"/rime-install %*
219 | exit /b !errorlevel!
220 | )
221 | if exist plum/rime-install (
222 | bash plum/rime-install %*
223 | ) else if exist rime-install (
224 | bash rime-install %*
225 | ) else (
226 | echo Downloading rime-install ...
227 | set script_url=https://raw.githubusercontent.com/rime/plum/master/rime-install
228 | curl -fsSL "!script_url!" -o "%download_cache_dir%"/rime-install
229 | if errorlevel 1 (
230 | set error_message=Error downloading rime-install
231 | goto error
232 | )
233 | bash "%download_cache_dir%"/rime-install %*
234 | )
235 | exit /b %errorlevel%
236 |
237 | :install_7z
238 | where /q 7z
239 | if not errorlevel 1 (
240 | if "%1" == "/needed" exit /b
241 | echo.
242 | echo Found 7z
243 | echo.
244 | exit /b
245 | )
246 |
247 | rem check for updates at https://www.7-zip.org/download.html
248 | if not defined _7z_version set _7z_version=18.01
249 |
250 | if "%arch%" == "64" (set _7z_arch=-x%arch%) else (set _7z_arch=)
251 | set _7z_installer=7z%_7z_version:.=%%_7z_arch%.exe
252 |
253 | rem find local 7z installer
254 | where /q %_7z_installer%
255 | if not errorlevel 1 (
256 | echo.
257 | echo Found installer: %_7z_installer%
258 | echo.
259 | set _7z_installer_path=%_7z_installer%
260 | goto run_7z_installer
261 | )
262 |
263 | set _7z_installer_path=%download_cache_dir%\%_7z_installer%
264 | if "%no_update%" == "1" if exist "%_7z_installer_path%" goto run_7z_installer
265 |
266 | :download_7z_installer
267 | set _7z_download_url=https://www.7-zip.org/a/%_7z_installer%
268 | if not defined downloader (
269 | echo.
270 | echo TODO: please download and install 7z: %_7z_download_url%
271 | echo.
272 | set error_message=Downloader not found.
273 | goto error
274 | )
275 | echo.
276 | echo Downloading installer: %_7z_installer%
277 | echo.
278 | %downloader% "%_7z_download_url%" %save_to% "%_7z_installer_path%"
279 | if errorlevel 1 (
280 | set error_message=Error downloading %_7z_installer%
281 | goto error
282 | )
283 | rem TODO: verify installer
284 | echo.
285 | echo Download complete: %_7z_installer%
286 | echo.
287 |
288 | :run_7z_installer
289 | echo.
290 | echo Installing 7z ...
291 | echo.
292 | "%_7z_installer_path%" /S
293 |
294 | exit /b
295 |
296 | :install_git
297 | where /q git
298 | if not errorlevel 1 (
299 | if "%1" == "/needed" exit /b
300 | echo.
301 | echo Found git
302 | echo.
303 | exit /b
304 | )
305 |
306 | rem check for updates at https://github.com/git-for-windows/git/releases/latest
307 | if not defined git_version set git_version=2.17.0
308 | if not defined git_release set git_release=.1
309 |
310 | set git_installer=Git-%git_version%%git_release:.1=%-%arch%-bit.exe
311 | rem find local Git installer
312 | where /q %git_installer%
313 | if not errorlevel 1 (
314 | echo.
315 | echo Found installer: %git_installer%
316 | echo.
317 | set git_installer_path=%git_installer%
318 | goto run_git_installer
319 | )
320 |
321 | set git_installer_path=%download_cache_dir%\%git_installer%
322 | if "%no_update%" == "1" if exist "%git_installer_path%" goto run_git_installer
323 |
324 | :download_git_installer
325 | set git_download_url_prefix=https://github.com/git-for-windows/git/releases/download/
326 | set git_download_url=%git_download_url_prefix%v%git_version%.windows%git_release%/%git_installer%
327 |
328 | if not defined downloader (
329 | echo.
330 | echo TODO: please download and install git: %git_download_url%
331 | echo.
332 | set error_message=Downloader not found.
333 | goto error
334 | )
335 | echo.
336 | echo Downloading installer: %git_installer%
337 | echo.
338 | %downloader% "%git_download_url%" %save_to% "%git_installer_path%"
339 | if errorlevel 1 (
340 | set error_message=Error downloading %git_installer%
341 | goto error
342 | )
343 | rem TODO: verify installer
344 | echo.
345 | echo Download complete: %git_installer%
346 | echo.
347 |
348 | :run_git_installer
349 | echo.
350 | echo Installing git ...
351 | echo.
352 | "%git_installer_path%" /SILENT
353 |
354 | exit /b
355 |
356 | :find_7z
357 | set search_path=^
358 | %ProgramFiles%\7-Zip;
359 |
360 | if defined ProgramW6432 set search_path=%search_path%^
361 | %ProgramW6432%\7-Zip;
362 |
363 | if defined ProgramFiles(x86) set search_path=%search_path%^
364 | %ProgramFiles(x86)%\7-Zip;
365 |
366 | set PATH=%search_path%%PATH%
367 |
368 | where /q 7z
369 | if %errorlevel% equ 0 set has_7z=1
370 | exit /b
371 |
372 | :find_git_bash
373 | set search_path=^
374 | %ProgramFiles%\Git\cmd;^
375 | %ProgramFiles%\Git\mingw%arch%\bin;^
376 | %ProgramFiles%\Git\usr\bin;
377 |
378 | rem find 64-bit Git in 32-bit cmd.exe
379 | if defined ProgramW6432 set search_path=%search_path%^
380 | %ProgramW6432%\Git\cmd;^
381 | %ProgramW6432%\Git\mingw%arch%\bin;^
382 | %ProgramW6432%\Git\usr\bin;
383 |
384 | rem find user installed 32-bit Git on 64-bit OS
385 | if defined ProgramFiles(x86) set search_path=%search_path%^
386 | %ProgramFiles(x86)%\Git\cmd;^
387 | %ProgramFiles(x86)%\Git\mingw32\bin;^
388 | %ProgramFiles(x86)%\Git\usr\bin;
389 |
390 | set PATH=%search_path%%PATH%
391 |
392 | where /q git
393 | if %errorlevel% equ 0 set has_git=1
394 |
395 | where /q bash
396 | if %errorlevel% equ 0 set has_bash=1
397 |
398 | if "%has_git%" == "1" if "%has_bash%" == "1" set has_git_bash=1
399 | exit /b
400 |
401 | :find_downloader
402 | where /q curl
403 | if %errorlevel% equ 0 (
404 | set downloader=curl -fsSL
405 | set save_to=-o
406 | goto downloader_found
407 | )
408 |
409 | where /q powershell
410 | if %errorlevel% equ 0 (
411 | set downloader=powershell Invoke-WebRequest
412 | set save_to=-OutFile
413 | goto downloader_found
414 | )
415 | :downloader_found
416 | exit /b
417 |
418 | :error
419 | echo.
420 | echo Installation failed: %error_message%
421 | echo.
422 | exit /b 1
423 |
424 | :finish
425 | echo.
426 | if %installed_packages% equ 0 (
427 | echo No package installed.
428 | ) else (
429 | echo Installed %installed_packages% packages.
430 | )
431 | echo.
432 |
433 | :exit
434 |
--------------------------------------------------------------------------------
/scripts/bootstrap.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # bootstraps the script module system
4 | #
5 | # usage:
6 | # - source this file in the main script
7 | # - require 'module-name'
8 | # in modules:
9 | # - require module dependencies
10 | # - define module
11 | # - provide 'module-name'
12 |
13 | module_root_dir="$(dirname "${BASH_SOURCE[0]}")"
14 |
15 | provide() {
16 | local module_name="$1"
17 | loaded_modules+=("${module_name}")
18 | }
19 |
20 | require() {
21 | local module_name="$1"
22 | if grep -qF " ${module_name} " <<<" ${loaded_modules[*]} "; then return; fi
23 | source "${module_root_dir}/${module_name}.sh"
24 | if grep -qF " ${module_name} " <<<" ${loaded_modules[*]} "; then return; fi
25 | echo >&2 "ERROR: failed to load module '${module_name}'"
26 | }
27 |
28 | provide 'bootstrap'
29 |
--------------------------------------------------------------------------------
/scripts/fetch-package.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # Fetch a Rime data package from GitHub
4 | #
5 |
6 | package_name="$1"
7 | shift
8 |
9 | if [[ -z "${package_name}" ]]; then
10 | echo "Usage: $(basename "$0") [] [-b ]"
11 | exit 1
12 | fi
13 |
14 | resolve_package_name() {
15 | local name="$1"
16 | if [[ ${name} =~ [^/]*/[^/]* ]]; then
17 | echo ${name}
18 | elif [[ ${name} =~ rime-[^/]* ]]; then
19 | echo rime/${name}
20 | else
21 | echo rime/rime-${name}
22 | fi
23 | }
24 |
25 | package_url="https://github.com/$(resolve_package_name "${package_name}").git"
26 |
27 | git_version_greater_or_equal() {
28 | local target_major="$1"
29 | local target_minor="$2"
30 | local git_version_pattern='^git version ([0-9]*)\.([0-9]*).*$'
31 | if [[ "$(git --version | grep '^git version')" =~ $git_version_pattern ]]; then
32 | local major="${BASH_REMATCH[1]}"
33 | local minor="${BASH_REMATCH[2]}"
34 | [[ "${major}" -gt "${target_major}" ]] || (
35 | [[ "${major}" -eq "${target_major}" ]] && [[ "${minor}" -ge "${target_minor}" ]]
36 | )
37 | else
38 | return 1
39 | fi
40 | }
41 |
42 | clone_options=(
43 | --depth 1
44 | --recurse-submodules
45 | )
46 |
47 | if git_version_greater_or_equal 2 9; then
48 | clone_options+=(
49 | --shallow-submodules
50 | )
51 | fi
52 |
53 | git clone ${clone_options[@]} "${package_url}" "$@"
54 |
--------------------------------------------------------------------------------
/scripts/frontend.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | require 'styles'
4 |
5 | guess_rime_user_dir() {
6 | if [[ -n "${rime_dir}" ]]; then
7 | return
8 | fi
9 | if [[ -z "${rime_frontend}" ]]; then
10 | # guess frontend by OS
11 | case "$OSTYPE" in
12 | linux*)
13 | export rime_frontend='rime/ibus-rime'
14 | ;;
15 | darwin*)
16 | export rime_frontend='rime/squirrel'
17 | ;;
18 | cygwin* | msys* | win*)
19 | # Weasel
20 | export rime_frontend='rime/weasel'
21 | ;;
22 | *)
23 | echo $(warning 'WARNING:') 'Unknown OSTYPE:' $(print_option "$OSTYPE")
24 | ;;
25 | esac
26 | fi
27 | # install to default rime user directory
28 | case "${rime_frontend}" in
29 | fcitx/fcitx-rime | fcitx-rime)
30 | export rime_dir="$HOME/.config/fcitx/rime"
31 | ;;
32 | fcitx5/fcitx5-rime | fcitx5-rime)
33 | export rime_dir="$HOME/.local/share/fcitx5/rime"
34 | ;;
35 | rime/ibus-rime | ibus-rime)
36 | export rime_dir="$HOME/.config/ibus/rime"
37 | ;;
38 | rime/squirrel | squirrel)
39 | export rime_dir="$HOME/Library/Rime"
40 | ;;
41 | rime/weasel | weasel)
42 | export rime_dir="$APPDATA\\Rime"
43 | ;;
44 | *)
45 | echo $(warning 'WARNING:') 'Unknown Rime frontend:' $(print_option "${rime_frontend:-(unknown)}")
46 | return
47 | ;;
48 | esac
49 | echo 'Installing for Rime frontend:' $(print_option "${rime_frontend:-(unknown)}")
50 | }
51 |
52 | provide 'frontend'
53 |
--------------------------------------------------------------------------------
/scripts/install-packages.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | script_dir="$(dirname "$0")"
4 | target="$1"
5 | output_dir="$2"
6 |
7 | option_no_update="${no_update:+1}"
8 |
9 | source "${script_dir}"/bootstrap.sh
10 | require 'styles'
11 | require 'resolver'
12 |
13 | if [[ -z "$target" ]] || [[ -z "$output_dir" ]]; then
14 | echo "Usage: $(basename "$0") :| "
15 | exit 1
16 | fi
17 |
18 | set -e
19 |
20 | [[ -d "${output_dir}" ]] || mkdir -p "${output_dir}"
21 |
22 | files_updated=0
23 |
24 | install_package() {
25 | local user_name="$(resolve_user_name "$1")"
26 | local package_name="$(resolve_package_name "$1")"
27 | local package_dir="${root_dir:-.}/package/${user_name}/${package_name}"
28 |
29 | local package="$(resolve_package "$1")"
30 | local branch="$(resolve_branch "$1")"
31 | local branch_label="${branch:+@${branch}}"
32 |
33 | local recipe="$(resolve_recipe "$1")"
34 | local recipe_options=($(resolve_recipe_options "$1"))
35 |
36 | fetch_or_update_package
37 |
38 | if [[ -n "${recipe}" ]]; then
39 | require 'recipe'
40 | install_recipe "${package_dir}/${recipe}.recipe.yaml"
41 | elif [[ -f "${package_dir}/recipe.yaml" ]]; then
42 | require 'recipe'
43 | install_recipe "${package_dir}/recipe.yaml"
44 | else
45 | install_files_from_package "${package_dir}"
46 | fi
47 | }
48 |
49 | fetch_or_update_package() {
50 | if ! [[ -d "${package_dir}" ]]; then
51 | echo $(info 'Downloading package:') $(highlight "${package}") $(print_option "${branch_label}")
52 | local fetch_options=()
53 | if [[ -n "${branch}" ]]; then
54 | fetch_options+=(--branch "${branch}")
55 | fi
56 | "${script_dir}"/fetch-package.sh "${package}" "${package_dir}" "${fetch_options[@]}"
57 | else
58 | if [[ -z "${option_no_update}" ]]; then
59 | echo $(info 'Updating package:') $(highlight "${package}")
60 | else
61 | echo $(info 'Found package:') $(highlight "${package}")
62 | fi
63 | "${script_dir}"/update-package.sh "${package_dir}" "${branch}"
64 | fi
65 | }
66 |
67 | install_files_from_package() {
68 | local package_dir="$1"
69 | local IFS=$'\r\n'
70 | local data_files=(
71 | $(
72 | cd "${package_dir}"
73 | ls *.yaml 2> /dev/null \
74 | | grep -v -e '\.custom\.yaml$' -e '\.recipe\.yaml$' -e '^recipe\.yaml$'
75 | ls *.txt 2> /dev/null
76 | ls *.gram 2> /dev/null
77 | ls opencc/*.* 2> /dev/null \
78 | | grep -e '\.json$' -e '\.ocd$' -e '\.txt$'
79 | )
80 | )
81 | install_files "${data_files[@]}"
82 | }
83 |
84 | install_files() {
85 | if [[ "$#" -eq 0 ]]; then
86 | return
87 | fi
88 | local source_path
89 | local target_path
90 | for file in "$@"; do
91 | source_path="${package_dir}/${file}"
92 | target_path="${output_dir}/${file}"
93 | if ! [ -e "${target_path}" ]; then
94 | create_containing_directory "${target_path}"
95 | echo $(info 'Installing:') $(print_item "${file}")
96 | elif ! diff -q "${source_path}" "${target_path}" &> /dev/null; then
97 | echo $(info 'Updating:') $(print_item "${file}")
98 | else
99 | continue
100 | fi
101 | cp "${source_path}" "${target_path}"
102 | ((++files_updated))
103 | done
104 | }
105 |
106 | create_containing_directory() {
107 | local target_dir="$(dirname "$1")"
108 | if ! [ -d "${target_dir}" ]; then
109 | echo $(info 'Creating directory:') $(print_item "${target_dir}")
110 | mkdir -p "${target_dir}"
111 | fi
112 | }
113 |
114 | load_package_list_from_target "${target}"
115 |
116 | for package in "${package_list[@]}"; do
117 | install_package "${package}"
118 | done
119 |
120 | if [[ "${files_updated}" -eq 0 ]]; then
121 | echo $(print_result 'No files updated.')
122 | else
123 | echo $(print_result "Updated ~ ${files_updated} files " \
124 | "from ${#package_list[@]} packages in") "'${output_dir}'"
125 | fi
126 |
--------------------------------------------------------------------------------
/scripts/minimal-build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # encoding: utf-8
3 |
4 | script_dir="$(dirname "$0")"
5 | output_dir="$1"
6 |
7 | for package in essay luna-pinyin prelude; do
8 | bash "${script_dir}"/install-packages.sh "${package}" "${output_dir}"
9 | done
10 |
11 | pushd "${output_dir}" > /dev/null
12 |
13 | awk '($2 >= 500) {print}' essay.txt > essay.txt.min
14 | mv essay.txt.min essay.txt
15 |
16 | sed -n '{
17 | s/^version: \(["]*\)\([0-9.]*\)\(["]*\)$/version: \1\2.minimal\3/
18 | /^#以下爲詞組$/q;p
19 | }' luna_pinyin.dict.yaml > luna_pinyin.dict.yaml.min
20 | mv luna_pinyin.dict.yaml.min luna_pinyin.dict.yaml
21 |
22 | for schema in *.schema.yaml; do
23 | sed '{
24 | s/version: \(["]*\)\([0-9.]*\)\(["]*\)$/version: \1\2.minimal\3/
25 | s/\(- stroke\)$/#\1/
26 | s/\(- reverse_lookup_translator\)$/#\1/
27 | }' ${schema} > ${schema}.min
28 | mv ${schema}.min ${schema}
29 | done
30 |
31 | ls *.schema.yaml | sed 's/^\(.*\)\.schema\.yaml/ - schema: \1/' > schema_list.yaml
32 | grep -Ff schema_list.yaml default.yaml > schema_list.yaml.min
33 | mv schema_list.yaml.min schema_list.yaml
34 | sed '{
35 | s/^config_version: \(["]*\)\([0-9.]*\)\(["]*\)$/config_version: \1\2.minimal\3/
36 | /- schema:/d
37 | /^schema_list:$/r schema_list.yaml
38 | }' default.yaml > default.yaml.min
39 | rm schema_list.yaml
40 | mv default.yaml.min default.yaml
41 |
42 | popd > /dev/null
43 |
--------------------------------------------------------------------------------
/scripts/recipe.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | require 'styles'
4 |
5 | install_recipe() {
6 | local recipe_file="$1"
7 | if ! [[ -f "${recipe_file}" ]]; then
8 | echo $(error 'Recipe not found:') "${recipe_file}"
9 | exit 1
10 | fi
11 |
12 | local rx="${package}${recipe:+:${recipe}}"
13 | echo $(info 'Installing recipe:') $(highlight "${rx}")
14 | for option in "${recipe_options[@]}"; do
15 | echo $(info '- option:') $(print_option "${option}")
16 | done
17 |
18 | check_recipe_info
19 |
20 | apply_download_files
21 |
22 | apply_install_files
23 |
24 | apply_patch_files
25 | }
26 |
27 | print_section() {
28 | local section="$1"
29 | sed -n '/^'"${section}"':/,/^[^[:space:]#]/ {
30 | /^[^[:space:]#]/ !p
31 | }'
32 | }
33 |
34 | check_recipe_info() {
35 | local recipe_decl=$(
36 | cat "${recipe_file}" |
37 | print_section 'recipe' |
38 | grep '^[ ]*Rx: ' |
39 | sed 's/^[ ]*Rx:[ "'"'"']*\(.*\)[ "'"'"']*$/\1/'
40 | )
41 | [[ -z "${recipe}" ]] || [[ "${recipe_decl}" == "${recipe}" ]] || (
42 | echo $(error 'Invalid recipe:') "'${recipe_decl}' does not match file name '${recipe_file}'"
43 | exit 1
44 | )
45 | }
46 |
47 | get_filename() {
48 | local url="$1"
49 | # if a filename is specified, use it
50 | if [[ "$url" = *::* ]]; then
51 | echo "${url%%::*}"
52 | else
53 | echo "${url##*/}"
54 | fi
55 | }
56 |
57 | download_file() {
58 | local url="$1"
59 | local filename="$(get_filename $url)"
60 | local check_update=""
61 | local msg='Downloading file:'
62 |
63 | if [[ -e "${package_dir}/${filename}" ]]; then
64 | check_update="-z $filename"
65 | msg='Checking for update of external file:'
66 | fi
67 |
68 | (
69 | cd "${package_dir}"
70 | echo $(info "$msg") $(highlight "$filename")
71 | curl -fRL -o "$filename" $check_update "${url#*::}"
72 | )
73 | }
74 |
75 | apply_download_files() {
76 | if ! grep -q '^download_files:' "${recipe_file}"; then
77 | return
78 | fi
79 | local file_patterns=(
80 | $(cat "${recipe_file}" |
81 | print_section 'download_files' |
82 | sed '/^[ ]*#/ d; s/^[ ]*-[ ]//'
83 | )
84 | )
85 | if (( ${#file_patterns[@]} == 0 )); then
86 | return
87 | fi
88 | for _item in ${file_patterns[@]}; do
89 | download_file $_item || (
90 | echo $(error 'Error:') "failed to download files in recipe ${rx}"
91 | exit 1
92 | )
93 | done
94 | }
95 |
96 | apply_install_files() {
97 | if ! grep -q '^install_files:' "${recipe_file}"; then
98 | return
99 | fi
100 | local file_patterns=(
101 | $(cat "${recipe_file}" |
102 | print_section 'install_files' |
103 | sed '/^[ ]*#/ d; s/^[ ]*-[ ]//'
104 | )
105 | )
106 | if (( ${#file_patterns[@]} == 0 )); then
107 | return
108 | fi
109 | install_files $(
110 | cd "${package_dir}"
111 | ls ${file_patterns[@]} ||
112 | echo $(error 'Error: some files to install are not found.') >&2
113 | ) || (
114 | echo $(error 'Error:') "failed to install files in recipe ${rx}"
115 | exit 1
116 | )
117 | }
118 |
119 | apply_patch_files() {
120 | if ! grep -q '^patch_files:' "${recipe_file}"; then
121 | return
122 | fi
123 | local script_header="\
124 | #!/usr/bin/env bash
125 | source '${script_dir}/bootstrap.sh'
126 | require 'recipe'
127 | output_dir='${output_dir}'
128 | package='${package}'
129 | recipe='${recipe}'
130 | recipe_options=(
131 | ${recipe_options[*]}
132 | )
133 | eval \${recipe_options[@]}
134 | "
135 | cat "${recipe_file}" |
136 | print_section 'patch_files' |
137 | sed '{
138 | 1 i\
139 | '"$(escape_sed_text <<<"${script_header}")"'
140 | # patch files
141 | s/^[ ][ ]//
142 | s/^\([^[:space:]#]*\):\s*$/patch_file \1 <> "${target_file}"
165 | fi
166 | local option_list="${recipe_options[*]}"
167 | local rx="${package}:${recipe}:${option_list// /,}"
168 | if grep -Fq "# Rx: ${rx}" "${target_file}"; then
169 | echo $(info 'Updating patch.')
170 | # first remove the existing patch
171 | sed '/^# Rx: '"${rx//\//\\/}"' {$/,/^# }$/ d' \
172 | "${target_file}" > "${target_file}.new" &&
173 | mv "${target_file}.new" "${target_file}"
174 | fi
175 | # read patch contents from standard input
176 | local patch_contents="$(escape_sed_text)"
177 | sed -E '
178 | /^__patch:$/,/^[^[:space:]#]/ {
179 | $ {
180 | /^__patch:|^[[:space:]#]/ {
181 | a\
182 | # Rx: '"${rx}"' {\
183 | '"${patch_contents}"'
184 | # }
185 | q
186 | }
187 | i\
188 | # Rx: '"${rx}"' {\
189 | '"${patch_contents}"'
190 | # }
191 | }
192 | }
193 | ' "${target_file}" > "${target_file}.new" &&
194 | mv "${target_file}.new" "${target_file}" || (
195 | echo $(error 'Error patching:') "${file_name}"
196 | exit 1
197 | )
198 | }
199 |
200 | provide 'recipe'
201 |
--------------------------------------------------------------------------------
/scripts/resolver.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | require 'styles'
4 |
5 | # a recipe order takes the form
6 | # /@::key=value,...
7 | #
8 | # the "/" and/or "@", ":..." parts can be omitted
9 |
10 | resolve_user_name() {
11 | local package="${1%%[@:]*}"
12 | local user_name='rime'
13 | if [[ "${package}" =~ / ]]; then
14 | user_name="${package%/*}"
15 | fi
16 | echo "${user_name}"
17 | }
18 |
19 | resolve_package_name() {
20 | local package="${1%%[@:]*}"
21 | local repo_name="${package##*/}"
22 | local package_name="${repo_name#rime-}"
23 | echo "${package_name}"
24 | }
25 |
26 | resolve_package() {
27 | local package="${1%%[@:]*}"
28 | echo "${package}"
29 | }
30 |
31 | # returns empty string if not specified
32 | resolve_branch() {
33 | local package="${1%%:*}"
34 | if [[ "${package}" =~ @ ]]; then
35 | echo "${package##*@}"
36 | fi
37 | }
38 |
39 | # returns empty string if not specified
40 | resolve_recipe() {
41 | local rx="$1"
42 | if [[ "${rx}" =~ : ]]; then
43 | rx="${rx#*:}"
44 | echo "${rx%%:*}"
45 | fi
46 | }
47 |
48 | resolve_recipe_options() {
49 | local rx="$1"
50 | if [[ "${rx}" =~ : ]]; then
51 | rx="${rx#*:}"
52 | if [[ "${rx}" =~ : ]]; then
53 | echo "${rx#*:}" | sed 's/[:,]/ /g'
54 | fi
55 | fi
56 | }
57 |
58 | expand_configuration_url() {
59 | if [[ "$1" =~ ^https:// ]]; then
60 | echo "$1"
61 | elif [[ "$1" =~ ^([^/@:]*)/([^/@:]*)(@[^/@:]*)?/([^@:]*-packages.conf)$ ]]; then
62 | local user="${BASH_REMATCH[1]}"
63 | local repo="${BASH_REMATCH[2]}"
64 | local branch="${BASH_REMATCH[3]#@}"
65 | local filepath="${BASH_REMATCH[4]}"
66 | echo "https://github.com/${user}/${repo}/raw/${branch:-master}/${filepath}"
67 | fi
68 | }
69 |
70 | load_package_list_from_target() {
71 | local target="$1"
72 | case "${target}" in
73 | */*/*-packages.conf |\
74 | https://github.com/*/raw/*-packages.conf |\
75 | https://raw.githubusercontent.com/*-packages.conf)
76 | local configuration_url="$(expand_configuration_url "${target}")"
77 | if [[ -z "${configuration_url}" ]]; then
78 | echo $(error 'ERROR:') "unable to recognize configuration: ${target}" >&2
79 | exit 1
80 | fi
81 | echo $(info 'Fetching') "${configuration_url}"
82 | curl -fLO "${configuration_url}"
83 | source "$(basename "${configuration_url}")"
84 | ;;
85 | *.conf)
86 | source "${target}"
87 | ;;
88 | :*)
89 | source "${root_dir:-.}/${target#:}"-packages.conf
90 | ;;
91 | *)
92 | package_list=("${target}")
93 | ;;
94 | esac
95 | }
96 |
97 | provide 'resolver'
98 |
--------------------------------------------------------------------------------
/scripts/selector.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | require 'styles'
4 | require 'resolver'
5 |
6 | select_packages() {
7 | local all_packages=()
8 | local target
9 | local package
10 | for target in "$@"; do
11 | load_package_list_from_target "${target}"
12 | for package in "${package_list[@]}"; do
13 | if ! (echo " ${all_packages[*]} " | grep -qF " ${package} "); then
14 | all_packages+=("${package}")
15 | fi
16 | done
17 | done
18 |
19 | selected_packages=()
20 | local PS3="$(prompt '#') Enter number, package name or '.' when finished $(prompt '#') "
21 | echo $(highlight 'Select packages to install:')
22 | select selected in "${all_packages[@]}"; do
23 | if [[ -n "${selected}" ]]; then
24 | selected_packages+=("${selected}")
25 | else
26 | case "$REPLY" in
27 | end | ok | 0 | .)
28 | break
29 | ;;
30 | cancel | exit | quit)
31 | echo $(warning 'Installation canceled.')
32 | exit
33 | ;;
34 | reset | clear)
35 | selected_packages=()
36 | echo $(print_result 'Reset selected packages.')
37 | continue
38 | ;;
39 | [:A-Za-z]*)
40 | selected_packages+=("$REPLY")
41 | ;;
42 | *)
43 | echo $(error 'ERROR:') 'invalid number or package name:' $(print_option "$REPLY")
44 | continue
45 | ;;
46 | esac
47 | fi
48 | echo "You will rime with $(print_item ${selected_packages[@]}) (+$(print_option $REPLY))"
49 | done
50 |
51 | if [[ ${#selected_packages} -eq 0 ]]; then
52 | echo $(warning 'You did not select any packages.')
53 | echo
54 | echo -n "$(highlight 'Do you want to install default packages?') ($(print_item $@))"
55 | read -p " $(prompt '[Y/n]') " answer
56 | case "${answer}" in
57 | '' | y*)
58 | selected_packages=("$@")
59 | ;;
60 | *)
61 | echo $(warning 'Installation canceled.')
62 | exit
63 | ;;
64 | esac
65 | fi
66 | }
67 |
68 | provide 'selector'
69 |
--------------------------------------------------------------------------------
/scripts/split-packages.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | old_branch=master
4 | new_branch=split-packages
5 |
6 | package_files() {
7 | local package="$1"
8 | grep "^${package}=" < []"
14 | exit 1
15 | fi
16 |
17 | git_current_branch() {
18 | if ! command git rev-parse 2> /dev/null
19 | then
20 | # not a git repository
21 | return 2
22 | fi
23 | local ref="$(command git symbolic-ref HEAD 2> /dev/null)"
24 | if [[ -n "$ref" ]]
25 | then
26 | echo "${ref#refs/heads/}"
27 | return 0
28 | else
29 | return 1
30 | fi
31 | }
32 |
33 | git_default_branch() {
34 | if ! command git rev-parse 2> /dev/null
35 | then
36 | return 2
37 | fi
38 | local ref="$(command git symbolic-ref refs/remotes/origin/HEAD 2> /dev/null)"
39 | if [[ -n "$ref" ]]
40 | then
41 | echo "${ref#refs/remotes/origin/}"
42 | return 0
43 | else
44 | return 1
45 | fi
46 | }
47 |
48 | fetch_all_branches() {
49 | local fetch_all_pattern='\+refs/heads/\*:'
50 | if ! [[ "$(git config --get remote.origin.fetch)" =~ $fetch_all_pattern ]]; then
51 | if [[ -n "${option_no_update}" ]]; then
52 | echo $(warning 'WARNING:') 'forced update for switching branch to' $(print_option "${target_branch}")
53 | fi
54 | git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'
55 | elif [[ -n "${option_no_update}" ]]; then
56 | return
57 | fi
58 | git fetch origin --depth 1
59 | }
60 |
61 | switch_branch() {
62 | local target_branch="$1"
63 | if [[ -z "${branch}" ]]; then
64 | echo $(warning 'WARNING:') "'${package_dir}' was on" \
65 | $(print_option "${current_branch:-(detached HEAD)}") 'instead of' $(print_option "${target_branch}")
66 | fi
67 | fetch_all_branches
68 | git checkout "${target_branch}" || exit 1
69 | }
70 |
71 | pushd "${package_dir}" &> /dev/null
72 |
73 | current_branch="$(git_current_branch)"
74 | if [[ $? -gt 1 ]]; then
75 | echo $(warning 'WARNING:') "not a git repository, skipped updating '${package_dir}'"
76 | exit
77 | fi
78 | if [[ -z "${branch}" ]]; then
79 | target_branch="$(git_default_branch)"
80 | else
81 | target_branch="${branch}"
82 | fi
83 | if [[ "${current_branch}" != "${target_branch}" ]]; then
84 | switch_branch "${target_branch}"
85 | elif [[ -z "${option_no_update}" ]]; then
86 | git fetch --recurse-submodules && (
87 | git merge --ff-only "origin/${target_branch}" || (
88 | echo $(warning 'WARNING:') 'fast-forward failed;' \
89 | 'doing a hard reset to' $(print_option "origin/${target_branch}")
90 | git reset --hard "origin/${target_branch}"
91 | )
92 | ) || exit 1
93 | fi
94 |
95 | popd &> /dev/null
96 |
--------------------------------------------------------------------------------