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
16 from ProcessLog
import ProcessLogWindowController
23 workspace
= NSWorkspace
.sharedWorkspace ()
25 nsurl
= NSURL
.URLWithString_ (url
)
26 workspace
.openURL_ (nsurl
)
29 prefix
= getLilypondDirectory ()
30 executable
= getLilypondDirectory () + '/bin/lilypond'
33 call
= subprocess
.Popen (executable
= executable
,
35 stdout
= subprocess
.PIPE
,
36 stderr
= subprocess
.STDOUT
,
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
54 def getLilypondDirectory ():
55 bundle
= NSBundle
.mainBundle ()
57 appdir
= os
.environ
['LILYPOND_DEBUG_APPDIR']
59 appdir
= NSBundle
.mainBundle ().bundlePath ()
61 appdir
+= '/Contents/Resources'
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:
70 textView
= objc
.IBOutlet ()
72 startupPath
= None # fallback if instance has no startupPath.
74 self
= super (TinyTinyDocument
, self
).init ()
75 self
.processLogWindowController
= None
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
87 self
.readFromUTF8 (path
)
91 def writeToFile_ofType_ (self
, path
, tp
):
93 text
= self
.textView
.string ()
94 f
.write (text
.encode ("utf8"))
99 def windowControllerDidLoadNib_ (self
, controller
):
102 self
.readFromUTF8 (self
.startupPath
)
104 prefix
= getLilypondDirectory ()
105 self
.readFromUTF8 (prefix
+ '/Welcome-to-LilyPond-MacOS.ly')
109 def readFromUTF8 (self
, path
):
111 text
= unicode (f
.read (), "utf8")
113 self
.textView
.setString_ (text
)
115 def compileFile_ (self
, sender
):
116 # self.saveDocumentWithDelegate_didSaveSelector_contextInfo_ (self,
117 # "compileDidSaveSelector:",
122 self
.saveDocument_ (None)
124 def updateSyntax_ (self
, sender
):
126 self
.updateMySyntax ()
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:",
143 wc
.close_callback
= self
.processLogClosed_
145 self
.processLogWindowController
.showWindow_ (None)
147 # @objc.signature ('v@:@cv')
148 # def compileDidSaveSelector_ (self, doc, didSave, info):
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 ()],
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'
179 args
+= ['--verbose']
180 args
+= [self
.fileName ()]
181 dest
= os
.path
.split (self
.fileName ())[0]
182 call
= subprocess
.Popen (executable
= executable
,
185 stdout
= subprocess
.PIPE
,
186 stderr
= subprocess
.STDOUT
,
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
):
200 os
.spawnv (os
.P_NOWAIT
, b
, args
)
202 def contextHelp_ (self
, sender
):
204 r
= tv
.selectedRange ()
207 (maj
,min,pat
) = lily_version ()
208 open_url ('http://lilypond.org/doc/v%s.%s' % (maj
, min))
210 substr
= tv
.string ()[r
.location
:r
.location
+ r
.length
]
211 google_lilypond (substr
)
214 if __name__
== "__main__":
215 AppHelper
.runEventLoop()