Browse Source

Utils: add comments, options, and methods to rules.py

remotes/origin/cmake
Romain Goffe 13 years ago
parent
commit
f64f93f762
  1. 137
      utils/rules.py

137
utils/rules.py

@ -2,9 +2,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import glob import glob
import sys import getopt, sys
import fileinput
import re import re
import logging
import locale
re.LOCALE re.LOCALE
# the dictionary has target_word:replacement_word pairs # the dictionary has target_word:replacement_word pairs
@ -110,61 +111,135 @@ word_dic = {
### end of rules ### end of rules
} }
# Process song files
songfiles = glob.glob('songs/*/*.sg')
for filename in songfiles:
with open(filename, 'r+') as songfile:
data = songfile.read() def usage():
#replace words print '''
for search, replace in word_dic.items(): Usage: rules.py [OPTION]
data = data.replace(search, replace)
#no dots for acronyms OPTIONS
# data = re.sub("(?P<capital_letter>[A-Z])\.","\g<capital_letter>", data) -h, --help
display this help and exit
-f, --files=FILES
apply the set of rules on FILES
default is songs/*/*.sg
-l, --log=LEVEL
set the logging level to LEVEL
possible LEVEL values are : debug, info, warning, error and critical
'''
def replace_words(string):
'''
Search the data string for words defined in the dictionary and
replace them. This method avoids usual spelling and typos mistakes
when writing a song.
'''
logging.info("replace_words: search and replace words from dictionary into song data")
for search, replace in word_dic.items():
string = string.replace(search, replace)
return string
#language based typographical rules #language based typographical rules
if (re.compile("selectlanguage{french}").search(data)): def language_rules(string):
'''
Search the data string for common typographical mistakes.
Implemented rules depend on the current song language that is
defined by babel for every .sg file through the macro
\selectlanguage{<lang>}
'''
logging.info("language_rules: looking for common typographical mistakes")
if (re.compile("selectlanguage{french}").search(string)):
logging.info(" song language is set to : french")
#ensure non-breaking spaces before symbols ? ! ; : #ensure non-breaking spaces before symbols ? ! ; :
data = re.sub("(?P<last_char>\S)(?P<symbol>[!?;:])","\g<last_char> \g<symbol>", data) string = re.sub("(?P<last_char>\S)(?P<symbol>[!?;:])","\g<last_char> \g<symbol>", string)
#... except for gtabs macros with capos #... except for gtabs macros with capos
data = re.sub("(?P<gtab>gtab.*)\s:","\g<gtab>:", data) string = re.sub("(?P<gtab>gtab.*)\s:","\g<gtab>:", string)
#and apply a second time for cases like \gtab{Gm}{10:X02210:} #and apply a second time for cases like \gtab{Gm}{10:X02210:}
data = re.sub("(?P<gtab>gtab.*)\s:","\g<gtab>:", data) string = re.sub("(?P<gtab>gtab.*)\s:","\g<gtab>:", string)
#ensure no spaces after symbols ( #ensure no spaces after symbols (
data = re.sub("(?P<symbol>[\(])\s(?P<next_char>\S)","\g<symbol>\g<next_char>", data) string = re.sub("(?P<symbol>[\(])\s(?P<next_char>\S)","\g<symbol>\g<next_char>", string)
#convert inverted commas #convert inverted commas
data = re.sub("``","{\\og}", data) string = re.sub("``","{\\og}", string)
data = re.sub("''","{\\\\fg}", data) string = re.sub("''","{\\\\fg}", string)
elif (re.compile("selectlanguage{english}").search(data)): elif (re.compile("selectlanguage{english}").search(string)):
#print "english song" logging.info(" song language is set to : english")
#ensure no spaces before symbols ? ! ; : ) #ensure no spaces before symbols ? ! ; : )
data = re.sub("(?P<last_char>\S)\s(?P<symbol>[!?;:\)])","\g<last_char>\g<symbol>", data) string = re.sub("(?P<last_char>\S)\s(?P<symbol>[!?;:\)])","\g<last_char>\g<symbol>", string)
#ensure no spaces after symbols ( #ensure no spaces after symbols (
data = re.sub("(?P<symbol>[\(])\s(?P<next_char>\S)","\g<symbol>\g<next_char>", data) string = re.sub("(?P<symbol>[\(])\s(?P<next_char>\S)","\g<symbol>\g<next_char>", string)
elif (re.compile("selectlanguage{spanish}").search(data)): elif (re.compile("selectlanguage{spanish}").search(string)):
#print "spanish song" logging.info(" song language is set to : spanish")
#ensure no spaces before symbols ? ! ; : ) #ensure no spaces before symbols ? ! ; : )
data = re.sub("(?P<last_char>\S)\s(?P<symbol>[!?;:\)])","\g<last_char>\g<symbol>", data) string = re.sub("(?P<last_char>\S)\s(?P<symbol>[!?;:\)])","\g<last_char>\g<symbol>", string)
#ensure no spaces after symbols ¿ ¡ ( #ensure no spaces after symbols ¿ ¡ (
data = re.sub("(?P<symbol>[¿¡\(])\s(?P<next_char>\S)","\g<symbol>\g<next_char>", data) string = re.sub("(?P<symbol>[¿¡\(])\s(?P<next_char>\S)","\g<symbol>\g<next_char>", string)
elif (re.compile("selectlanguage{portuguese}").search(data)): elif (re.compile("selectlanguage{portuguese}").search(string)):
logging.info(" song language is set to : portuguese")
#convert inverted commas #convert inverted commas
data = re.sub("``","{\\og}", data) string = re.sub("``","{\\og}", string)
data = re.sub("''","{\\\\fg}", data) string = re.sub("''","{\\\\fg}", string)
else : else :
print "Warning: language is not defined for song : " + filename print "Warning: language is not defined for song : " + filename
return string
lines = data.split('\n') def process_lines(lines):
'''
Removes trailing punctuation and multi-spaces from lines. Not
that it preserves whitespaces at the beginning of lines that
correspond to indentation.
'''
logging.info("process_lines: handling song data line by line")
for index, line in enumerate(lines): for index, line in enumerate(lines):
#remove trailing spaces and punctuation #remove trailing spaces and punctuation
line = line.rstrip().rstrip(',.;').rstrip() line = line.rstrip().rstrip(',.;').rstrip()
#remove multi-spaces within lines #remove multi-spaces within lines
line = re.sub("(?P<last_char>\S)\s{2,}","\g<last_char> ", line) line = re.sub("(?P<last_char>\S)\s{2,}","\g<last_char> ", line)
lines[index] = line lines[index] = line
return lines
def main():
locale.setlocale(locale.LC_ALL, '')
try:
opts, args = getopt.getopt(sys.argv[1:],
"hf:l:",
["help", "files=", "log="])
except getopt.GetoptError:
usage()
sys.exit(2)
songfiles = glob.glob('songs/*/*.sg')
loglevel = "warning"
for option, arg in opts:
if option in ("-h", "--help"):
usage()
sys.exit()
elif option in ("-f", "--files"):
songfiles = glob.glob(arg)
elif option in ("-l", "--log"):
loglevel = arg
numeric_level = getattr(logging, loglevel.upper(), None)
if not isinstance(numeric_level, int):
raise ValueError('Invalid log level: %s' % loglevel)
logging.basicConfig(level=numeric_level, filename='rules.log', filemode='w')
else:
assert False, "unhandled option"
for filename in songfiles:
with open(filename, 'r+') as songfile:
data = songfile.read()
#no dots for acronyms
#data = re.sub("(?P<capital_letter>[A-Z])\.","\g<capital_letter>", data)
data = replace_words(data)
data = language_rules(data)
lines = process_lines(data.split('\n'))
data = "\n".join(lines) data = "\n".join(lines)
songfile.seek(0) songfile.seek(0)
songfile.write(data) songfile.write(data)
songfile.truncate() songfile.truncate()
if __name__ == '__main__':
main()

Loading…
Cancel
Save