Skip to content

Commit c227976

Browse files
authored
Merge pull request #354 from PyThaiNLP/verb-commands
Verb-like commands for "thainlp" command-line program
2 parents b329aa8 + c058102 commit c227976

12 files changed

Lines changed: 281 additions & 231 deletions

File tree

docs/notes/command_line.rst

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,75 @@
11
Command Line
22
============
33

4-
You can use PyThaiNLP from Command Line.
4+
You can use some thainlp functions directly from command line.
55

6-
Run Command Line and type the commands:::
6+
**Tokenization**::
77

8-
pythainlp
8+
thainlp tokenize <word|syllable|subword|sent> [-w] [-nw] [-a newmm|attacut|longest] [-s SEPARATOR] TEXT
99

10-
**Word tokenization**::
10+
*Example*::
1111

12-
pythainlp tokenization word --text TEXT
12+
$ thainlp tokenize word สภาพการจ้างและสภาพการทำงาน
13+
สภาพการจ้าง|และ|สภาพ|การทำงาน|
1314

14-
*Example*::
15+
$ thainlp tokenize syllable สภาพการจ้างและสภาพการทำงาน
16+
สภาพ~การ~จ้าง~และ~สภาพ~การ~ทำ~งาน~
1517

16-
$ pythainlp tokenization word --text "ผมร<0e31>กประเทศไทย? สามารถ" --engine newmm
17-
ผม|รัก|ประเทศไทย|?| |สามารถ
18+
$ thainlp tokenize subword สภาพการจ้างและสภาพการทำงาน
19+
ส/ภา/พ/กา/ร/จ้า/ง/และ/ส/ภา/พ/กา/ร/ทำ/งา/น/
1820

21+
$ thainlp tokenize word -a longest "แรงงานกะดึก: ฟันเฟืองที่ยังหมุนในคำ่คืนมีเคอร์ฟิว"
22+
แรงงาน|กะ|ดึก|:| |ฟันเฟือง|ที่|ยัง|หมุน|ใน|คำ่|คืน|มี|เคอร์ฟิว|
1923

20-
**Syllable tokenization**::
24+
$ thainlp tokenize word -nw -s # "5 เหตุผล 'ไม่ควร' ต่อพ.ร.ก.ฉุกเฉิน"
25+
5#เหตุผล#'#ไม่#ควร#'#ต่อ#พ.ร.ก.#ฉุกเฉิน#
2126

22-
pythainlp tokenization syllable --text TEXT
27+
**Part-Of-Speech tagging**::
28+
29+
pythainlp tagg pos [-s SEPARATOR] TEXT
2330

2431
*Example*::
2532

26-
$ pythainlp tokenization syllable --text "ผมร<0e31>กประเทศไทย? สามารถ"
27-
ผม~รัก~ประ~เทศ~ไทย~? ~สา~มารถ
33+
$ thainlp tag pos -s . ผม.ไม่.กิน.เผ็ด
2834

29-
**Part-Of-Speech tagging**::
35+
**Soundex**::
3036

31-
pythainlp tagging pos --text TEXT
37+
thainlp soundex [-a udom83|lk82|metasound] TEXT
3238

3339
*Example*::
3440

35-
$ pythainlp tagging pos --text "ผม|ไม่|กิน|เผ็ด"
41+
$ thainlp soundex วรรณ
42+
ว330000
3643

37-
**Soundex**::
44+
$ thainlp soundex -a lk82 วัน
45+
ว4000
46+
47+
$ thainlp soundex -a lk82 วรรณ
48+
ว4000
3849

39-
pythainlp soundex --text TEXT
50+
**Corpus management**::
51+
52+
thainlp data <catalog|info|get|rm|path>
4053

4154
*Example*::
4255

43-
$ pythainlp soundex --text "บ<0e39>รณการ" --engine lk82
44-
บE419
56+
$ thainlp data path
57+
/Users/user1/pythainlp-data
58+
59+
$ thainlp data catalog
60+
Dataset/corpus available for download:
61+
- crfcut 0.1
62+
- thai-g2p 0.1 (Local: 0.1)
63+
- thai2fit_wv 0.1
64+
- thainer-1-3 1.3
4565

46-
**Mange corpus**::
66+
$ thainlp data get thai2fit_wv
67+
Corpus: thai2fit_wv
68+
- Downloading: thai2fit_wv 0.1
69+
36%|█████████████████▉ |
4770

48-
pythainlp corpus
71+
$ thainlp data --help
4972

5073
**Help**::
5174

52-
pythainlp --help
75+
thainlp --help

docs/notes/installation.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,8 @@ Runtime Configurations
5050
This environment variable specifies the location where the downloaded data
5151
and the corpus database information are stored. If this directory
5252
does not exist, PyThaiNLP will automatically create a new one.
53+
5354
By default, it is specified to the directory called ``pythainlp-data``
5455
within the home directory.
56+
57+
Type `thainlp data path` at command line to see current PYTHAINLP_DATA_DIR.

pythainlp/__main__.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,19 @@
66

77

88
def main(args=None):
9-
"""The main routine of PyThaiNLP command line."""
9+
"""ThaiNLP command line."""
1010
if args is None:
1111
args = sys.argv[1:]
1212

1313
parser = argparse.ArgumentParser(
14-
usage="pythainlp command [subcommand] [options]"
14+
"thainlp", usage="thainlp <command> [options]"
1515
)
1616

1717
parser.add_argument(
1818
"command",
1919
type=str,
20-
default="",
21-
nargs="?",
22-
help="[%s]" % "|".join(cli.COMMANDS),
20+
choices=cli.COMMANDS,
21+
help="text processing action",
2322
)
2423

2524
args = parser.parse_args(sys.argv[1:2])

pythainlp/cli/__init__.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
1+
"""Command line helpers."""
12
import sys
3+
from argparse import ArgumentParser
24

3-
from . import corpus
4-
from . import tokenize
5-
from . import soundex
6-
from . import tag
5+
from . import data, soundex, tag, tokenize
76

8-
# commands should be verb when possible
9-
COMMANDS = sorted(['corpus', 'tokenize', 'soundex', 'tag'])
7+
# a command should be a verb when possible
8+
COMMANDS = sorted(["data", "soundex", "tag", "tokenize"])
109

1110
CLI_NAME = "thainlp"
1211

1312

14-
def make_usage(s):
15-
prog = f"{CLI_NAME} {s}"
13+
def make_usage(command: str) -> dict:
14+
prog = f"{CLI_NAME} {command}"
1615

17-
return dict(
18-
prog=prog,
19-
usage="%(prog)s command [subcommand] [options]"
20-
)
16+
return dict(prog=prog, usage=f"{prog} [options]")
2117

2218

23-
def exit_if_empty(d, parser):
24-
if not d:
19+
def exit_if_empty(command: str, parser: ArgumentParser) -> None:
20+
if not command:
2521
parser.print_help()
2622
sys.exit(0)

pythainlp/cli/corpus.py

Lines changed: 0 additions & 40 deletions
This file was deleted.

pythainlp/cli/data.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"""
2+
thainlp dataset/corpus management command line.
3+
"""
4+
import argparse
5+
6+
from pythainlp import cli, corpus
7+
from pythainlp.tools import get_pythainlp_data_path
8+
9+
10+
class App:
11+
def __init__(self, argv):
12+
parser = argparse.ArgumentParser(
13+
prog="data", usage="thainlp data <subcommand>",
14+
)
15+
parser.add_argument(
16+
"subcommand",
17+
type=str,
18+
choices=["catalog", "info", "get", "rm", "path"],
19+
help="action on dataset/corpus",
20+
)
21+
args = parser.parse_args(argv[2:3])
22+
getattr(self, args.subcommand)(argv)
23+
24+
def get(self, argv):
25+
parser = argparse.ArgumentParser(
26+
description="Download a dataset",
27+
usage="thainlp data get <dataset_name>",
28+
)
29+
parser.add_argument(
30+
"dataset_name", type=str, help="dataset/corpus's name",
31+
)
32+
args = parser.parse_args(argv[3:])
33+
if corpus.download(args.dataset_name):
34+
print("Downloaded successfully.")
35+
else:
36+
print("Not found.")
37+
38+
def rm(self, argv):
39+
parser = argparse.ArgumentParser(
40+
description="Remove a dataset",
41+
usage="thainlp data rm <dataset_name>",
42+
)
43+
parser.add_argument(
44+
"dataset_name", type=str, help="dataset/corpus's name",
45+
)
46+
args = parser.parse_args(argv[3:])
47+
if corpus.remove(args.dataset_name):
48+
print("Removed successfully.")
49+
else:
50+
print("Not found.")
51+
52+
def info(self, argv):
53+
parser = argparse.ArgumentParser(
54+
description="Print information about a dataset",
55+
usage="thainlp data info <dataset_name>",
56+
)
57+
parser.add_argument(
58+
"dataset_name", type=str, help="dataset/corpus's name",
59+
)
60+
args = parser.parse_args(argv[3:])
61+
info = corpus.get_corpus_db_detail(args.dataset_name)
62+
if info:
63+
print(info)
64+
else:
65+
print("Not found.")
66+
67+
def catalog(self, argv):
68+
"""Print dataset/corpus available for download."""
69+
corpus_db = corpus.get_corpus_db(corpus.corpus_db_url())
70+
corpus_db = corpus_db.json()
71+
corpus_names = sorted(corpus_db.keys())
72+
print("Dataset/corpus available for download:")
73+
for name in corpus_names:
74+
print(f"- {name} {corpus_db[name]['version']}", end="")
75+
corpus_info = corpus.get_corpus_db_detail(name)
76+
if corpus_info:
77+
print(f" (Local: {corpus_info['version']})")
78+
else:
79+
print()
80+
81+
print("\nUse subcommand 'get' to download dataset.")
82+
print("Example: thainlp data get crfcut")
83+
84+
def path(self, argv):
85+
"""Print path for local dataset."""
86+
print(get_pythainlp_data_path())

pythainlp/cli/soundex.py

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,34 @@
1+
"""
2+
thainlp soundex command line.
3+
4+
Take input text from command line.
5+
"""
16
import argparse
27

38
from pythainlp import cli
4-
from pythainlp.soundex import soundex
9+
from pythainlp.soundex import DEFAULT_SOUNDEX_ENGINE, soundex
510

611

712
class App:
8-
913
def __init__(self, argv):
10-
parser = argparse.ArgumentParser("soundex")
11-
14+
parser = argparse.ArgumentParser(
15+
prog="soundex",
16+
description="Convert a text to its sound-based index.",
17+
)
1218
parser.add_argument(
13-
"subcommand",
19+
"-a",
20+
"--algo",
21+
dest="algorithm",
1422
type=str,
15-
nargs="?",
16-
help="[udom83|lk82|metasound]"
23+
choices=["udom83", "lk82", "metasound"],
24+
help="soundex algorithm",
25+
default=DEFAULT_SOUNDEX_ENGINE,
1726
)
18-
1927
parser.add_argument(
20-
"-t",
21-
"--text",
22-
type=str,
23-
help="input text",
28+
"text", type=str, help="input text",
2429
)
2530

26-
args = parser.parse_args(argv[2:3])
27-
28-
cli.exit_if_empty(args.subcommand, parser)
29-
subcommand = str.lower(args.subcommand)
30-
31-
cli.exit_if_empty(args.text, parser)
32-
33-
sdx = ""
34-
if subcommand.startswith("udom"):
35-
sdx = soundex(args.text, engine="udom83")
36-
elif subcommand.startswith("lk"):
37-
sdx = soundex(args.text, engine="lk82")
38-
elif subcommand.startswith("meta"):
39-
sdx = soundex(args.text, engine="metasound")
40-
else:
41-
raise NotImplementedError(
42-
f"Subcommand not available: {subcommand}")
31+
args = parser.parse_args(argv[2:])
4332

33+
sdx = soundex(args.text, engine=args.algorithm)
4434
print(sdx)

0 commit comments

Comments
 (0)