- require "yaml"
- class Clip < Shoes::Widget
- attr_reader :content
- def initialize(content=nil)
- @content = content || app.clipboard.strip
- stack :margin => 5 do
- @border = border gainsboro
- @background = background lavender, :margin => 1
- @para = para @content
- click do |btn, left, top|
- app.clipboard = @content
- @para.stroke = firebrick
- timer(1) do
- @para.stroke = black
- remove if btn == 2
- end
- end
- end
- end
- end
- class Pasty < Shoes::Widget
- def initialize
- stack :margin => 15 do
- flow :margin => 5 do
- para link("Clear Pasty") { clear_pasty }, " | ",
- link("Clear Clipboard") { clear_clipboard }, " | ",
- link("Save") { save_clips }, " | ",
- link("Load") { load_clips }, " | ",
- link("Restart") { Shoes.visit __FILE__; close }, :align => "center"
- end
- stack :margin => 5 do
- background aliceblue, :margin => 1
- border lightblue
- @info = para "Ready.", :stroke => mediumblue, :emphasis => "italic"
- end
- flow :margin => 5 do
- @search = edit_line :width => 355
- para link("Search"){ search }, " | ",
- link("Clear"){ clear_search }
- end
- stack :margin_left => 150 do
- button("Paste!", :width => 200, :margin_top => 5) { paste }
- end
- @dropstack = stack
- load_clips
- end
- end
- def flash_message(msg, type=nil)
- @info.replace msg
- case type
- when :error then
- colorcode = red
- when :warning then
- colorcode = orange
- when :success then
- colorcode = green
- else
- colorcode = mediumblue
- end
- @info.style :stroke => colorcode
- timer(1) do
- @info.style :stroke => mediumblue
- @info.replace "Ready."
- end
- end
- def paste
- begin
- if app.clipboard.to_s.strip != "" then
- @dropstack.contents.delete_if {|p| p.content == app.clipboard.strip }
- @dropstack.prepend do
- clip
- end
- flash_message "Pasted!", :success
- end
- rescue Exception => e
- clear_clipboard
- flash_message "The system clipboard doesn't contain text. Not nice!", :error
- end
- end
- def clear_search
- @search.text = ""
- flash_message "Search box cleared!", :success
- @dropstack.clear
- @dropstack_contents.each {|c| @dropstack.append { clip c.content } }
- end
- def search
- flash_message "Searching...", :success
- regexp = @search.text
- regexp = (regexp.match(/^\/.*\/[a-z]$/)) ? instance_eval(regexp) : Regexp.new(regexp)
- @dropstack_contents = @dropstack.contents.dup
- clips = @dropstack_contents.select{|c| c.content.match regexp}
- flash_message "#{clips.length} matching clips found.", :success
- @dropstack.clear
- clips.each { |c| @dropstack.append{ clip c.content } }
- end
- def clear_pasty
- @dropstack.clear
- flash_message "Pasty cleared!", :success
- end
- def clear_clipboard
- app.clipboard = ""
- flash_message "Clipboard cleared!", :success
- end
- def save_clips
- File.open("pasty.yml", "w+") { |f| f.write @dropstack.contents.map{|c| c.content }.to_yaml}
- flash_message "Clips saved!", :success
- end
- def load_clips
- if File.exist? "pasty.yml" then
- clips = YAML.load_file("pasty.yml")
- if clips.empty? || !clips.respond_to?(:each) then
- flash_message "No clips to load...", :warning
- else
- clips.each { |c| @dropstack.append{ clip c } }
- flash_message "#{clips.length} clips loaded!", :success
- end
- else
- flash_message "No clips to load...", :warning
- end
- end
- end
- Shoes.app(:title => "Pasty", :resizable => false, :height => 700, :width => 500) do
- style Shoes::Para, :size => 10
- style Shoes::Link, :weight => "bold", :underline => false
- style Shoes::LinkHover, :weight => "bold"
- @pasty = pasty
- end