Repository: opendatakosovo/cyrillic-transliteration (language: python)

Issue:
File and command line?
input a .txt and execute it through a command "CyrTranslit -i text.txt"
File and command line?
input a .txt and execute it through a command "CyrTranslit -i text.txt"
Command line interface
I need this for a project pipeline, but thought it would be useful for you. It should solve #12 .

The code of the command line script has been simplified and now it is able to read files and stdin seamlessly without any limitation of large inputs. I've also added the short command installation. The usage is detailed on the readme.


Discussion / hints:
Great idea @andradadad! I will look into this.
Second this suggestion, a command line utility for transliteration would be great. Or may be you guys have heard of something like this already in existence?
Great idea @andradadad! I will look into this.
Second this suggestion, a command line utility for transliteration would be great. Or may be you guys have heard of something like this already in existence?


Fix patch:
diff --git a/README.md b/README.md
index 5a17f7d..cb0ffb2 100644
--- a/README.md
+++ b/README.md
@@ -24,8 +24,10 @@ CyrTranslit currently supports bi-directional transliteration of Bulgarian, Mont
 ['bg', 'me', 'mk', 'mn', 'ru', 'sr', 'tj', 'ua']
 ```
 ## How do I use this? 
+CyrTranslit can be used both programatically and via command line interface.
 
-### Bulgarian
+### Programmatically
+#### Bulgarian
 ```python
 >>> import cyrtranslit
 >>> cyrtranslit.to_latin("Съединението прави силата!", "bg")
@@ -34,7 +36,7 @@ CyrTranslit currently supports bi-directional transliteration of Bulgarian, Mont
 "Съединението прави силата!"
 ```
 
-### Montenegrin
+#### Montenegrin
 ```python
 >>> import cyrtranslit
 >>> cyrtranslit.to_latin("Република", "me")
@@ -43,7 +45,7 @@ CyrTranslit currently supports bi-directional transliteration of Bulgarian, Mont
 "Република"
 ```
 
-### Macedonian
+#### Macedonian
 ```python
 >>> import cyrtranslit
 >>> cyrtranslit.to_latin("Моето летачко возило е полно со јагули", "mk")
@@ -51,7 +53,8 @@ CyrTranslit currently supports bi-directional transliteration of Bulgarian, Mont
 >>> cyrtranslit.to_cyrillic("Moeto letačko vozilo e polno so jaguli", "mk")
 "Моето летачко возило е полно со јагули"
 ```
-### Mongolian
+
+#### Mongolian
 ```python
 >>> import cyrtranslit
 >>> cyrtranslit.to_latin("Амрагаа Сүнжидмаагаа гэсээр ирлээ дээ хө-хө-хө", "mn")
@@ -60,7 +63,7 @@ CyrTranslit currently supports bi-directional transliteration of Bulgarian, Mont
 "Амрагаа Сүнжидмаагаа гэсээр ирлээ дээ хө-хө-хө"
 ```
 
-### Russian
+#### Russian
 ```python
 >>> import cyrtranslit
 >>> cyrtranslit.to_latin("Моё судно на воздушной подушке полно угрей", "ru")
@@ -69,7 +72,7 @@ CyrTranslit currently supports bi-directional transliteration of Bulgarian, Mont
 "Моё судно на воздушной подушке полно угрей"
 ```
 
-### Serbian
+#### Serbian
 ```python
 >>> import cyrtranslit
 >>> cyrtranslit.to_latin("Мој ховеркрафт је пун јегуља")
@@ -78,7 +81,7 @@ CyrTranslit currently supports bi-directional transliteration of Bulgarian, Mont
 "Мој ховеркрафт је пун јегуља"
 ```
 
-### Tajik
+#### Tajik
 ```python
 >>> import cyrtranslit
 >>> cyrtranslit.to_latin("Ман мактуб навишта истодам", "tj")
@@ -87,7 +90,7 @@ CyrTranslit currently supports bi-directional transliteration of Bulgarian, Mont
 "Ман мактуб навишта истодам"
 ```
 
-### Ukrainian
+#### Ukrainian
 ```python
 >>> import cyrtranslit
 >>> cyrtranslit.to_latin("Під лежачий камінь вода не тече", "ua")
@@ -96,6 +99,40 @@ CyrTranslit currently supports bi-directional transliteration of Bulgarian, Mont
 "Під лежачий камінь вода не тече"
 ```
 
+## Command Line Interface
+Sample command line call to transliterate a Russian text file:
+```bash
+$ cyrtranslit -l RU -i tests/ru.txt -o tests/output.txt
+```
+
+Use the -c argument to accomplish the reverse, that is to input latin characters and output cyrillic.
+
+Use the -h argument for help.
+
+You can also omit the input and output files and use standard input/output
+```bash
+$ echo 'Мој ховеркрафт је пун јегуља' | cyrtranslit -l sr
+Moj hoverkraft je pun jegulja
+$ echo 'Moj hoverkraft je pun jegulja' | cyrtranslit -l sr
+Мој ховеркрафт је пун јегуља
+```
+
+You can test the "script" by running it directly, e.g.:
+```bash
+$ python3
+Python 3.10.8 (main, Oct 12 2022, 19:14:09) [GCC 7.5.0] on linux
+Type "help", "copyright", "credits" or "license" for more information.
+>>> import sys
+>>> import cyrtranslit.cyrtranslit
+>>> sys.argv.extend(['-l', 'RU'])
+>>> sys.argv.extend(['-i', 'tests/ru.txt'])
+>>> sys.argv.extend(['-o', 'tests/output.txt'])
+
+>>> cyrtranslit.cyrtranslit.main()
+>>> exit()
+```
+
+
 ## How can I contribute?
 You can include support for other Cyrillic script alphabets. Follow these steps in order to do so:
 
@@ -117,7 +154,7 @@ A citation would be much appreciated if you use CyrTranslit in a research public
 [Georges Labrèche. (2021, March 29). CyrTranslit (Version v1.0). Zenodo. http://doi.org/10.5281/zenodo.4643047](https://doi.org/10.5281/zenodo.4643047)
 
 BibTex entry:
-```
+```bibtex
 @software{georges_labreche_2021_4643047,
   author       = {Georges Labrèche},
   title        = {CyrTranslit},
diff --git a/cyrtranslit/cyrtranslit.py b/cyrtranslit/cyrtranslit.py
new file mode 100644
index 0000000..87d9e06
--- /dev/null
+++ b/cyrtranslit/cyrtranslit.py
@@ -0,0 +1,65 @@
+import cyrtranslit
+from cyrtranslit.mapping import TRANSLIT_DICT
+from argparse import ArgumentParser, FileType
+import os
+import sys
+
+def __is_valid_language_code(parse, arg):
+    ''' Validates inputted two-letter language code.
+    :param parse: The argument parser. Used to display error message.
+    :param arg: The language code argument.
+    '''
+    if arg.lower() not in TRANSLIT_DICT:
+        parser.error("The language code %s is not supported. Support language codes are: %s." % (arg, ", ".join(TRANSLIT_DICT.keys()).upper()))
+    else:
+        return arg
+
+def main():
+    # Setup argument parser
+    parser = ArgumentParser(description="Transiliterate text in a given file.")
+
+    # Input file.
+    # Not required.
+    parser.add_argument("-i", dest="input_file", required=False,
+                        help="input file",
+                        type=FileType('rt'),
+                        default=sys.stdin)
+
+    # Output file.
+    # Not required. If not specified, transliteration will appear as console output.
+    parser.add_argument("-o", dest="output_file", required=False,
+                        help="ouput file",
+                        type=FileType('w'),
+                        default=sys.stdout)
+
+    # Language code for cyrillic text in inputted file.
+    # Required.
+    parser.add_argument("-l", dest="language_code", required=True,
+                        help="two-letter ISO 639-1 language code of cyrillic text",
+                        type=lambda x: __is_valid_language_code(parser, x))
+
+    # Flag for reverse transliteration, i.e. from latin/roman alphabet to cyrillic.
+    parser.add_argument("-c", dest="to_cyrillic", action='store_true',
+                        help="Parse latin characters to cyrillic (reverse of transliteration)")
+
+    # Parse arguments
+    args = parser.parse_args()
+
+    # Fetch arguments.
+    lang_code = args.language_code
+    file_output = args.output_file
+    file_input = args.input_file
+    to_cyrillic = args.to_cyrillic
+
+    # Transliterate and write directly to output line by line
+    for line in file_input:
+        if to_cyrillic is True:
+            file_output.write(cyrtranslit.to_cyrillic(line, lang_code=lang_code))
+        else:
+            file_output.write(cyrtranslit.to_latin(line, lang_code=lang_code))
+
+    # Close output stream.
+    file_output.close()
+
+if __name__ == "__main__":
+    main()
diff --git a/setup.py b/setup.py
index b309c57..5ab2575 100644
--- a/setup.py
+++ b/setup.py
@@ -25,4 +25,9 @@
                'Programming Language :: Python :: 3.6',
                'Programming Language :: Python :: 3.7',
                'Programming Language :: Python :: 3.8'],
-)
+  entry_points={
+      "console_scripts": [
+          "cyrtranslit=cyrtranslit.cyrtranslit:main",
+      ]
+  }
+)
\ No newline at end of file


Test patch:
diff --git a/tests/bg.txt b/tests/bg.txt
new file mode 100644
index 0000000..2968085
--- /dev/null
+++ b/tests/bg.txt
@@ -0,0 +1,1 @@
+АаБбВвГгДдЕеЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЬьЮюЯя
\ No newline at end of file
diff --git a/tests/me.txt b/tests/me.txt
new file mode 100644
index 0000000..fa45d73
--- /dev/null
+++ b/tests/me.txt
@@ -0,0 +1,1 @@
+АаБбВвГгДдЂђЕеЖжЗзЗ́з́ИиЈјКкЛлЉљМмНнЊњОоПпРрСсТтЋћУуФфХхЦцЧчЏџШшС́с́
diff --git a/tests/mk.txt b/tests/mk.txt
new file mode 100644
index 0000000..8891222
--- /dev/null
+++ b/tests/mk.txt
@@ -0,0 +1,1 @@
+АаБбВвГгДдЃѓЕеЖжЗзЅѕИиЈјКкЛлЉљМмНнЊњОоПпРрСсТтЌќУуФфХхЦцЧчЏџШш
diff --git a/tests/mn.txt b/tests/mn.txt
new file mode 100644
index 0000000..efa63eb
--- /dev/null
+++ b/tests/mn.txt
@@ -0,0 +1,1 @@
+АаБбВвГгДдЂђЕеЖжЗзЗ́з́ИиЈјКкЛлЉљМмНнЊњОоПпРрСсТтЋћУуФфХхЦцЧчЏџШшС́с́
\ No newline at end of file
diff --git a/tests/ru.txt b/tests/ru.txt
new file mode 100644
index 0000000..34e80ed
--- /dev/null
+++ b/tests/ru.txt
@@ -0,0 +1,1 @@
+АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮюЯя
diff --git a/tests/sr.txt b/tests/sr.txt
new file mode 100644
index 0000000..6c10ee2
--- /dev/null
+++ b/tests/sr.txt
@@ -0,0 +1,1 @@
+АаБбВвГгДдЂђЕеЖжЗзИиЈјКкЛлЉљМмНнЊњОоПпРрСсТтЋћУуФфХхЦцЧчЏџШш
diff --git a/tests/tj.txt b/tests/tj.txt
new file mode 100644
index 0000000..9cf2119
--- /dev/null
+++ b/tests/tj.txt
@@ -0,0 +1,1 @@
+АаБбВвГгҒғДдЕеЁёЖжЗзИиӢӣЙйКкЛлМмНнОоПпРрСсТтУуӮӯФфХхҲҳЧчҶҷШшъЭэЮюЯя
diff --git a/tests/ua.txt b/tests/ua.txt
new file mode 100644
index 0000000..4b7a2f3
--- /dev/null
+++ b/tests/ua.txt
@@ -0,0 +1,1 @@
+АаБбВвГгҐґДдЕеЄєЖжЗзИиІіЇїЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЮюЯяь
\ No newline at end of file