2021-10-12 04:40:03 +08:00
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
"""
A Python script to generate or update alias pages .
2024-05-13 16:21:30 +02:00
Disclaimer : This script generates a lot of false positives so it isn ' t suggested to use the sync option. If used, only stage changes and commit verified changes for your language by using -l LANGUAGE.
2021-10-12 04:40:03 +08:00
2024-05-13 16:21:30 +02:00
Note : If the current directory or one of its parents is called " tldr " , the script will assume it is the tldr root , i . e . , the directory that contains a clone of https : / / github . com / tldr - pages / tldr
If you aren ' t, the script will use TLDR_ROOT as the tldr root. Also, ensure ' git ' is available.
2023-12-21 19:47:18 +05:30
Usage :
2024-05-13 16:21:30 +02:00
python3 scripts / set - alias - page . py [ - p PAGE ] [ - S ] [ - l LANGUAGE ] [ - s ] [ - n ] [ COMMAND ]
2023-12-21 19:47:18 +05:30
Options :
- p , - - page PAGE
Specify the alias page in the format " platform/alias_command.md " .
2024-05-13 16:21:30 +02:00
- S , - - sync
Synchronize each translation ' s alias page (if exists) with that of the English page.
2024-05-09 13:01:01 +02:00
- l , - - language LANGUAGE
Specify the language , a POSIX Locale Name in the form of " ll " or " ll_CC " ( e . g . " fr " or " pt_BR " ) .
2023-12-21 19:47:18 +05:30
- s , - - stage
Stage modified pages ( requires ' git ' on $ PATH and TLDR_ROOT to be a Git repository ) .
2024-01-02 06:53:39 +01:00
- n , - - dry - run
Show what changes would be made without actually modifying the page .
2024-05-13 16:21:30 +02:00
Positional Argument :
COMMAND The command to be set as the alias command .
2023-12-21 19:47:18 +05:30
Examples :
1. Add ' vi ' as an alias page of ' vim ' :
2024-01-02 06:53:39 +01:00
python3 scripts / set - alias - page . py - p common / vi vim
2024-05-13 16:21:30 +02:00
python3 scripts / set - alias - page . py - - page common / vi vim
2023-12-21 19:47:18 +05:30
2. Read English alias pages and synchronize them into all translations :
2024-01-02 06:53:39 +01:00
python3 scripts / set - alias - page . py - S
2024-05-13 16:21:30 +02:00
python3 scripts / set - alias - page . py - - sync
2024-01-02 06:53:39 +01:00
2024-05-13 16:21:30 +02:00
3. Read English alias pages and synchronize them for Brazilian Portuguese pages only :
2024-05-09 13:01:01 +02:00
python3 scripts / set - alias - page . py - S - l pt_BR
python3 scripts / set - alias - page . py - - sync - - language pt_BR
2024-05-13 16:21:30 +02:00
4. Read English alias pages , synchronize them into all translations and stage modified pages for commit :
python3 scripts / set - more - info - link . py - Ss
python3 scripts / set - more - info - link . py - - sync - - stage
5. Read English alias pages and show what changes would be made :
python3 scripts / set - alias - page . py - Sn
python3 scripts / set - alias - page . py - - sync - - dry - run
2021-10-12 04:40:03 +08:00
"""
import argparse
import os
import re
import subprocess
2024-05-13 16:21:30 +02:00
from pathlib import Path
2021-10-12 04:40:03 +08:00
IGNORE_FILES = ( " .DS_Store " , " tldr.md " , " aria2.md " )
def get_tldr_root ( ) :
"""
Get the path of local tldr repository for environment variable TLDR_ROOT .
"""
# If this script is running from tldr/scripts, the parent's parent is the root
2024-05-13 16:21:30 +02:00
f = Path ( __file__ ) . resolve ( )
if (
tldr_root := next ( ( path for path in f . parents if path . name == " tldr " ) , None )
) is not None :
return tldr_root
elif " TLDR_ROOT " in os . environ :
return Path ( os . environ [ " TLDR_ROOT " ] )
raise SystemExit (
" \x1b [31mPlease set TLDR_ROOT to the location of a clone of https://github.com/tldr-pages/tldr. "
)
2021-10-12 04:40:03 +08:00
def get_templates ( root ) :
"""
Get all alias page translation templates from
TLDR_ROOT / contributing - guides / translation - templates / alias - pages . md .
Parameters :
root ( string ) : The path of local tldr repository , i . e . , TLDR_ROOT .
Returns :
dict of ( str , str ) : Language labels map to alias page templates .
"""
template_file = os . path . join (
root , " contributing-guides/translation-templates/alias-pages.md "
)
2024-05-09 13:01:01 +02:00
with open ( template_file , encoding = " utf-8 " ) as f :
2021-10-12 04:40:03 +08:00
lines = f . readlines ( )
# Parse alias-pages.md
templates = { }
i = 0
while i < len ( lines ) :
if lines [ i ] . startswith ( " ### " ) :
lang = lines [ i ] [ 4 : ] . strip ( " \n " ) . strip ( " " )
while True :
i = i + 1
if lines [ i ] . startswith ( " Not translated yet. " ) :
is_translated = False
break
elif lines [ i ] . startswith ( " ```markdown " ) :
i = i + 1
is_translated = True
break
if is_translated :
text = " "
while not lines [ i ] . startswith ( " ``` " ) :
text + = lines [ i ]
i = i + 1
templates [ lang ] = text
i = i + 1
return templates
def get_alias_page ( file ) :
"""
Determine whether the given file is an alias page .
Parameters :
file ( string ) : Path to a page
Returns :
str : " " If the file doesn ' t exit or is not an alias page,
otherwise return what command the alias stands for .
"""
if not os . path . isfile ( file ) :
return " "
2024-05-09 13:01:01 +02:00
with open ( file , " r " , encoding = " utf-8 " ) as f :
2023-10-04 03:32:15 -05:00
for line in f :
if match := re . search ( r " ^`tldr (.+)` " , line ) :
return match [ 1 ]
2021-10-12 04:40:03 +08:00
return " "
2024-05-09 13:01:01 +02:00
def set_alias_page ( file , command , dry_run = False , language_to_update = " " ) :
2021-10-12 04:40:03 +08:00
"""
Write an alias page to disk .
Parameters :
file ( string ) : Path to an alias page
command ( string ) : The command that the alias stands for .
2024-05-09 13:01:01 +02:00
dry_run ( bool ) : Whether to perform a dry - run , i . e . only show the changes that would be made .
language_to_update ( string ) : Optionally , the language of the translation to be updated .
2021-10-12 04:40:03 +08:00
Returns :
str : Execution status
" " if the alias page standing for the same command already exists .
" \x1b [36mpage added " if it ' s a new alias page.
" \x1b [34mpage updated " if the command updates .
"""
# compute locale
pages_dir = os . path . basename ( os . path . dirname ( os . path . dirname ( file ) ) )
if " . " in pages_dir :
_ , locale = pages_dir . split ( " . " )
else :
locale = " en "
2024-05-09 13:01:01 +02:00
if locale not in templates or (
language_to_update != " " and locale != language_to_update
) :
2021-10-12 04:40:03 +08:00
return " "
# Test if the alias page already exists
orig_command = get_alias_page ( file )
if orig_command == command :
return " "
2024-01-02 06:53:39 +01:00
if orig_command == " " :
status_prefix = " \x1b [36m "
action = " added "
2021-10-12 04:40:03 +08:00
else :
2024-01-02 06:53:39 +01:00
status_prefix = " \x1b [34m "
action = " updated "
2021-10-12 04:40:03 +08:00
2024-01-02 06:53:39 +01:00
if dry_run :
2024-05-13 16:21:30 +02:00
status = f " page would be { action } "
2024-01-02 06:53:39 +01:00
else :
status = f " page { action } "
status = f " { status_prefix } { status } \x1b [0m "
if not dry_run : # Only write to the file during a non-dry-run
alias_name , _ = os . path . splitext ( os . path . basename ( file ) )
text = (
templates [ locale ]
. replace ( " example " , alias_name , 1 )
. replace ( " example " , command )
)
os . makedirs ( os . path . dirname ( file ) , exist_ok = True )
2024-05-09 13:01:01 +02:00
with open ( file , " w " , encoding = " utf-8 " ) as f :
2024-01-02 06:53:39 +01:00
f . write ( text )
2021-10-12 04:40:03 +08:00
return status
2024-05-09 13:01:01 +02:00
def sync (
root , pages_dirs , alias_name , orig_command , dry_run = False , language_to_update = " "
) :
2021-10-12 04:40:03 +08:00
"""
2024-01-02 06:53:39 +01:00
Synchronize an alias page into all translations .
2021-10-12 04:40:03 +08:00
Parameters :
root ( str ) : TLDR_ROOT
pages_dirs ( list of str ) : Strings of page entry and platform , e . g . " page.fr/common " .
alias_name ( str ) : An alias command with . md extension like " vi.md " .
orig_command ( string ) : An Original command like " vim " .
2024-05-09 13:01:01 +02:00
dry_run ( bool ) : Whether to perform a dry - run , i . e . only show the changes that would be made .
language_to_update ( string ) : Optionally , the language of the translation to be updated .
2021-10-12 04:40:03 +08:00
Returns :
2024-01-02 06:53:39 +01:00
list : A list of paths to be staged into git , using by - - stage option .
2021-10-12 04:40:03 +08:00
"""
rel_paths = [ ]
for page_dir in pages_dirs :
path = os . path . join ( root , page_dir , alias_name )
2024-05-09 13:01:01 +02:00
status = set_alias_page ( path , orig_command , dry_run , language_to_update )
2021-10-12 04:40:03 +08:00
if status != " " :
rel_path = path . replace ( f " { root } / " , " " )
rel_paths . append ( rel_path )
print ( f " \x1b [32m { rel_path } { status } \x1b [0m " )
return rel_paths
def main ( ) :
parser = argparse . ArgumentParser (
description = " Sets the alias page for all translations of a page "
)
parser . add_argument (
" -p " ,
" --page " ,
type = str ,
required = False ,
default = " " ,
help = ' page name in the format " platform/alias_command.md " ' ,
)
2024-05-13 16:21:30 +02:00
parser . add_argument (
" -S " ,
" --sync " ,
action = " store_true " ,
default = False ,
help = " synchronize each translation ' s alias page (if exists) with that of English page " ,
)
2024-05-09 13:01:01 +02:00
parser . add_argument (
" -l " ,
" --language " ,
type = str ,
required = False ,
default = " " ,
help = ' language in the format " ll " or " ll_CC " (e.g. " fr " or " pt_BR " ) ' ,
)
2021-10-12 04:40:03 +08:00
parser . add_argument (
" -s " ,
" --stage " ,
action = " store_true " ,
default = False ,
help = " stage modified pages (requires `git` to be on $PATH and TLDR_ROOT to be a Git repository) " ,
)
2024-01-02 06:53:39 +01:00
parser . add_argument (
" -n " ,
" --dry-run " ,
action = " store_true " ,
default = False ,
help = " show what changes would be made without actually modifying the pages " ,
)
2021-10-12 04:40:03 +08:00
parser . add_argument ( " command " , type = str , nargs = " ? " , default = " " )
args = parser . parse_args ( )
root = get_tldr_root ( )
# A dictionary of all alias page translations
global templates
templates = get_templates ( root )
pages_dirs = [ d for d in os . listdir ( root ) if d . startswith ( " pages " ) ]
rel_paths = [ ]
# Use '--page' option
if args . page != " " :
if not args . page . lower ( ) . endswith ( " .md " ) :
args . page = f " { args . page } .md "
target_paths = [ os . path . join ( root , p , args . page ) for p in pages_dirs ]
target_paths . sort ( )
for path in target_paths :
rel_path = path . replace ( f " { root } / " , " " )
rel_paths . append ( rel_path )
2024-05-09 13:01:01 +02:00
status = set_alias_page ( path , args . command , args . language )
2021-10-12 04:40:03 +08:00
if status != " " :
print ( f " \x1b [32m { rel_path } { status } \x1b [0m " )
# Use '--sync' option
elif args . sync :
pages_dirs . remove ( " pages " )
en_page = os . path . join ( root , " pages " )
platforms = [ i for i in os . listdir ( en_page ) if i not in IGNORE_FILES ]
for platform in platforms :
platform_path = os . path . join ( en_page , platform )
commands = [
f " { platform } / { p } "
for p in os . listdir ( platform_path )
if p not in IGNORE_FILES
]
for command in commands :
orig_command = get_alias_page ( os . path . join ( root , " pages " , command ) )
if orig_command != " " :
2024-01-02 06:53:39 +01:00
rel_paths + = sync (
2024-05-09 13:01:01 +02:00
root ,
pages_dirs ,
command ,
orig_command ,
args . dry_run ,
args . language ,
2024-01-02 06:53:39 +01:00
)
2021-10-12 04:40:03 +08:00
2024-01-02 06:53:39 +01:00
# Use '--stage' option
if args . stage and not args . dry_run :
2021-10-12 04:40:03 +08:00
subprocess . call ( [ " git " , " add " , * rel_paths ] , cwd = root )
if __name__ == " __main__ " :
main ( )