1#!/usr/bin/env python 2# This file is part of python-ly, https://pypi.python.org/pypi/python-ly 3# 4# Copyright (c) 2008 - 2015 by Wilbert Berendsen 5# 6# This program is free software; you can redistribute it and/or 7# modify it under the terms of the GNU General Public License 8# as published by the Free Software Foundation; either version 2 9# of the License, or (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program; if not, write to the Free Software 18# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19# See http://www.gnu.org/licenses/ for more information. 20 21""" 22generate all scheme words in the _scheme_data.py file 23""" 24from __future__ import unicode_literals 25 26import os 27import re 28try: 29 from urllib.request import urlopen 30except: 31 from urllib import urlopen 32 33 34VERSION = "2.18" 35GUILE_URL = "https://www.gnu.org/software/guile/docs/docs-1.8/guile-ref/Procedure-Index.html#Procedure-Index" 36LY_FUNCTION_URL = "http://lilypond.org/doc/v2.18/Documentation/internals/scheme-functions" 37SCM_PATH = os.path.join(os.environ['HOME'], 'lilypond_bin/2.18.2-1/lilypond/usr/share/lilypond/current/scm') 38 39GUILE_IGNONED_TYPE = ( 40 'Apply Traps', 41 'Common Trap Options', 42 'Continuations', 43 'Debug on Error', 44 'Display Backtrace', 45 'Encryption', 46 'Entry Traps', 47 'Exit Traps', 48 'Garbage Collection Functions', 49 'getopt-long Reference', 50 'Internationalization', 51 'Location Traps', 52 'Network Databases', 53 'Network Socket Address', 54 'Network Sockets and Communication', 55 'Procedure Traps', 56 'Signals', 57 'Threads', 58 'Trap Utilities', 59 'Source Traps', 60 'Step Traps', 61 'SRFI-37', 62 'Stepping and Continuing', 63 'System asyncs', 64 'System Identification', 65 'User asyncs', 66 'User Information', 67 'User level options interfaces', 68) 69 70GUILE_OTHER_WORDS = ['else', 'set!'] 71 72def writeList(file_, name, lst): 73 file_.write("{} = [\n".format(name)) 74 for word in sorted(set(lst)): 75 file_.write(" '{0}',\n".format(word)) 76 file_.write("]\n\n") 77 78def replace(word): 79 word = word.replace('<', '<') 80 word = word.replace('>', '>') 81 return word 82 83guilePage = urlopen(GUILE_URL).read() 84guilePat = re.compile(r"<code>([a-z\d\+\?\!\*&;/=:-]+)</code></a>: <a href=\".+\">(.+)</a>") 85 86lyFunctionPage = urlopen(LY_FUNCTION_URL).read() 87lyFunctionPat = re.compile(r'<u>Function:</u> <b>(ly:.+)</b>') 88 89 90defineFunc = re.compile(r'\((?:define\*?|define-safe)-public\s+\(([-><a-zA-Z:\?]+)[\s\)]') 91defineMacro = re.compile(r'\(defmacro\*?-public\s+([-><a-zA-Z:\?]+)[\s\)]') 92defineVar = re.compile(r'\((?:define\*?|define-safe)-public\s+([-><a-zA-Z:\?]+)[\s\)]') 93startWithLy = re.compile(r"(ly:[-><a-zA-Z:\?]+)[\s\)]") 94 95 96schemeDataPath = os.path.join(os.path.split(__file__)[0], '_scheme_data.py') 97 98def main(): 99 with open(schemeDataPath, "w") as f: 100 f.write("#generated by makeschemedata.py\n\nversion=\"{}\"\n\n".format(VERSION)) 101 102 guileWords = [] 103 for m in guilePat.finditer(guilePage.decode('utf-8')): 104 if m.group(2) not in GUILE_IGNONED_TYPE: 105 proc = m.group(1) 106 if not proc.startswith('gds-'): 107 guileWords.append(replace(proc)) 108 guileWords += GUILE_OTHER_WORDS 109 110 111 lyFunctions = [] 112 lyVars = [] 113 lyCons = [] 114 for word in lyFunctionPat.finditer(lyFunctionPage.decode('utf-8')): 115 lyFunctions.append(replace(word.group(1))) 116 117 for filename in os.listdir(SCM_PATH): 118 path = os.path.join(SCM_PATH, filename) 119 with open(path) as inp: 120 text = inp.read() 121 for m in defineFunc.finditer(text): 122 lyFunctions.append(m.group(1)) 123 124 for m in defineMacro.finditer(text): 125 lyFunctions.append(m.group(1)) 126 127 for m in startWithLy.finditer(text): 128 lyFunctions.append(m.group(1)) 129 130 for m in defineVar.finditer(text): 131 word = m.group(1) 132 if word.isupper(): 133 lyCons.append(word) 134 else: 135 lyVars.append(word) 136 137 for word in lyFunctions: 138 if word in lyVars: 139 lyVars.remove(word) 140 141 lyVars.remove('parser') 142 143 writeList(f, 'scheme_keywords', guileWords) 144 writeList(f, 'scheme_functions', lyFunctions) 145 writeList(f, 'scheme_variables', lyVars) 146 writeList(f, 'scheme_constants', lyCons) 147 148 149if __name__ == "__main__": 150 main() 151 152