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
8 NibClassBuilder
.extractClasses("TinyTinyDocument")
10 import URLHandlerClass
18 from ProcessLog
import ProcessLogWindowController
25 workspace
= NSWorkspace
.sharedWorkspace ()
27 nsurl
= NSURL
.URLWithString_ (url
)
28 workspace
.openURL_ (nsurl
)
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
)
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
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:
64 startupPath
= None # fallback if instance has no startupPath.
66 self
= NSDocument
.init (self
)
67 self
.processLogWindowController
= None
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
79 self
.readFromUTF8(path
)
83 def writeToFile_ofType_(self
, path
, tp
):
85 text
= self
.textView
.string()
86 f
.write(text
.encode("utf8"))
91 def windowControllerDidLoadNib_(self
, controller
):
94 self
.readFromUTF8 (self
.startupPath
)
96 appdir
= NSBundle
.mainBundle().bundlePath()
97 prefix
= appdir
+ "/Contents/Resources"
98 self
.readFromUTF8 (prefix
+ '/Welcome-to-LilyPond-MacOS.ly')
102 def readFromUTF8(self
, path
):
104 text
= unicode(f
.read(), "utf8")
106 self
.textView
.setString_(text
)
108 def compileFile_ (self
, sender
):
110 self
.saveDocumentWithDelegate_didSaveSelector_contextInfo_ (self
,
111 "compileDidSaveSelector:",
116 self
.saveDocument_ (None)
118 def updateSyntax_(self
, sender
):
120 self
.updateMySyntax ()
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:",
137 wc
.close_callback
= self
.processLogClosed_
139 self
.processLogWindowController
.showWindow_ (None)
141 def compileDidSaveSelector_ (doc
, didSave
, info
):
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 ()],
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 ()
172 appdir
= os
.environ
['LILYPOND_DEBUG_APPDIR']
174 appdir
= NSBundle
.mainBundle().bundlePath()
175 executable
= appdir
+ '/Contents/Resources/bin/lilypond'
178 args
+= ['--verbose']
179 args
+= [self
.fileName()]
180 dest
= os
.path
.split (self
.fileName())[0]
181 call
= subprocess
.Popen (executable
= executable
,
184 stdout
= subprocess
.PIPE
,
185 stderr
= subprocess
.STDOUT
,
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
):
199 os
.spawnv (os
.P_NOWAIT
, b
, args
)
201 def contextHelp_ (self
, sender
):
203 r
= tv
.selectedRange ()
206 (maj
,min,pat
) = lily_version ()
207 open_url ('http://lilypond.org/doc/v%s.%s' % (maj
, min))
209 substr
= tv
.string()[r
.location
:r
.location
+ r
.length
]
210 google_lilypond (substr
)
213 if __name__
== "__main__":
214 AppHelper
.runEventLoop()