Revert "Fix percent-escape URI issue (hopefully)."
[lilypad-macos.git] / LilyPond.py
bloba20ed9b0ed809c1ae04ff111257c152d983033b0
1 """LilyPond.py -- A minimal Document-based Cocoa application."""
3 from PyObjCTools import AppHelper
4 from Foundation import *
5 from AppKit import NSWorkspace, NSDocumentController, NSDocument, NSMenu, NSLog
6 import AppKit
8 import URLHandlerClass
9 import subprocess
10 import os
11 import glob
12 import string
13 import re
14 import urllib
16 from ProcessLog import ProcessLogWindowController
18 firstStart = True
19 debug = False
21 # utility functions
22 def open_url (url):
23 workspace = NSWorkspace.sharedWorkspace ()
25 nsurl = NSURL.URLWithString_ (url)
26 workspace.openURL_ (nsurl)
28 def lily_version ():
29 prefix = getLilypondDirectory ()
30 executable = getLilypondDirectory () + '/bin/lilypond'
31 args = [executable]
32 args += ['--version']
33 call = subprocess.Popen (executable = executable,
34 args = args,
35 stdout = subprocess.PIPE,
36 stderr = subprocess.STDOUT,
37 shell = False)
39 (stdoutdata, stderrdata) = call.communicate ()
41 versionline = stdoutdata.splitlines ()[0]
42 version = versionline.split (' ')[2]
43 return tuple (version.split ('.'))
45 def google_lilypond (str):
46 (maj,min,pat) = lily_version ()
48 url = '%s site:lilypond.org v%s.%s' % (str, maj, min)
49 url = re.sub (' ', '+', url)
50 url = urllib.quote (url, safe='+')
51 url = 'http://www.google.com/search?q=%s' % url
52 open_url (url)
54 def getLilypondDirectory ():
55 bundle = NSBundle.mainBundle ()
56 try:
57 appdir = os.environ['LILYPOND_DEBUG_APPDIR']
58 except KeyError:
59 appdir = NSBundle.mainBundle ().bundlePath ()
61 appdir += '/Contents/Resources'
62 return appdir
65 # class defined in TinyTinyDocument.nib
66 class TinyTinyDocument (NSDocument):
67 # the actual base class is NSDocument
68 # The following outlets are added to the class:
69 # textView
70 textView = objc.IBOutlet ()
72 startupPath = None # fallback if instance has no startupPath.
73 def init (self):
74 self = super (TinyTinyDocument, self).init ()
75 self.processLogWindowController = None
76 return self
78 def windowNibName (self):
79 return "TinyTinyDocument"
81 def readFromFile_ofType_ (self, path, tp):
82 if self.textView is None:
83 # we're not yet fully loaded
84 self.startupPath = path
85 else:
86 # "revert"
87 self.readFromUTF8 (path)
89 return True
91 def writeToFile_ofType_ (self, path, tp):
92 f = file (path, "w")
93 text = self.textView.string ()
94 f.write (text.encode ("utf8"))
95 f.close ()
97 return True
99 def windowControllerDidLoadNib_ (self, controller):
100 global firstStart
101 if self.startupPath:
102 self.readFromUTF8 (self.startupPath)
103 elif firstStart:
104 prefix = getLilypondDirectory ()
105 self.readFromUTF8 (prefix + '/Welcome-to-LilyPond-MacOS.ly')
107 firstStart = False
109 def readFromUTF8 (self, path):
110 f = file (path)
111 text = unicode (f.read (), "utf8")
112 f.close ()
113 self.textView.setString_ (text)
115 def compileFile_ (self, sender):
116 # self.saveDocumentWithDelegate_didSaveSelector_contextInfo_ (self,
117 # "compileDidSaveSelector:",
118 # 0)
119 if self.fileName ():
120 self.compileMe ()
121 else:
122 self.saveDocument_ (None)
124 def updateSyntax_ (self, sender):
125 if self.fileName ():
126 self.updateMySyntax ()
127 else:
128 self.saveDocument_ (None)
130 def processLogClosed_ (self, data):
131 self.processLogWindowController = None
133 def createProcessLog (self):
134 if not self.processLogWindowController:
135 wc = ProcessLogWindowController ()
136 self.processLogWindowController = wc
137 center = NSWorkspace.sharedWorkspace ().notificationCenter ()
138 notification = AppKit.NSWindowWillCloseNotification
139 # center.addObserver_selector_name_object_ (self, "processLogClosed:",
140 # notification,
141 # wc.window ())
143 wc.close_callback = self.processLogClosed_
144 else:
145 self.processLogWindowController.showWindow_ (None)
147 # @objc.signature ('v@:@cv')
148 # def compileDidSaveSelector_ (self, doc, didSave, info):
149 # NSLog ("I'm here")
150 # if didSave:
151 # doc.compileMe ()
153 def revert_ (self, sender):
154 self.readFromUTF8 (self.fileName ())
156 def updateMySyntax (self):
157 env = os.environ.copy ()
158 prefix = getLilypondDirectory ()
159 localPython = NSBundle.mainBundle ().bundlePath () + '/Contents/MacOS/python'
160 env['LILYPOND_DATADIR'] = prefix + '/share/lilypond/current'
162 self.writeToFile_ofType_ (self.fileName (), None)
163 binary = prefix + '/bin/convert-ly'
165 pyproc = subprocess.Popen ([localPython, binary, '-e', self.fileName ()],
166 env = env,
167 stderr = subprocess.STDOUT,
168 stdout = subprocess.PIPE,
170 self.createProcessLog ()
171 wc = self.processLogWindowController
172 wc.setWindowTitle_ ('convert-ly -- ' + self.fileName ())
173 wc.runProcessWithCallback (pyproc, self.revert_)
175 def compileMe (self):
176 executable = getLilypondDirectory () + '/bin/lilypond'
177 args = [executable]
178 if debug:
179 args += ['--verbose']
180 args += [self.fileName ()]
181 dest = os.path.split (self.fileName ())[0]
182 call = subprocess.Popen (executable = executable,
183 args = args,
184 cwd = dest,
185 stdout = subprocess.PIPE,
186 stderr = subprocess.STDOUT,
187 shell = False)
190 self.createProcessLog ()
191 wc = self.processLogWindowController
192 wc.setWindowTitle_ ('LilyPond -- ' + self.fileName ())
193 wc.runProcessWithCallback (call, self.open_pdf)
195 def open_pdf (self, data):
196 pdf_file = os.path.splitext (self.fileName ())[0] + '.pdf'
197 if os.path.exists (pdf_file):
198 b = '/usr/bin/open'
199 args = [b, pdf_file]
200 os.spawnv (os.P_NOWAIT, b, args)
202 def contextHelp_ (self, sender):
203 tv = self.textView
204 r = tv.selectedRange ()
206 if r.length == 0:
207 (maj,min,pat) = lily_version ()
208 open_url ('http://lilypond.org/doc/v%s.%s' % (maj, min))
209 else:
210 substr = tv.string ()[r.location:r.location + r.length]
211 google_lilypond (substr)
214 if __name__ == "__main__":
215 AppHelper.runEventLoop()