デスクトップの背景を黒一色にする
地味にやり方をわすれてしまうのでメモ代わりに。
デスクトップの背景は黒一色がよいのだが、デフォルトで選択できるの「無地の色」の中にはそれがない。
ここにでてきているのは、/Library/Desktop Pictures/Solid Colors の中身っぽいので、
こんな感じの適当に黒い画像を作って*1、Library/Desktop Pictures/Solid Colors にいれてあげると、
上の画像のように、フォルダに入れた画像が選べるようになる。
ということで、自分のデスクトップはこんな感じ。真っ黒な背景はおちつく。
別に黒に限らず特定の色、一色にしたい場合はこれでいける。
「日本語WordNetのデータベースを探索するフロントエンドプログラム」を Ruby で書き直した
日本語WordNetのデータベースを探索するフロントエンドプログラム - yanbe.diff - subtech を読んで使ってみようとしたが、Python 2.6 が手元のマシンに入っておらず、apt で探すもみつからず、絶望的な気分になり、Ruby で書き直してみた。
基本的にはそのまま。usage とかもコピペ。嵌まった点としては、Python では空のリストが偽であるということ*1。
#!/usr/bin/ruby -Ku # -*- coding: utf-8 -*- require 'rubygems' require 'sqlite3' class WNJpn Word = Struct.new("Word",:wordid, :lang, :lemma, :pron, :pos) Sense = Struct.new("Sense",:synset, :wordid, :lang, :rank, :lexid, :freq, :src) Synset = Struct.new("Synset",:synset, :pos, :name, :src) SynLink = Struct.new("SynLink",:synset1, :synset2, :link, :src) def initialize(dbfile) @conn = SQLite3::Database.new(dbfile) end def get_words(lemma) @conn.execute("select * from word where lemma=?",lemma).map{|row|Word.new(*row)} end def get_word(wordid) Word.new(*@conn.get_first_row("select * from word where wordid=?",wordid)) end def get_senses(word) @conn.execute("select * from sense where wordid=?",(word.wordid)).map{|row|Sense.new(*row)} end def get_sense(synset, lang="jpn") row = @conn.get_first_row("select * from sense where synset=? and lang=?",synset,lang) row ? Sense.new(*row) : nil end def get_synset(synset) row = @conn.get_first_row("select * from synset where synset=?",synset) row ? Synset.new(*row) : nil end def get_syn_links(sense, link) @conn.execute("select * from synlink where synset1=? and link=?",sense.synset,link).map{|row|SynLink.new(*row)} end def get_sys_links_recursive(senses, link, lang="jpn", depth=0) senses.each do |sense| syn_links = get_syn_links(sense, link) puts "#{' ' * depth}#{get_word(sense.wordid).lemma} #{get_synset(sense.synset).name}" unless syn_links.empty? _senses = syn_links.map{|syn_link|get_sense(syn_link.synset2,lang)}.compact get_sys_links_recursive(_senses, link, lang, depth + 1) end end def main(word, link, lang='jpn') if words = get_words(word) sense = get_senses(words.first) get_sys_links_recursive(sense, link, lang) else STDERR.puts "(nothing found)" end end def self.print_usage puts <<-EOS usage: wn.rb word link [lang] word word to investigate link syns - Synonyms hype - Hypernyms inst - Instances hypo - Hyponym hasi - Has Instances mero - Meronyms mmem - Meronyms --- Member msub - Meronyms --- Substance mprt - Meronyms --- Part holo - Holonyms hmem - Holonyms --- Member hsub - Holonyms --- Substance hprt - Holonyms -- Part attr - Attributes sim - Similar to entag - Entails causg - Causes dmncg - Domain --- Category dmnug - Domain --- usage dmnrg - Domain --- Region dmtcg - In Domain --- Category dmtug - In Domain --- usage dmtrg - In Domain --- Region antsg - Antonyms lang (default: jpn) jpn - Japanese eng - English EOS end def close_db @conn.close end end if __FILE__ == $0 if ARGV.length >= 2 dbfile = "wnjpn-0.9.db" wnj = WNJpn.new(dbfile) wnj.main(*ARGV) wnj.close_db else WNJpn.print_usage end end
termtterで補完
list ユーザ名 とか、uri-open ってうつのがめんどくさいので、補完できるようにした。
require 'set' class Termtter::Client public_storage[:users] ||= Set.new add_hook do |statuses, event, t| if !statuses.empty? case event when :update_friends_timeline, :replies, :list_user_timeline statuses.each do |s| public_storage[:users].add(s.user_screen_name) s.text.scan(/@[a-zA-Z_0-9]*/).each do |u| # reply public_storage[:users].add(u.gsub("@","")) unless u == "@" end end end end end end module Termtter module InputCompletor Commands = %w[exit help list pause update resume replies search show uri-open] CompletionProc = proc {|input| case input when /^l(ist)? +(.*)/ username = $2 if username.empty? Termtter::Client.public_storage[:users].to_a else Termtter::Client.public_storage[:users].to_a. grep(/^#{Regexp.quote username}/).map{|u| "list #{u}"} end when /^uri-open +(.*)/ uri_open_com = $1 if uri_open_com.empty? %w[clear list] else %w[clear list]. grep(/^#{Regexp.quote uri_open_com}/).map{|c| "uri-open #{c}"} end else Commands.grep(/^#{Regexp.quote input}/) end } end end Readline.basic_word_break_characters= "\t\n\"\\'`><=;|&{(" Readline.completion_proc = Termtter::InputCompletor::CompletionProc
これを適当に保存して、.termtter から require すれば、補完できるようになる。
たとえば、
list ってうってタブ押すと、
ユーザ名が出てくるし、
そこで、適当にいれてタブ押すと
こんな感じで補完できる。
コマンドに関しても同様で
urまでうってタブ押せば、
こんな感じに補完される。
termtter から growl に通知する
http://jugyo.org/blog/2931がおもしろそうなので、termtter から growl に通知してみた。
できていること
require 'meow' Termtter::Client.add_hook do |statuses, event| if !statuses.empty? && event == :update_friends_timeline growl = Meow.new("Termtter") statuses.reverse.each do |s| screen_name = s.user_screen_name text = s.text.gsub("\n",'') growl.notify(screen_name,text) end end end
これを好きなとこにおいて、.termtterから require すればOK*1。とりあえず、誰の発言かということとその内容はでる。
超簡単ですばらしいと思った。
よくわからないこと
現状よくわかんないのが、どうやってアイコンを出すかということで、
.termtterに、
module Termtter class Status %w( id text created_at truncated in_reply_to_status_id in_reply_to_user_id user_id user_name user_screen_name user_profile_image_url # ここに user_profile_image_url を追加した ).each do |attr| attr_accessor attr.to_sym end end class Client def get_timeline(uri, update_since_id = false) doc = Nokogiri::XML(open(uri, :http_basic_authentication => [@user_name, @password])) statuses = [] doc.xpath('//status').each do |node| status = Status.new %w( id text created_at truncated in_reply_to_status_id in_reply_to_user_id user/id user/name user/screen_name user/profile_image_url # ここにも user/profile_image_url を追加した ).each do |key| method = "#{key.gsub('/', '_')}=".to_sym status.send(method, node.xpath(key).text) end status.created_at = Time.utc(*ParseDate::parsedate(status.created_at)).localtime statuses << status end if update_since_id && !statuses.empty? @since_id = statuses[0].id end return statuses end end end
とかを書いて、user_profile_image_url にもアクセスできるようにして
Termtter::Client.add_hook do |statuses, event| if !statuses.empty? && event == :update_friends_timeline growl = Meow.new("Termtter") statuses.reverse.each do |s| screen_name = s.user_screen_name text = s.text.gsub("\n",'') tmp = OSX::NSURL.URLWithString_(s.user_profile_image_url) #ここと icon = OSX::NSImage.alloc.initWithContentsOfURL(tmp) #ここと growl.notify(screen_name,text,:icon=>icon) #ここを追加 end end end
というようにしてあげれば、いいのかなーと思ったのだけれど、OSX::NSURL.URLWithString_(s.user_profile_image_url)がとれるのもあったり、 nil になったりするのがあって、よくわからなくなっている。あとでちゃんと考えたい。
*1:ただし、meow必須
termtter から growl に通知する の続き
引き続きtwitter、というかtermtterの話。
termtter から growl に通知する - Learning to be Me の続き。growlで通知するとこまではできたのだが、ユーザのアイコンが表示できていなかった。url指定しても、うまくいったり行かなかったりなので、結局一度ダウンロードして、画像を表示することにした。
~/sketch/ruby/growl-send.rb とかそんな感じの適当なファイルに、
require 'meow' require 'uri' def get_icon(s) cache_file = "#{Termtter::CACHE_DIR}/#{s.user_id}" unless File.exist? cache_file buf = "" open(URI.encode(s.user_profile_image_url)) do |r| buf = r.read end open(cache_file,"w") do |r| r.write(buf) end end return OSX::NSImage.alloc.initWithContentsOfFile(cache_file) end Termtter::Client.add_hook do |statuses, event| if !statuses.empty? && event == :update_friends_timeline growl = Meow.new("Termtter") statuses.reverse.each do |s| screen_name = s.user_screen_name text = s.text.gsub("\n",'') icon = get_icon(s) growl.notify(screen_name,text,:icon=>icon) end end end
を保存してあげて、
.termtter を、
module Termtter CACHE_DIR = '/tmp/termtter-icon-cache-dir' class Status %w( id text created_at truncated in_reply_to_status_id in_reply_to_user_id user_id user_name user_screen_name user_profile_image_url ).each do |attr| attr_accessor attr.to_sym end end class Client def get_timeline(uri, update_since_id = false) doc = Nokogiri::XML(open(uri, :http_basic_authentication => [@user_name, @password])) statuses = [] doc.xpath('//status').each do |node| status = Status.new %w( id text created_at truncated in_reply_to_status_id in_reply_to_user_id user/id user/name user/screen_name user/profile_image_url ).each do |key| method = "#{key.gsub('/', '_')}=".to_sym status.send(method, node.xpath(key).text) end status.created_at = Time.utc(*ParseDate::parsedate(status.created_at)).localtime statuses << status end if update_since_id && !statuses.empty? @since_id = statuses[0].id end return statuses end end end Dir.mkdir(Termtter::CACHE_DIR) unless File.exist?(Termtter::CACHE_DIR) require File.expand_path('~/sketch/ruby/growl-send.rb') configatron.user_name = 'ユーザ名' configatron.password = 'パスワード'
という感じにしてあげれば、アイコン付きで、termtterからgrowlに通知がいく、はず。
debian etch の subversion のバージョンをあげる
研究室で計算用サーバとして使ってるマシーン(debian etch)で
% svn up
ってやると、「svn: このクライアントは、作業コピー '.' を扱うには古すぎます。もっと新しい Subversion クライアントをダウンロードしてください。」などと言われた。
ググると subversion が古いからこうなるらしい。
ということで、新しくした手続きのメモ。といっても、backportsから持ってくるだけ。
/etc/apt/preferencesに
Package: * Pin: release a=etch-backports Pin-Priority: 1 Package: * Pin: release a=stable Pin-Priority: 800 Package: subversion Pin: release a=etch-backports Pin-Priority: 900 Package: libsvn1 Pin: release a=etch-backports Pin-Priority: 900
という感じでかいてあげて、
% sudo apt-get update % sudo apt-get dist-upgrade
としてあげればOK
grep --color について
find/grep/xargsコマンドを使いこなす 業務で楽するためのUNIXテクニック集「検索」編 (1/4):CodeZine(コードジン) をみて思い出したけれど、
grep に --color オプションつけなくても、
export GREP_OPTIONS='--color=always'
って .zshrc なり .bashrc にかいておくと、常に grep の結果に色がつく。
でも、grep をパイプでつないでいるときに、色が邪魔してうまく動かなかったりする*1。
そのときは、スクリプト内の grep に --color=never というオプションを渡してあげれば、色をつかなくできる。