root/lang/ruby/misc/openmenu.rb @ 1026

Revision 587, 6.1 kB (checked in by cho45, 7 years ago)

lang/ruby/misc/openmenu.rb:

注意書きとライセンスを追記

  • Property svn:executable set to *
Line 
1#!/usr/bin/env ruby
2#
3# あるディレクトリ以下のファイルへアクセスするための
4# ステータスバーアイコンを出す。
5#
6# growlserver.rb と一緒につかって URL をさっさと開くために書いた
7# growlserver.rb -c ~/openmenu して ./openmenu.rb
8#
9# 古いファイルを削除していくので注意
10#
11# License: Public Domain
12
13require 'osx/cocoa'
14require 'pathname'
15
16include OSX
17
18class Test < NSObject
19
20        MAKE_ALL_FILE_AS_CHECKED   = "Make All Files as Checked"
21        MAKE_ALL_FILE_AS_UNCHECKED = "Make All Files as Unchecked"
22        OPEN_UNCHECKED_FILES       = "Open Unchecked Files"
23        QUIT                       = "Quit"
24
25        def initWithDirectory(dir)
26                init
27                @dir = Pathname.new dir
28                self
29        end
30
31        def applicationDidFinishLaunching(aNotification)
32                # menu items exclude 'quit'
33                @items  = []
34                # already opened items
35                @opened = []
36
37                # create root menu
38                @menu = NSMenu.alloc.initWithTitle "OpenMenu"
39                @menu.setDelegate self
40        #       @menu.setAutoenablesItems false
41
42                # add separator and quit item
43                @menu.addItem NSMenuItem.separatorItem
44                @menu.objc_send :addItemWithTitle, MAKE_ALL_FILE_AS_CHECKED, :action, "checkall_", :keyEquivalent, ""
45                @menu.objc_send :addItemWithTitle, OPEN_UNCHECKED_FILES, :action, "openunchecked_", :keyEquivalent, ""
46                @menu.addItem NSMenuItem.separatorItem
47                @menu.objc_send :addItemWithTitle, QUIT, :action, "quit_", :keyEquivalent, ""
48
49                icon, acon = DATA.readlines("").map { |str|
50                        str = str.unpack("m")[0]
51                        str = NSData.objc_send :dataWithBytes, str, :length
52                        NSImage.alloc.initWithData str
53                }
54
55                # create status item
56                @sitem = NSStatusBar.systemStatusBar.statusItemWithLength -1
57                @sitem.setTarget self
58                @sitem.setAction "itemclicked_"
59                @sitem.setToolTip "OpenMenu"
60                @sitem.setImage icon
61                @sitem.setAlternateImage acon
62                @sitem.setHighlightMode true
63                #@sitem.setMenu menu
64        end
65
66        def itemclicked(sender)
67                # remove all items
68                @menu.removeItem @items.pop until @items.empty?
69                files.each do |tooltip, title|
70                        item = @menu.objc_send :insertItemWithTitle, title,
71                                                            :action, "menuclicked_",
72                                                     :keyEquivalent, "",
73                                                           :atIndex, 0
74                        img = NSWorkspace.sharedWorkspace.iconForFile tooltip
75                        img.setSize [16, 16]
76                        item.setImage img
77                        item.setToolTip tooltip
78                        item.setState NSOnState if @opened.include? tooltip
79                        @items << item
80                end
81                @sitem.popUpStatusItemMenu @menu
82                true
83        end
84
85        def menuclicked(sender)
86                file = sender.toolTip.to_s
87                @opened << file
88                @opened.reject! do |i|
89                        !File.exist? i
90                end
91                system('open', file)
92        end
93
94
95        def checkall(sender)
96                case sender.title.to_s
97                when MAKE_ALL_FILE_AS_CHECKED
98                        @items.each do |i|
99                                @opened << i.toolTip.to_s
100                        end
101                        sender.setTitle MAKE_ALL_FILE_AS_UNCHECKED
102                else
103                        @opened.clear
104                        sender.setTitle MAKE_ALL_FILE_AS_CHECKED
105                end
106        end
107
108        def openunchecked
109                @items.each do |i|
110                        menuclicked(i) unless @opened.include? i.toolTip.to_s
111                end
112        end
113
114        def quit
115                exit
116        end
117
118        def validateMenuItem(item)
119                case item.title.to_s
120                when OPEN_UNCHECKED_FILES
121                        !!(@items.collect {|i| i.toolTip.to_s } - @opened).length.nonzero?
122                else
123                        true
124                end
125        end
126
127        private
128        def files
129                fs = Pathname.glob(@dir + "*")
130                fs = fs.sort_by {|f| f.ctime }
131
132                ret = fs.last(10)
133                (fs - ret).each do |f|
134                        f.unlink
135                end
136                ret.collect! do |f|
137                        [f.to_s, f.basename(".*").to_s.gsub(":", "/")]
138                end
139                ret
140        end
141end
142
143require "optparse"
144dir = "#{ENV['HOME']}/openmenu"
145OptionParser.new do |opts|
146        opts.separator ""
147        opts.separator "Optional:"
148        opts.on('-c', "--url [DIR]", "(~/openmenu)") {|v| dir = v }
149        opts.parse!(ARGV)
150end
151
152app = NSApplication.sharedApplication
153app.setDelegate(Test.alloc.initWithDirectory(dir))
154
155trap('SIGINT') { exit }
156app.run
157
158__END__
159iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAACzGlDQ1BJQ0Mg
160UHJvZmlsZQAAeJx9kEtoE1EUhr87WgRpFTRWKQp3VbNoy9C6qC6Upta0VmIY
161U/tAkHRyk4ydTMY7k/jAhQjiRrC6FDc+cCUupQsXLoQuRAqKuhHBpVhBENyI
162xMUkzUirFwa+Oefe/5z/h45k3vddQ0LFC7WVTsmZ2Tm55Q0ddNEJkLcDfySb
163PQGQ932XdefnewTA2/6N+/89XXpmdg6EBBKliA8AifmIx4HEhdAPQZwBEnY5
164XwDhA306Z42CuAdsK8V4PsYFFdggngBHbF+HYOSA8bpdCkGsAqZXcDww9gLD
165hcCugHEPjJszs3MyWjOchMP7YNOrdm0ugCePYXdvu5bcA7umYWmoXfthIQDR
166vRIUhwYBEJ0p6PjUaPzohS134PftRuPXg0bj90PY9BFeuHZN15sZCfEaIh8A
167JNLKU9qxpZVOyayuFh1XxSLduB35jfRgyWrRvzjKBIBhuD8O01th8jrc/Qz7
168n8LOZ5DtgtxBjKu0vlBdDAFGq/4l7ZTKoRw0zUHZLwdNc0iO+L6r5Gi14tdC
169peWEZw/0ybzrSu2UymEgtQqUrqvCABW31vK7HehU3tQpoBeMogrGmizOFfJH
170J4EBEG8K6ugY0AdisegcmwCSwMuiPjYVsdjhhBO5iI3Dnps50WS8auZkpMmq
171H6asln5QPzXWqp/LH88CPSAOLVQnLaAbjOTlcm46YpG7XB7NNPk5s7goHDwU
172HhKLNCn68dFUKeLg4OKQRuGh0DgELGx40yUbY0maL3h8QeNwnhoKicVpUhmu
1739a0pSPOD+c18Z943H5lfF3tqyXbnmj7r2Cu3vpNFodd0m93mTpG+TZURXFxK
174KCprnoLYprHtit5iT1vJXrn1Xd3I/Iy5VLFJ/cyjCFhA41BH4RKgGIlN+1d6
175Cnf5yvM97VnvNi+dedu5fOWvrKrrXKk1V3//t+/F36s/zbABaFPXSTsAAAB3
176SURBVCjPrZFBFcAgDEO/DR4WcFYR4IT78ICNyekuMKCD28KF14Y0pPAnAkJC
177CLumo6AoSiaScbZ9oygV3yp+pfTXfqr5eXYXt54apBGSIUi/xINCsgrWg1gP
1786y/qnMf1UpRMIqOUXQ7j3N+oZpVi22MX8bSLIx4U5UEkYy3cDgAAAABJRU5E
179rkJggg==
180
181iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAACzGlDQ1BJQ0Mg
182UHJvZmlsZQAAeJx9kEtoE1EUhr87WgRpFTRWKQp3VbNoy9C6qC6Upta0VmIY
183U/tAkHRyk4ydTMY7k/jAhQjiRrC6FDc+cCUupQsXLoQuRAqKuhHBpVhBENyI
184xMUkzUirFwa+Oefe/5z/h45k3vddQ0LFC7WVTsmZ2Tm55Q0ddNEJkLcDfySb
185PQGQ932XdefnewTA2/6N+/89XXpmdg6EBBKliA8AifmIx4HEhdAPQZwBEnY5
186XwDhA306Z42CuAdsK8V4PsYFFdggngBHbF+HYOSA8bpdCkGsAqZXcDww9gLD
187hcCugHEPjJszs3MyWjOchMP7YNOrdm0ugCePYXdvu5bcA7umYWmoXfthIQDR
188vRIUhwYBEJ0p6PjUaPzohS134PftRuPXg0bj90PY9BFeuHZN15sZCfEaIh8A
189JNLKU9qxpZVOyayuFh1XxSLduB35jfRgyWrRvzjKBIBhuD8O01th8jrc/Qz7
190n8LOZ5DtgtxBjKu0vlBdDAFGq/4l7ZTKoRw0zUHZLwdNc0iO+L6r5Gi14tdC
191peWEZw/0ybzrSu2UymEgtQqUrqvCABW31vK7HehU3tQpoBeMogrGmizOFfJH
192J4EBEG8K6ugY0AdisegcmwCSwMuiPjYVsdjhhBO5iI3Dnps50WS8auZkpMmq
193H6asln5QPzXWqp/LH88CPSAOLVQnLaAbjOTlcm46YpG7XB7NNPk5s7goHDwU
194HhKLNCn68dFUKeLg4OKQRuGh0DgELGx40yUbY0maL3h8QeNwnhoKicVpUhmu
1959a0pSPOD+c18Z943H5lfF3tqyXbnmj7r2Cu3vpNFodd0m93mTpG+TZURXFxK
196KCprnoLYprHtit5iT1vJXrn1Xd3I/Iy5VLFJ/cyjCFhA41BH4RKgGIlN+1d6
197Cnf5yvM97VnvNi+dedu5fOWvrKrrXKk1V3//t+/F36s/zbABaFPXSTsAAACH
198SURBVCjPrVGxDcAgDOuXLP2Hibnn8ADcgJSBNXMrBK2AUEhhq6cIGydxtu1H
199HFKDRQ2HnJBK+JAy3GXQXUow+swkRrXXl32Q0G+ii6TrTeZ8plpoKAKLo0BD
200LQzOHdoHcuAzNAeaYdwCY5cHbVEa2SeHlHyY5PDiTJ+oehcfGP3ewqxuscYN
20171eoPQOMXygAAAAASUVORK5CYII=
Note: See TracBrowser for help on using the browser.