MacRuby рдкрд░ рдПрдиреАрдореЗ рд╡реЙрд▓рдкреЗрдкрд░ рдбрд╛рдЙрдирд▓реЛрдбрд░ рд▓рд┐рдЦрдирд╛

рджрд┐рд▓рдЪрд╕реНрдк рдбреЗрд╕реНрдХрдЯреЙрдк рд╡реЙрд▓рдкреЗрдкрд░ рдХреА рдЦреЛрдЬ рдореЗрдВ theotaku.com рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рджреЗрдЦрддреЗ рд╣реБрдП, рдореИрдВрдиреЗ рдЦреБрдж рдХреЛ рдпрд╣ рд╕реЛрдЪрдХрд░ рдкрдХрдбрд╝рд╛ рдХрд┐ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рд▓рд┐рдЦрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдЬреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдореЗрд░реЗ рдмрдЬрд╛рдп рд╡реЙрд▓рдкреЗрдкрд░ рдХреЛ рдЯреИрдЧ рдХрд░рдХреЗ рдЦреБрдж рдХреЛ рдЯреИрдЧ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рддрдереНрдп рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд┐ рдореИрдВ рдореБрдЦреНрдп рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд░реВрдк рдореЗрдВ рдореИрдХ рдУрдПрд╕ рдПрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рднреА рдЗрд╕ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЗ рд▓рд┐рдП рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдХреЛрдХреЛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣реЛрдирд╛ рд╡рд╛рдВрдЫрдиреАрдп рд╣реИред рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ, рдореИрдВ рдпрд╣ рд╕рдм рдЬрд╛рд╡рд╛ рдореЗрдВ рдирд╣реАрдВ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред рдмреЗрд╢рдХ рдХрдИ рд╡рд┐рдХрд▓реНрдк рдереЗ, рд▓реЗрдХрд┐рди рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдореИрдВ рдХреБрдЫ рдФрд░ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдФрд░ рдЙрд╕реА рд╕рдордп рдХреБрдЫ рдирдпрд╛ рд╕реАрдЦрддрд╛ рдерд╛ред рдореБрдЭреЗ рддреБрд░рдВрдд рдореИрдХрд░рд╛рдмреА рдФрд░ рдХреЛрдХреЛ рдХреЗ рд╕рд╛рде рдЗрд╕рдХреЗ рдШрдирд┐рд╖реНрда рдПрдХреАрдХрд░рдг рдХреА рдпрд╛рдж рдЖ рдЧрдИред рдЗрд╕ рд╡рд┐рдЪрд╛рд░ рдХреЗ рд╕рд╛рде, рдореИрдВ рддреБрд░рдВрдд http://www.macruby.org/ рдкрд░ рдЪрдврд╝ рдЧрдпрд╛ рдФрд░ рдирд╡реАрдирддрдо рд╕реНрдерд┐рд░ рд╕рдВрд╕реНрдХрд░рдг 0.10 рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ред рд╕реНрдерд╛рдкрдирд╛ рдХреЗ рдмрд╛рдж, рдореИрдВрдиреЗ рдЕрдкрдирд╛ рдкрд╕рдВрджреАрджрд╛ Xcode рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдФрд░ AnimeWallpaperDownloader рдирд╛рдордХ рдПрдХ рдирдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ

рд╣рдорд╛рд░реЗ MacRuby рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдХрдИ рдлрд╛рдЗрд▓реЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ рдЬреЛ Xcode рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрдирд╛рддрд╛ рд╣реИред рдкрд╣рд▓реА рдлрд╝рд╛рдЗрд▓ main.m рд╣реИ рдЬреЛ рдмрд╕ MacRuby рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ rb_main.rb рдЪрд▓рд╛рддреА рд╣реИ
#import <Cocoa/Cocoa.h> #import <MacRuby/MacRuby.h> int main(int argc, char *argv[]) { return macruby_main("rb_main.rb", argc, argv); } 

rb_main.rb рдПрдХ рдХрд╛рдлреА рд╕рд░рд▓ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИ, рдпрд╣ рдЕрдиреНрдп рд╕рднреА рд░реВрдмреА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рд▓реЛрдб рдХрд░рддреА рд╣реИ рдФрд░ рдЪрд▓рддреА рд╣реИ
NSApplicationMain
 framework 'Cocoa' # Loading all the Ruby project files. main = File.basename(__FILE__, File.extname(__FILE__)) dir_path = NSBundle.mainBundle.resourcePath.fileSystemRepresentation Dir.glob(File.join(dir_path, '*.{rb,rbo}')).map { |x| File.basename(x, File.extname(x)) }.uniq.each do |path| if path != main require(path) end end # Starting the Cocoa main loop. NSApplicationMain(0, nil) 

рдЕрдВрддрд┐рдо рдлрд╝рд╛рдЗрд▓ рдЬреЛ рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╣реА рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрдирд╛рдИ рд╣реИ, AppDelegate.rb рд╣реИ , рдЬреЛ NSApplicationDelegate рдХреА рднреВрдорд┐рдХрд╛ рдирд┐рднрд╛рддрд╛ рд╣реИред рдЗрд╕рдореЗрдВ рдПрдХ рдЦрд╛рд▓реА ApplicationDidFinishLaunching рд╡рд┐рдзрд┐ рд╣реИ рдЬрд┐рд╕реЗ рддрдм рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рд╣рдорд╛рд░рд╛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рд╢реБрд░реВ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
 class AppDelegate attr_accessor :window def applicationDidFinishLaunching(a_notification) # Insert code here to initialize your application end end 

рдпрд╣рд╛рдБ attr_accessor: рд╡рд┐рдВрдбреЛ IBOutlet * рд╡рд┐рдВрдбреЛ рдХреА рднреВрдорд┐рдХрд╛ рдирд┐рднрд╛рддрд╛ рд╣реИ рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╣рдорд╛рд░реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреА рд╡рд┐рдВрдбреЛ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ

MainMenu.xib рдЦреЛрд▓реЗрдВ рдФрд░ рд╣рдорд╛рд░реЗ рд╡реЙрд▓рдкреЗрдкрд░ рдбрд╛рдЙрдирд▓реЛрдбрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рдПрдВ


рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдорд╛рд░реЗ AppDelegate рдореЗрдВ рддрд░реАрдХреЗ рдФрд░ рдЖрдЙрдЯрд▓реЗрдЯ рдЬреЛрдбрд╝реЗрдВ
 class AppDelegate attr_accessor :window attr_accessor :tags attr_accessor :size attr_accessor :number attr_accessor :saveInto attr_accessor :startButton attr_accessor :output attr_accessor :downprogress attr_accessor :downloader attr_accessor :img def applicationDidFinishLaunching(a_notification) @startButton.setEnabled(false) @downprogress.setStringValue('') @output.setStringValue('') @saveInto.stringValue = NSHomeDirectory()+"/Pictures" end def windowWillClose(a_notification) NSApp.terminate(self) end def controlTextDidChange(notification) sender = notification.object if sender == tags @startButton.setEnabled(@tags.stringValue.size > 0) elsif sender == number begin @number.setIntValue(@number.intValue) if @number.intValue < 0 @number.setIntValue(-@number.intValue) elsif @number.intValue == 0 @number.setIntValue(20) end rescue @number.setIntValue(20) end end end def browse(sender) dialog = NSOpenPanel.openPanel dialog.canChooseFiles = false dialog.canChooseDirectories = true dialog.allowsMultipleSelection = false if dialog.runModalForDirectory(nil, file:nil) == NSOKButton @saveInto.stringValue = dialog.filenames.first end end def startStop(sender) if @downloader == nil @downloader = Downloader.new(@tags.stringValue,@size.selectedItem.title,@number.stringValue,@saveInto.stringValue,self) @downloader.start @startButton.setTitle("Stop Download") else @downloader.stop @downloader = nil @startButton.setTitle("Start Download") end end def changeImage(file) @img.setImage(NSImage.alloc.initByReferencingFile(file)) end def clearStatus @downprogress.setStringValue('') end def setStatus(i,m) @downprogress.setStringValue("Downloading "+i.to_s()+" of "+m.to_s()) end def setStatusEnd(i) @downprogress.setStringValue("Downloaded "+i.to_s()+" wallpapers") end def puts(val) $stdout.puts val @output.setStringValue(val) end def stopped @startButton.setTitle("Start Download") down = @downloader @downloader = nil down.stop end end 

рдпрд╣рд╛рдБ рд╕рдм рдХреБрдЫ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИред WindowWillClose рдФрд░ controlTextDidChange рддрд░реАрдХреЗ рдкреНрд░реЛрдЧреНрд░рд╛рдо рд╡рд┐рдВрдбреЛ рдФрд░ рдкрд╣рд▓реЗ рдЯреЗрдХреНрд╕реНрдЯ рдлрд╝реАрд▓реНрдб рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рддрд░реАрдХреЗ рд╣реИрдВ (рдЖрдк рдЯреИрдЧ рджрд░реНрдЬ рдХрд░рдиреЗ рддрдХ рдХреБрдЫ рднреА рдбрд╛рдЙрдирд▓реЛрдб рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ)ред
рдмреНрд░рд╛рдЙрдЬрд╝ рд╡рд┐рдзрд┐ рдЙрд╕ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЛ рдЪреБрдирдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдбрд╛рдпрд▓реЙрдЧ рдмреЙрдХреНрд╕ рдЦреЛрд▓рддреА рд╣реИ рдЬрд╣рд╛рдВ рд╣рдо рдЕрдкрдиреЗ рд╡реЙрд▓рдкреЗрдкрд░ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВ, рд╣рдо рдЗрд╕реЗ рдмреНрд░рд╛рдЙрдЬ рдмрдЯрди рд╕реЗ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред StartStop рд╡рд┐рдзрд┐ рдХреВрджрдирд╛ рд╢реБрд░реВ рдХрд░рддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕реЗ рд╕реНрдЯрд╛рд░реНрдЯ рдбрд╛рдЙрдирд▓реЛрдб рдмрдЯрди рд╕реЗ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рд╢реЗрд╖ рд╡рд┐рдзрд┐рдпрд╛рдВ рд╕рд╣рд╛рдпрдХ рд╣реИрдВ рдФрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдбрд╛рдЙрдирд▓реЛрдбрд░ рд╡рд░реНрдЧ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рд▓рд┐рдВрдХ рдЦреЛрдЬрдиреЗ рдФрд░ рд╡реЙрд▓рдкреЗрдкрд░ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░реЗрдВрдЧреЗ

 require 'thread' require 'net/http' class Downloader attr_accessor :tags, :size, :number, :saveTo, :thread attr_accessor :app, :exit def initialize(tags, size, number, saveTo, app) @tags = tags.sub(' ','_') @size = size == 'Any' ? '' : size.sub('x','_') @number = number @saveTo = saveTo @app = app @exit = false end def getIndexPage(page) walls = {} url = 'http://www.theotaku.com/wallpapers/tags/'+tags+'/?sort_by=&resolution='+size+'&date_filter=&category=&page='+page.to_s() @app.puts 'getting index for page: '+page.to_s() @app.puts url response = Net::HTTP.get_response(URI.parse(url)) res = response.body res.each_line { |line| f = line.index('wallpapers/view') while f != nil b = line.rindex('"',f) e = line.index('"',b+1) u = line[b+1,eb].gsub('"','') walls[u] = u line = line.sub(u,'') f = line.index('wallpapers/view') end } @app.puts 'got '+walls.size.to_s()+' wallpapers' return walls.keys end def downloadWall(url) @app.puts 'downloading '+url response = Net::HTTP.get_response(URI.parse(url)) res = response.body b = res.index('src',res.rindex('wall_holder'))+5 e = res.index('"',b) img = res[b,eb] self.downloadFile(img) end def downloadFile(url) name = url[url.rindex('/')+1,1000] if File.exists?(@saveTo+'/'+name) @app.puts 'wallpaper already saved '+name @app.changeImage(@saveTo+'/'+name) else @app.puts 'downloading file '+url response = Net::HTTP.get_response(URI.parse(url)) open(@saveTo+'/'+name, 'wb') { |file| file.write(response.body) } @app.puts 'wallpaper saved '+name @app.changeImage(@saveTo+'/'+name) end end def getWallUrl(i,url,size) sizes = {} i = i+1 @app.puts 'getting '+url+' sizes' response = Net::HTTP.get_response(URI.parse(url)) res = response.body res.each_line { |line| f = line.index('wallpapers/download') while f != nil b = line.rindex('\'',f) e = line.index('\'',b+1) u = line[b+1,eb] u = u.gsub('\'','') sizes[u] = u line = line.sub(u,'') f = line.index('wallpapers/download') end } sizef = @size.sub('_','-by-') sizes = sizes.keys() if sizef == '' maxi = 0 max = 0 i = 0 sizes.each { |s| f = s.rindex('/') l = s[f+1,100] l = l.sub('-by-',' ') l = l.split(' ') rs = l[0].to_i()*l[1].to_i() if rs > max maxi = i max = rs end i = i+1 } return sizes[maxi] else sizes.each { |s| if s =~ /#{Regexp.escape(sizef)}$/ return s end } end return sizes[0] end def start @thread = Thread.new { @app.puts "Download started" begin i = 0 p = 1 @app.clearStatus while i < @number.to_i() and not @exit w = self.getIndexPage(p) if w.size == 0 break end w.each { |w| wallu = self.getWallUrl(i,w,self.size) if wallu != nil @app.setStatus(i+1,@number.to_i()) self.downloadWall(wallu) i = i+1 if i >= @number.to_i() or @exit break end end } p = p+1 end @app.puts "" @app.setStatusEnd(i) rescue => e puts e end @app.stopped } end def stop begin @app.puts "Download stopped" if @thread.alive? if @thread == Thread.current Thread.exit(0) else @exit = true end end rescue => e puts e end end end 

рдХреНрдпрд╛ рдПрдХ рд╡рд┐рд╢рд╛рд▓ рд╡рд░реНрдЧ рд╕рдЪ рд╣реИ? рд╣рд╛рдВ, рдпрд╣ рддрд░реНрдХ рд╕реЗ рднрд░рд╛ рд╣реБрдЖ рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдм рдХреБрдЫ рдХрд╛рдлреА рддреБрдЪреНрдЫ рд╣реИред
рдкреНрд░рд╛рд░рдВрдн рд╡рд┐рдзрд┐ рдмрд╕ рдПрдХ рдЕрд▓рдЧ рдзрд╛рдЧрд╛ рд╢реБрд░реВ рдХрд░рддреА рд╣реИ рдЬреЛ рд╣рдорд╛рд░реЗ рд╡реЙрд▓рдкреЗрдкрд░ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдЧреА, рдЗрд╕реЗ рд░реЛрдХрддреА рд╣реИред рддрд░реАрдХреЗ getIndexPage , getWallUrl , downloadWall forotaku.com рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реИрдВ рдФрд░ рдЗрдирдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рддрд░реНрдХ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рддреБрдЪреНрдЫ рд╣реИрдВ рдФрд░ рдЯреИрдЧ рджреНрд╡рд╛рд░рд╛ рд╡реЙрд▓рдкреЗрдкрд░ рдХреА рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рд╡рд╛рдВрдЫрд┐рдд рдЖрдХрд╛рд░ рдХреЗ рд╡рд╛рдВрдЫрд┐рдд рд▓рд┐рдВрдХ рдХрд╛ рдЪрдпрди рдХрд░реЗрдВ рдФрд░ рдЗрди рд╡реЙрд▓рдкреЗрдкрд░ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ

рдкрд░рд┐рдгрд╛рдо рд░рд╡рд┐рд╡рд╛рд░ рдХреА рд╢рд╛рдо, рдЖрддреНрдо-рд╕рдВрддреБрд╖реНрдЯрд┐ рдХреА рдПрдХ рдЕрдЪреНрдЫреА рднрд╛рд╡рдирд╛, рдФрд░ рдореИрдХ рдУрдПрд╕ рдПрдХреНрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╡рд┐рдХрд╛рд╕ рдордВрдЪ рдХреЗ рд░реВрдк рдореЗрдВ рдореИрдХрд░рд╛рдмреА рдХреЗ рднрд╡рд┐рд╖реНрдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рджрд┐рд▓рдЪрд╕реНрдк рд╡рд┐рдЪрд╛рд░ рднреА рдмрд┐рддрд╛рдП рдЧрдП рдереЗред рдмреЗрд╢рдХ, рдПрдХ рд░реЗрдХ рдерд╛ рдФрд░ рдХреБрдЫ рдЪреАрдЬреЗрдВ рдирд╣реАрдВ рдХреА рдЬрд╛ рд╕рдХрддреА рдереАрдВ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ MacRuby рдордВрдЪ рд▓реЛрдХрдкреНрд░рд┐рдпрддрд╛ рд╣рд╛рд╕рд┐рд▓ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рд░рд╣рд╛ рд╣реИ рдФрд░ рдЗрд╕рдХрд╛ рднрд╡рд┐рд╖реНрдп рдЙрдЬреНрдЬреНрд╡рд▓ рд╣реИред

рдЖрдк рдпрд╣рд╛рдВ рдкрд░рд┐рдгрд╛рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЖрдк рдпрд╣рд╛рдВ рд╕реЗ рддреИрдпрд╛рд░ рдирд┐рд░реНрдорд╛рдг рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдЖрдкрдХреЗ рдкрд╛рд╕ MacRuby рд╕реНрдерд╛рдкрд┐рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП)

рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж

рдЕрд▓рд╡рд┐рджрд╛ рдПрдирдЖрдИрдЖрдИ



UPD: рдкрд╛рд░реНрд╕рд░ рдХреЛ рд░рд┐рдлрд▓реЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрд╕реНрдЯреЗ рдХрд╛ рд╢реБрдХреНрд░рд┐рдпрд╛ , рдпрд╣ рд╕рд┐рд░реНрдл рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд▓рдЧ рд░рд╣рд╛ рд╣реИ, рдЧрд┐рддреБрдм рдкрд░ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рджреЗрдЦреЗрдВ

Source: https://habr.com/ru/post/In133739/


All Articles