LILYPONDPREFIX -> LILYPOND_DATADIR
[lilypad-macos.git] / LilyPond.py
blobcbc1f167e59c2f839e7773396bb489ff31d3d2cd
1 """LilyPond.py -- A minimal Document-based Cocoa application."""
3 from PyObjCTools import NibClassBuilder, AppHelper
4 from Foundation import NSBundle, NSURL
5 from AppKit import NSWorkspace, NSDocumentController, NSDocument
6 import AppKit
8 NibClassBuilder.extractClasses("TinyTinyDocument")
10 import URLHandlerClass
11 import subprocess
12 import os
13 import glob
14 import string
15 import re
16 import urllib
18 from ProcessLog import ProcessLogWindowController
20 firstStart = True
21 debug = False
23 # utility functions
24 def open_url (url):
25 workspace = NSWorkspace.sharedWorkspace ()
27 nsurl = NSURL.URLWithString_ (url)
28 workspace.openURL_ (nsurl)
30 def lily_version ():
31 bundle = NSBundle.mainBundle ()
32 appdir = NSBundle.mainBundle().bundlePath()
33 share = appdir + '/Contents/Resources/share/lilypond'
35 if not os.path.exists (share):
36 share = os.environ['HOME'] + '/Desktop/LilyPond.app/Contents/Resources/share/lilypond'
38 pattern = share + '/[0-9]*'
40 versions = glob.glob (pattern)
41 version = '2.8.0'
42 if versions:
43 version = versions[0]
44 version = os.path.split(version)[1]
46 return tuple (string.split (version, '.'))
48 def google_lilypond (str):
49 (maj,min,pat) = lily_version ()
51 url = '%s site:lilypond.org v%s.%s' % (str, maj, min)
52 url = re.sub (' ', '+', url)
53 url = urllib.quote (url, safe='+')
54 url = 'http://www.google.com/search?q=%s' % url
55 open_url (url)
58 # class defined in TinyTinyDocument.nib
59 class TinyTinyDocument(NibClassBuilder.AutoBaseClass):
60 # the actual base class is NSDocument
61 # The following outlets are added to the class:
62 # textView
64 startupPath = None # fallback if instance has no startupPath.
65 def init (self):
66 self = NSDocument.init (self)
67 self.processLogWindowController = None
68 return self
70 def windowNibName(self):
71 return "TinyTinyDocument"
73 def readFromFile_ofType_(self, path, tp):
74 if self.textView is None:
75 # we're not yet fully loaded
76 self.startupPath = path
77 else:
78 # "revert"
79 self.readFromUTF8(path)
81 return True
83 def writeToFile_ofType_(self, path, tp):
84 f = file(path, "w")
85 text = self.textView.string()
86 f.write(text.encode("utf8"))
87 f.close()
89 return True
91 def windowControllerDidLoadNib_(self, controller):
92 global firstStart
93 if self.startupPath:
94 self.readFromUTF8 (self.startupPath)
95 elif firstStart:
96 appdir = NSBundle.mainBundle().bundlePath()
97 prefix = appdir + "/Contents/Resources"
98 self.readFromUTF8 (prefix + '/Welcome-to-LilyPond-MacOS.ly')
100 firstStart = False
102 def readFromUTF8(self, path):
103 f = file(path)
104 text = unicode(f.read(), "utf8")
105 f.close()
106 self.textView.setString_(text)
108 def compileFile_ (self, sender):
109 if 0:
110 self.saveDocumentWithDelegate_didSaveSelector_contextInfo_ (self,
111 "compileDidSaveSelector:",
112 None)
113 if self.fileName():
114 self.compileMe ()
115 else:
116 self.saveDocument_ (None)
118 def updateSyntax_(self, sender):
119 if self.fileName():
120 self.updateMySyntax ()
121 else:
122 self.saveDocument_ (None)
124 def processLogClosed_ (self, data):
125 self.processLogWindowController = None
127 def createProcessLog (self):
128 if not self.processLogWindowController:
129 wc = ProcessLogWindowController()
130 self.processLogWindowController = wc
131 center = NSWorkspace.sharedWorkspace().notificationCenter()
132 notification = AppKit.NSWindowWillCloseNotification
133 # center.addObserver_selector_name_object_(self, "processLogClosed:",
134 # notification,
135 # wc.window ())
137 wc.close_callback = self.processLogClosed_
138 else:
139 self.processLogWindowController.showWindow_ (None)
141 def compileDidSaveSelector_ (doc, didSave, info):
142 print "I'm here"
143 if didSave:
144 doc.compileMe ()
146 def revert_ (self, sender):
147 self.readFromUTF8 (self.fileName ())
149 def updateMySyntax (self):
150 env = os.environ.copy()
151 bundle = NSBundle.mainBundle ()
152 appdir = NSBundle.mainBundle().bundlePath()
153 prefix = appdir + '/Contents/Resources'
154 env['LILYPOND_DATADIR'] = prefix + '/share/lilypond/current'
156 self.writeToFile_ofType_(self.fileName (), None)
157 binary = prefix + '/bin/convert-ly'
159 pyproc = subprocess.Popen ([binary, '-e', self.fileName ()],
160 env = env,
161 stderr = subprocess.STDOUT,
162 stdout = subprocess.PIPE,
164 self.createProcessLog ()
165 wc = self.processLogWindowController
166 wc.setWindowTitle_ ('convert-ly -- ' + self.fileName())
167 wc.runProcessWithCallback (pyproc, self.revert_)
169 def compileMe (self):
170 bundle = NSBundle.mainBundle ()
171 try:
172 appdir = os.environ['LILYPOND_DEBUG_APPDIR']
173 except KeyError:
174 appdir = NSBundle.mainBundle().bundlePath()
175 executable = appdir + '/Contents/Resources/bin/lilypond'
176 args = [executable]
177 if debug:
178 args += ['--verbose']
179 args += [self.fileName()]
180 dest = os.path.split (self.fileName())[0]
181 call = subprocess.Popen (executable = executable,
182 args = args,
183 cwd = dest,
184 stdout = subprocess.PIPE,
185 stderr = subprocess.STDOUT,
186 shell = False)
189 self.createProcessLog ()
190 wc = self.processLogWindowController
191 wc.setWindowTitle_ ('LilyPond -- ' + self.fileName())
192 wc.runProcessWithCallback (call, self.open_pdf)
194 def open_pdf (self, data):
195 pdf_file = os.path.splitext (self.fileName())[0] + '.pdf'
196 if os.path.exists (pdf_file):
197 b = '/usr/bin/open'
198 args = [b, pdf_file]
199 os.spawnv (os.P_NOWAIT, b, args)
201 def contextHelp_ (self, sender):
202 tv = self.textView
203 r = tv.selectedRange ()
205 if r.length == 0:
206 (maj,min,pat) = lily_version ()
207 open_url ('http://lilypond.org/doc/v%s.%s' % (maj, min))
208 else:
209 substr = tv.string()[r.location:r.location + r.length]
210 google_lilypond (substr)
213 if __name__ == "__main__":
214 AppHelper.runEventLoop()