2015-03-30 3 views
0

Я пишу небольшой инструмент в clojure и хочу знать, когда в буфере обмена произошли изменения. Вот упрощенная версия того, что происходит.clojure (add-watch) не сообщается, когда изменения сделаны в буфере обмена

(:import java.awt.Toolkit) 

(:import (java.awt.datatransfer Clipboard 
           ClipboardOwner 
           Transferable 
           StringSelection 
           DataFlavor 
           FlavorListener)) 

(defn get-clipboard [] (. (Toolkit/getDefaultToolkit) 
        (getSystemClipboard))) 

(defn get-content [] 
    (.getContents (get-clipboard) nil)) 


(def content (agent (get-content))) 


(defn watch [key f] 
(add-watch content key f)) 

(defn -main [] 
    (while (not= content "banana-man") 
    (watch :watcher 
      (fn [key agent old-state new-state] 
      (prn "-- agent Changed --") 
      (prn "key" key) 
      (prn "atom" agent) 
      (prn "old-state" old-state) 
      (prn "new-state" new-state))))) 

Я добавил в цикл while, чтобы немедленно отключить основную функцию.

Это выполняется без каких-либо ошибок, но не сообщает о внесении изменений в буфер обмена или прекращении цикла while при копировании bannan-man в буфер обмена. Я боролся с этим в течение нескольких недель, и я уверен, что я пропустил что-то простое. Если у кого-нибудь есть совет, я бы очень признателен!

ответ

0

Для начала контент является агентом, поэтому он никогда не будет равен строке. Вы должны обработать агент, используя @, чтобы сделать это сравнение.

Цикл while не нужен для предотвращения выхода. Если вы используете пул потоков агентов, Clojure не будет закрыт, пока вы явно не запустите shutdown-agents. Но мы будем нуждаться в нем для управления обновлениями вашего агента.

content не будет изменен после вашего первоначального назначения, если вы явно не отправите ему функцию обновления с помощью send или send-off. Не позволяйте названию вводить вас в заблуждение, агенты не являются автономными и не являются запланированными или повторяющимися задачами. Попробуйте что-то вроде этого:

(defn -main [] 
    (watch :watcher 
      (fn [key agent old-state new-state] 
      (prn "-- agent Changed --") 
      (prn "key" key) 
      (prn "atom" agent) 
      (prn "old-state" old-state) 
      (prn "new-state" new-state))) 
    (while (not= @content "banana-man") 
    (send-off content (fn [& _] (get-content))) 
    (Thread/sleep 250)) 
    (shutdown-agents)) 
+0

Спасибо за ваше время Noisemith, – Sawin

+0

Извините, преждевременно нажмите enter. Я довольно новичок в clojure и программировании в целом, поэтому извиняюсь за любые неэффективные методы, которые я использовал в своем примере. И спасибо за ваше предложение! Но я должен спросить, нет ли способа вернуть функцию add-watch новое состояние без активной отправки для контента? Чтобы быть ясным, я нацелен на то, что пользователь сканирует документ на текст ctrl-c, который будет автоматически вытащен из буфера обмена и обработан для просмотра пользователем позже. У меня есть чувство, что ваше предложение - лучший вариант, но я просто хотел проверить. Еще раз спасибо! – Sawin

+0

Не то, чтобы это было неэффективно - это было бы на самом деле ничего не делать. Агент изменяется только в том случае, если вы вызываете 'send' или' send-off'. Он не является автономным. И наблюдатель только срабатывает, если агент меняется - он еще менее автономный. Вам нужно * что-то *, которое многократно проверяет состояние буфера обмена в цикле. Я думаю, что проще в явном виде включить это действие в цикл. – noisesmith

 Смежные вопросы

  • Нет связанных вопросов^_^