Ответ 1
Этот ответ отлично подходит для OSX:
def pbcopy(input)
str = input.to_s
IO.popen('pbcopy', 'w') { |f| f << str }
str
end
def pbpaste
`pbpaste`
end
Как вы копируете текст в буфер обмена в Ruby?
Звучит просто, правда? Но я пытаюсь сделать это уже 5 дней, но безуспешно.
Я искал в интернете, но все, что я получил, это как это сделать в более новых версиях Ruby (я использую 1.8.7, и нет, я не могу использовать более новую версию).
Поэтому я попытался сделать HTML файл, чтобы сделать это для меня. Попробовав 4-5 различных способов (из онлайн-руководств), в 3 браузерах и даже взглянув на исходный код Photobucket, чтобы попытаться выяснить, как он копирует img-коды, я сдался. Ничто не сработало для меня.
Поэтому я создал С#.exe и заставил мою программу Ruby вызывать его. Наконец что-то отправляется в буфер обмена. Это шаг вперед, но все же, это только первое слово в строке. Когда я пытаюсь скопировать two words
, копируются только two
.
моя Ruby-программа выглядит так:
system ("CopyClip.exe #{text}")
и в С# (в CopyClip) это делает:
Clipboard.set_text(args[0])
По сути, мне все равно, если вы поможете мне сделать это на Ruby, HTML, С# или любом другом языке, если он работает.
Этот ответ отлично подходит для OSX:
def pbcopy(input)
str = input.to_s
IO.popen('pbcopy', 'w') { |f| f << str }
str
end
def pbpaste
`pbpaste`
end
Жемчужина буфера обмена позволяет получить доступ к буферу обмена в Liunx, MacOS и Windows. Основное внимание уделяется простому тексту. Вы можете скопировать строку с помощью Clipboard.copy("строка") и вставить ее с помощью Clipboard.paste()
.
Вот оно, в принципе.
Теперь давайте подробнее рассмотрим конкретные платформы.
Linux Для поддержки Linux нужна небольшая утилита xclip. Вы можете установить его в Ubuntu с помощью sudo apt-get install xclip
.
Кроме того, вы можете выбрать, из какого буфера обмена вы хотите вставить (по умолчанию PRIMARYCLIPBOARD). copy()
копирует все буферы обмена в Clipboard::CLIPBOARDS
, например, Clipboard.paste :primary
.
Macos
На macOS все работает нормально.
Я подозреваю, что вы переносите аргумент в свое приложение С# в кавычки, вы получите весь текст в args[0]
:
system("CopyClip.exe '#{text}'")
Альтернативно и, вероятно, лучше, если ваш текст содержит апострофы или другие специальные символы оболочки:
system("CopyClip.exe", text)
Или, может быть, даже лучше, используйте буфера обмена - это работает для меня на 1.8.7, но я не смог проверить он в Windows:
require 'clipboard'
Clipboard.copy text
Для тех, кто пишет приложения GTK + (которых нет OP), запись в буфер обмена довольно проста:
Gtk::Clipboard.get(Gdk::Selection::CLIPBOARD).set_text(content).store
Вы также можете использовать выбор первичного (Gdk::Selection::PRIMARY
) или вторичного (Gdk::Selection::SECONDARY
) X.
См. также полный ruby API и его базовый C API.
Похоже, вы используете окна, это работает с Ruby 1.9.3 под Windows 7.
Для исходного ответа см. Рубиновая копия в буфер обмена с помощью Fiddle
require 'open3'
module Clipboard; end
module Clipboard::Windows
extend self
CF_TEXT = 1
CF_UNICODETEXT = 13
GMEM_MOVEABLE = 2
# get ffi function handlers
begin
require 'ffi'
rescue LoadError
raise LoadError, 'Could not load the required ffi gem, install it with: gem install ffi'
end
module User32
extend FFI::Library
ffi_lib "user32"
ffi_convention :stdcall
attach_function :open, :OpenClipboard, [ :long ], :long
attach_function :close, :CloseClipboard, [ ], :long
attach_function :empty, :EmptyClipboard, [ ], :long
attach_function :get, :GetClipboardData, [ :long ], :long
attach_function :set, :SetClipboardData, [ :long, :long ], :long
end
module Kernel32
extend FFI::Library
ffi_lib 'kernel32'
ffi_convention :stdcall
attach_function :lock, :GlobalLock, [ :long ], :pointer
attach_function :unlock, :GlobalUnlock, [ :long ], :long
attach_function :size, :GlobalSize, [ :long ], :long
attach_function :alloc, :GlobalAlloc, [ :long, :long ], :long
end
# see http://www.codeproject.com/KB/clipboard/archerclipboard1.aspx
def paste(_ = nil)
ret = ""
if 0 != User32.open( 0 )
hclip = User32.get( CF_UNICODETEXT )
if hclip && 0 != hclip
pointer_to_data = Kernel32.lock( hclip )
data = ""
# Windows Unicode is ended by to null bytes, so get the whole string
size = Kernel32.size( hclip )
data << pointer_to_data.get_bytes( 0, size - 2 )
if RUBY_VERSION >= '1.9'
ret = data.force_encoding("UTF-16LE").encode(Encoding.default_external) # TODO catch bad encodings
else # 1.8: fallback to simple CP850 encoding
require 'iconv'
utf8 = Iconv.iconv( "UTF-8", "UTF-16LE", data)[0]
ret = Iconv.iconv( "CP850", "UTF-8", utf8)[0]
end
if data && 0 != data
Kernel32.unlock( hclip )
end
end
User32.close( )
end
ret || ""
end
def clear
if 0 != User32.open( 0 )
User32.empty( )
User32.close( )
end
paste
end
def copy(data_to_copy)
if ( RUBY_VERSION >= '1.9' ) && 0 != User32.open( 0 )
User32.empty( )
data = data_to_copy.encode("UTF-16LE") # TODO catch bad encodings
data << 0
handler = Kernel32.alloc( GMEM_MOVEABLE, data.bytesize )
pointer_to_data = Kernel32.lock( handler )
pointer_to_data.put_bytes( 0, data, 0, data.bytesize )
Kernel32.unlock( handler )
User32.set( CF_UNICODETEXT, handler )
User32.close( )
else # don't touch anything
Open3.popen3( 'clip' ){ |input,_,_| input << data_to_copy } # depends on clip (available by default since Vista)
end
paste
end
end
Clipboard::Windows.copy("test")
puts Clipboard::Windows.paste
В моей коллекции у меня был еще один script, который использовался для работы в 32-разрядной версии Windows 7, если у вас есть проблемы с первым и используйте только 32 бит, попробуйте этот
#!/usr/bin/env ruby -w
# win32 only
require 'singleton'
require 'thread'
require 'Win32API'
class Clipboard
include Singleton
CF_TEXT = 1
def initialize
@@mutex = Mutex.new
@@open = Win32API.new("user32","OpenClipboard",['L'],'L')
@@close = Win32API.new("user32","CloseClipboard",[],'L')
@@empty = Win32API.new("user32","EmptyClipboard",[],'L')
@@set = Win32API.new("user32","SetClipboardData",['L','P'],'L')
@@get = Win32API.new("user32", "GetClipboardData", ['L'], 'L')
@@lock = Win32API.new("kernel32", "GlobalLock", ['L'], 'P')
@@unlock = Win32API.new("kernel32", "GlobalUnlock", ['L'], 'L')
end
def copy
@@mutex.synchronize do
@@open.Call(0)
str = @@lock.Call(@@get.Call(CF_TEXT))
@@unlock.Call(@@get.Call(CF_TEXT))
@@close.Call
return str
end
end
def paste(str)
@@mutex.synchronize do
@@open.Call(0)
@@empty.Call
@@set.Call(CF_TEXT, str)
@@close.Call
@@lock = Win32API.new("kernel32", "GlobalLock", ['L'], 'P')
@@unlock = Win32API.new("kernel32", "GlobalUnlock", ['L'], 'L')
return nil
end
end
end
clip = Clipboard.instance
puts clip.copy
puts str
clip.paste("foo")
puts clip.copy
Если вы не возражаете, чтобы установить драгоценный камень, вот гораздо более простое решение, работающее на 64-разрядном Windows7, Ruby 1.9.3.
#gem install clipboard
require 'clipboard'
Clipboard.copy("This is a sentence that has been copied to your clipboard")
puts Clipboard.paste