2018年10月30日火曜日

Chrome拡張でクリックイベントを完全に止める

クリックイベントにcookieを付けて必ず広告を表示させてくるケースを見かけるようになった。
iframeを使うクリックジャッキングなら様々な防ぎ方があるけど、 そういった方法では防ぐ事ができないポップアップだし、何よりやられると鬱陶しさが半端じゃない。

この問題は、Chrome拡張なら以下のように設定する事で防げる。 要約すると、このコードの宣言以降はクリックイベントの上書きを禁止する命令です。 Chrome拡張を "run_at": "document_start" で実行すれば鬱陶しいクリックイベントを仕込んでくる処理を無効化できる。
if (location.host == "www.hoge.com") {
  document.addEventListener('click', event => event.stopImmediatePropagation(), true);
  document.addEventListener('mousedown', event => event.stopImmediatePropagation(), true);
  document.addEventListener('touchend', event => event.stopImmediatePropagation(), true);
  document.addEventListener('touchstart', event => event.stopImmediatePropagation(), true);
}

全サイトに適用すると便利な機能まで削除してしまうので、 本当に鬱陶しいサイトだけにしましょう。

2018年10月29日月曜日

Googleアプリ有料化から見える変化の兆し

IT/AIの時代も大きく動いている感じがする。 例を挙げればキリがないけど、以下はかなりわかりやすいし大きなニュースだと思いました。
このニュースに伴って、Googleアプリを載せる場合にはライセンス料を付ける方針が伝えられ、欧州ではやはり端末価格が上がっていく事になりそうです。 一見は自爆ですが、利点もある。

まずはGoogle一強の防止。 Google Maps、Gmail, YouTube、PlayStoreが有料になったとして、マップは様々な代替があります。 メールもLINEに代表されるチャットツールの浸透によって様々な余地ができている。 YouTubeには代替になり得るものはない気がするけど、だからあえて盛り込んだ感じなのかな。 長期的には権力の分散効果はありそうです。
ただPlayStoreは問題です。これがないとアプリのインストールさえできません。 野良ストアが流行すれば確かに競合になり得ますが、どうなっていくか何とも言えない。 現時点では一強を防いだとしても不都合があまりにも大きい。


なのでPlayStoreに関してはもう1つの利点で考える事のほうが簡単だと思う。 それは欧州が課税面での恩恵が得られるという事です。 米国系IT企業はどこの国で稼いでいるかが曖昧である事を利用して課税逃れをしているとよく言われますが、その対策になる。 以前からデジタル税で売上に課税をする事でそれを防止しようとしていましたし、 端末にPlayStoreを組み込んでいる事を明確化させる事で、 その売上が欧州向けに発売されたものである事が明確になります。 地域端末に関連する売上にデジタル税で課税をすれば、課税逃れが結構難しくなると思う。

似たような事は韓国でも進められていますが、 このような課税の厳格化は、国家の利益を守る意味では非常に重要です。 ただ実際どれくらい課税逃れがあるかはよくわからないし、欧州の目論見通りに進むかはまだ不透明です。 でも利益のほうが大きいと試算したから課税したんじゃないかな。 などと思惑を巡らせていたらイギリスもデジタル税をプッシュして来ました他国も追随しつつあるようです。 たった1ヶ月でこの速度、どの国も凄い迅速だなあ。


このような課税の変化は端末競争の在り方にはかなり影響があり、結構大きな変化を生むように思います。 既に通貨危機や貿易戦争によって世界と米国の不和が強まり、ロシアや中国、中東は米国から離れつつあります。 欧州も間接的にですが、関税の流れができた事になります。 この感じだとさらに新しい流れも出てくるかも。

例えばサウジに関する一連の報道対米投資規制が強まっている事なども、かなり近い分野の話なので嫌な感じですね。 他にもIBMがLinuxのRed Hatを340億ドルで買収などもレイヤが多少違うもののクラウドとOSが絡む大きな話。 仮想端末として見れば端末に食い込む余地も大きいプレイヤーなので、もしかすると。 今思えばMicrosoftがLinux保護のために6万件の特許を無料開放した事も、流れを加速させる一因になっていそうです。 着々と全体に波が波及しているように思う。

このような変化の中、あくまで最終的な流れとして純粋な効率面だけを考えれば、 端末の在り方は大きく変わっていく事は想像でき、 状況次第では他国で製造するほうがずっと安くなる可能性はあるように思います。

2018年10月27日土曜日

Pixel 3はAIの未来を占う試金石

iPhone XR/XS/XS MaxPixel 3/3 XLが日本で発売される事になりました。



iPhoneは749〜1499ドルで、日本では84,800円〜。スペック的には素晴らしいようですが、ソフトは2-3年前から頭打ちしている。 本来なら中韓の設備投資でDRAM価格が下がって多少は値頃感が出るかなとも思っていたのですが、 貿易戦争もあってか価格は上昇した感じ。 とにかく高スペックを求める人には良さそうだけど、以前から少し高めではある。


一方のPixel 3は799〜1099ドルで、日本では95,000円〜。 安ければ良いなという淡い期待があったのですが、それは夢と消えました。 ただ記事を見ていると非常に面白い端末で、Googleでなければ作れないようなAI機能を盛り込んだ端末になっている。 良くも悪くもPixel 3は今後のAIの未来を占う試金石のような製品ですね。 AI大好きな人には面白い端末だと思う。

ただ画像翻訳はアプリでも提供されてますし。カメラは凄いけど使うかな。 ファッションアイテムの画像検索もGogglesから派生したGoogleレンズですよね。 Call ScreenやDuplex、迷惑電話のAIによる撃退なども面白いけど絶対必要というものではないし。 リアルタイム翻訳は凄いし欲しい人も多いと思うけど、これもGoogle翻訳が凄いのであって、Pixel 3が凄いのとはまた違う。 同じスペックで半額の端末もあるし、まさにキャッチフレーズから「AIを買うかどうか」になってると思うのです。

多くの人にとって「AIを買う」判断はどのようにするものなんでしょうね。 私だったら未来の大きさというのが1つの尺度かなあ。 ノートPCが10万円くらいして今よりずっと高かった時代でも、それによって買えた未来は大きかった。 6万円で買えた初代iPhoneや、初代Androidと比較してどうか。 今4万円で買えるPCの未来より、10万円で買えるPixel 3の未来は大きいだろうか。 2〜3万円で買える中古スマホと比較してどうか。とか。 日本人より新興国の方がどう感じるのかが気になるなあ。


Pixel 3の売れ行きがどうなるかは割と気になります。 「面白いと欲しいはまた違う」となるのか、やっぱAI凄いとなるのか。 米国の物価とインフレに世界は合わせていけるのかという良い判断材料にもなりそう。 iPhoneの値段は初期型が599ドルですから、そこに 1.02^11 (インフレ率) を掛けると744ドルなんですよね。 アメリカの方にとってはiPhoneの価格の肌感覚は変わってないですが、日本人からすると結構な差に見える。

ガラケが付属機能を付けるのに躍起になっていた時代があるけど、結局はiPhoneに駆逐されたようにならないか。 と言って当時のiPhoneのような先端的端末が今後作れるのかというと、そこも難しいところがあるので、PCのほうが参考になるのかも知れない。 PCは先進的な機能が結局生まれず、廉価端末として定着しました。 ガラケ時代にはiPhoneが成功する事は多くの人が予想できたと思いますが、AIは成功するでしょうか。


Pixel 3が成功ならGoogleの描く世界、失敗なら安きに流れる時代が加速していくだろうと私は思います。 貿易戦争の前なら私は後者だろうと思っていて、その主役は中国だろうとは思っていましたし、 実際にHuaweiは後一歩のところまで来ていた。 しかし知財で徹底的に叩かれ始めた中国が、覇権を取るのはかなり遠くなった。 スパイウェアまみれになるよりは良いかも知れないけど、 知財をまともにして売ってくれる道も残っていると助かる。別に中国である必要はないけども。

2018年10月17日水曜日

フリゲ紹介: シューティングスターセブン

シューティングスターセブンは3人の主人公を操作してプレイする爽快アクションゲーム。 ゲーム自体は英語ですが、日本語で紹介されてますし、それほど英語は出てこないので大丈夫です。



作者様が紹介動画も公開されているのでそちらを見ると雰囲気がわかるかも。




これはなかなか凄いアクションゲームです。 ぬるぬる動くし、必殺技があったり、その見せ方も細かなところまで凝ってるし、背景も凄い作り込み。 そして何より爽快感抜群だし、主人公の1人のアミィはアクションが格好良い (左下)。 操作方法もプレイ中に提示してくれるので操作に困る事もない (右下)。 凄く気持ち良くプレイできる作品だと思います。



1面でアミィ、2〜3面ではベティ (左下)、セシリィ (右下) の3人をプレイできます。 アミィは銃器、ベティは重火器、セシリィは超能力を操っており、まったく操作性が異なります。 最初プレイした時は3面のセシリィの癖が強くて難しかった。 ちゃんと説明されているのですが、相手の攻撃をシールドで防ぐとチャージできる事に気付かないと厳しい。 気付いてからはサクサクプレイできました。ゲームバランスも素晴らしい。



4面以降は3人が協力し合ったりして (下)、3面までとはまた違った面白さ。どこまでもよく考えられた作品だと思う。 EASYでも歯ごたえはあったけど、何回かコンティニューしていればクリアまではしっかり辿り着けるくらいの難易度でした。 アクションがそこまで得意な人ではなくても楽しめると思います。 上手い人ならHARDでもいけるのかな、私にはちょっと厳しそうだった。



非常に面白い作品でした。おすすめ。

フリゲ紹介: 妖精とゴーレム

妖精とゴーレムはマウスとキーボードを使って、二人の妖精をそれぞれ操作し、ゴーレムを引っ張る新感覚アクションゲームです。



妖精のリタとシラハがスケルトンっぽいホネに襲われるところから物語は始まります (左下)。 近くで寝ていたゴーレムを使ってホネを撃退しようとするリタ。 「妖精がどうやってゴーレムを動かすの?」と疑問に感じると思いますが、フェアリーロープという凄いロープを使います。 マウスで妖精1、キーボードで妖精2を操作し、輪ゴムを飛ばすイメージでゴーレムを飛ばす事ができる (右下)。 図では黄色の点線がフェアリーロープですが、何となくわかるかな。
マウスを使うゲームってどうしても操作性が悪くなりがちですが、 妖精がゴーレムを動かすなんて難しくて当然だし、でもその割には思い通りに動いてくれる。楽しい。



ステージはかなり多くて実は歯ごたえのある作品。左下のマップのの5-6倍くらいステージあります。 ステージの難易度も自由に変えられるのでアクションが苦手な人でも大丈夫。 ステージごとにクリア条件が異なっているので、そのへんも飽きが来ないように配慮されている。
仲間の妖精もどんどん増えます (右下)。 妖精はそれぞれ能力がまったく異なるので、その能力をうまく活かさないとクリアが難しいステージもある。



シンプルだけど凄く面白い作品だと思いました。

2018年10月11日木曜日

vimの配色を起動時刻ごとにランダムに変える

普段エディタで黒系の配色を使っていて、 晴れの日に外でコーディングすると画面が明るいせいで見にくくなったりする事があります。 で、設定を変える訳ですが、帰ってくるとまた黒配色に戻さないといけない。 最近のエディタはカラースキームが用意されているので切り替えは昔より簡単にはなっているのですが、 もっと簡単にできないかなあと思いました。

vimだとこの問題は簡単に対応できそうだったので、 少し問題を簡単にして、起動時刻で配色を変えられるスクリプトを書いてみました。 配色の設定を変える事自体も簡単になっています。 まず以下のコードを ~/bin/cvim などの実行しやすい環境に配置します。
#!/usr/bin/env python

import os, sys, datetime, argparse, subprocess, random

# config
light_500   = 'solarized,gruvbox,seoul256,hybrid,PaperColor'.split(',')
light_other = 'github,schellar,newspaper,kalisi,pencil,tender'.split(',')
dark_500   = 'solarized,gruvbox,molokai,onedark,jellybeans,hybrid,badwolf,seoul256,monokai,zenburn,iceberg,PaperColor,nord'.split(',')
dark_other = 'frictionless,wasabi256,tender,apprentice,alduin,kalisi,antares,nefertiti,moonshine'.split(',')
light = light_500 + light_other
dark = dark_500 + dark_other

filepath = os.environ['HOME'] + '/.vimrc.colorscheme'


parser = argparse.ArgumentParser(description='color changer for vim')
parser.add_argument('-d', '--dark',  action='store_true', help='use dark theme')
parser.add_argument('-l', '--light', action='store_true', help='use light theme')
(args, vim_args) = parser.parse_known_args()


background = colorscheme = None
hour = datetime.datetime.now().hour
if args.light == True:
    background = 'light'
    colorscheme = random.choice(light)
elif args.dark == True:
    background = 'dark'
    colorscheme = random.choice(dark)
elif hour < 7 or 17 < hour:
    background = 'dark'
    colorscheme = random.choice(dark)
else:
    background = 'light'
    colorscheme = random.choice(light)
with open(filepath, 'w') as f:
    f.write('set background=%s\n' % background)
    f.write('colorscheme %s' % colorscheme)

vim_args = ' '.join(vim_args)
subprocess.call('nvim %s' % vim_args, shell=True)

上記のコードではGithubで500以上のスターを貰っているカラースキームと、ここで紹介されているものを片っ端から登録してみました。今回はvimでこれらのカラースキームを事前に読み込んでおく事を想定しています。 この設定は面倒だと思うので、Shougo/dein.vimを使った設定例を表示しておくと以下になります。
"--- 500 fav
call dein#add('altercation/vim-colors-solarized')
call dein#add('morhetz/gruvbox')
call dein#add('tomasr/molokai')
call dein#add('joshdick/onedark.vim')
call dein#add('nanotech/jellybeans.vim')
call dein#add('w0ng/vim-hybrid')
call dein#add('sjl/badwolf')
call dein#add('junegunn/seoul256.vim')
call dein#add('sickill/vim-monokai')
call dein#add('jnurmine/Zenburn')
call dein#add('cocopon/iceberg.vim')
call dein#add('NLKNguyen/papercolor-theme')
call dein#add('arcticicestudio/nord-vim')
"--- dark & light
call dein#add('freeo/vim-kalisi')
"--- dark
call dein#add('0xcharly/vim-frictionless')
call dein#add('thomd/vim-wasabi-colorscheme')
call dein#add('AlessandroYorba/Alduin')
call dein#add('romainl/Apprentice')
call dein#add('jacoborus/tender.vim')
call dein#add('Haron-Prime/Antares')
call dein#add('jeetsukumaran/vim-nefertiti')
call dein#add('KKPMW/moonshine-vim')
"--- light
call dein#add('endel/vim-github-colorscheme')
call dein#add('igungor/schellar')
call dein#add('vim-scripts/newspaper.vim')
call dein#add('reedes/vim-colors-pencil')


さらに ~/.vimrc や ~/.config/nvim/init.vim で背景色とカラースキームを指定をしている箇所を以下のように書き換え、カラースキームの設定を別のファイルから読み込むようにします。
" 時刻で表示を変える
execute ':source ' . '~/.vimrc.colorscheme'

あとは以下のように普段vimを使う時と同様に実行すればカラフルなvimの出来上がり。 -l, -dオプションを付けると黒配色と白配色を明示したりもできる。
cvim foobar.txt
cvim -d dark.feel

今のところ夜中に実行すると黒配色、日中に実行すると白配色で表示します。 表示はカラースキームのリストの中からランダムに選びます。 照明や屋内外の判定を頑張れば面白いかもですが、そこまでのやる気はなかった。 起動する度に表示が変わり新鮮な気持ちでvimれるようになったので、これだけでも満足してます。

2018年10月8日月曜日

bashで編集可能な補完を実現する方法

fzfを使った時にCtrl-Tなどのキーバインドで「編集可能な補完」を実現している方法がわからなかったので調べてみました。 ~/.fzf/shell/key-bindings.bash を読むと重要なのは以下。

fzf-file-widget() {
  if __fzf_use_tmux__; then
    __fzf_select_tmux__
  else
    local selected="$(__fzf_select__)"
    READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}$selected${READLINE_LINE:$READLINE_POINT}"
    READLINE_POINT=$(( READLINE_POINT + ${#selected} ))
  fi
}
bind -x '"\C-t": "fzf-file-widget"'

bindコマンドでCtrl-Tでfzf-file-widget関数を呼び出しているけど、 内部では__fzf_select__、ようするにfzfを起動して選択パスをselectedに保存している。 その後READLINE_LINEとREADLINE_POINTを設定する事で、編集可能な文字列の入力を実現しているようです。

このREADLINE_LINEとREADLINE_POINTの仕組みは覚えておくと結構便利そうですね。 しかしbashの公式リファレンス見てもサラッとしか書いてない。 おそらくここが最も詳しく説明しているページなので、そちらを読んだほうが良いけど、軽くまとめると以下のようになっている。
# 出力文字列の設定
READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}$selected${READLINE_LINE:$READLINE_POINT}"
       # 先頭からカーソル位置までの現在の文字列 | 選択文字 | カーソル位置より後ろの現在の文字列

# カーソル位置の設定
READLINE_POINT=$(( READLINE_POINT + ${#selected} ))


ところでこの機能についての補足ですが、fzfではbash3以前では別の方法で実現しており、そちらについては割愛してます。 またzshやfishだとまた違った方法で実現するしかないようで、あまり深みにハマらないほうが良いかも知れません。 シェルスクリプトの種類ごとに実装が異なるという事は、有名ではないシェルだと編集可能な補完がそもそもできない可能性もあるかも知れない。


応用してみます。
コマンドを補完してアプリを選択し、引数を付けて実行しやすくしてみましょう。
__launch() {
    local selected="$(compgen -ac | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse $FZF_DEFAULT_OPTS $FZF_CTRL_T_OPTS" fzf) "
    READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}$selected${READLINE_LINE:$READLINE_POINT}"
    READLINE_POINT=$(( READLINE_POINT + ${#selected} ))
}
bind -x '"\C-j": "__launch"'

上記を~/.bashrcなどに記述すると、fzfを利用してCtrl-Jで実行ファイルの入力補完ができ、補完後に実行オプションを再編集できます。

2018年10月1日月曜日

peco/fzfを使って軽量ランチャーを作ってみた

常駐なしでコマンドをpeco/fzfで部分一致検索できる軽量ランチャーを作ってみた。

これまでAlbertランチャーを使っていたのだけど常駐する必要もない気がしてきて、何となくランチャーを作ってみたら一瞬で作れてしまった。 似たようなコンセプトでRofiという良い感じのランチャーもあるのだけど、作ってしまったものは仕方ないので紹介してみる。

peco/fzfとRofiそのものの最大の違いは執筆時点では複数選択できるかどうかと思うけど、ランチャーでは複数選択する必要性があまりないので、正直Rofiでも良かったかも知れない。 まあRofiよりWindowsに応用しやすい点は利点かなあ。


作り方: まず以下のコードを ~/bin/launch などの実行しやすいディレクトリに配置する。 launchコマンドを実行するとpeco/fzfを使ってコマンドを検索、実行できる。
特に複雑な事は何もしていないけど、コマンドのリストをキャッシュして高速化している。 apt-getなどでコマンドをインストールしてキャッシュを更新したい場合は launch update で更新できる。 何もしないでも1日間隔でキャッシュは更新する。
#!/usr/bin/env ruby

update_freq = 24 * 60 * 60  # 1day
cache = ENV['HOME'] + '/bin/launch.lst'

def update(filepath)
  t = Time.now
  open(filepath, 'w') {|f|
    f.write `bash -ic "compgen -ac"`
  }
  puts "cache are updated! (#{Time.now - t}sec.)"
end


if ARGV[0] == 'update'
  update(cache)
  exit
elsif !File.exist?(cache)
  update(cache)
elsif File.ctime(cache) + update_freq < Time.now()
  update(cache)
end

# app = `cat #{cache} | peco --select-1`
app = `cat #{cache} | fzf --select-1`
`lnch #{app}`

最終行のlnchコマンドは存在しないため、次にこのコマンドを ~/bin/lnch などのパスが通ったディレクトリに登録する必要がある。 lnchコマンドは外部コマンドを実行する時に子プロセスを停止しないような実行を行う。 RubyやPythonではたぶんこれができない。 なので仕方なく以下のようなコードをGo言語で書いてビルドする必要がある。 実はこのテクニック、このサイトで紹介されていたもの。この方もfzfをランチャー化したいという事で、よく似た事をやっている。
package main
import (
  "fmt"
  "log"
  "os"
  "os/exec"
  "syscall"
)

func main() {
  if len(os.Args) <= 1 {
    fmt.Println("Usage: lnch  ")
    os.Exit(1)
  }
  cmd := exec.Command(os.Args[1], os.Args[2:]...)

  // this is the important part to avoid killing the child process instantly
  cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}

  err := cmd.Start()
  if err != nil {
    log.Fatal(err)
  }
}

あとは何らかの方法でlaunchコマンドをGUI呼び出しすればランチャーになる。 実はこれ、xfce4-terminalを使うと秒速で完成する。 xfce4-terminalには様々なウィンドウオプションがあるので簡単に格好良い表示ができる。 例えば以下のような感じで呼び出す。
xfce4-terminal --drop-down \
--hide-menubar --hide-borders --hide-toolbar --hide-scrollbar \
-x launch

あとはこれを何らかの方法でキーボード呼び出しすれば、キーボードランチャーの完成となります。 Lubuntuなら ~/.config/openbox/lubuntu-rc.xml でキーバインドを設定できるので、 以下をkeybindタグがある辺りに追加すると、Win+Spaceでランチャーを起動できる。 設定は openbox --reconfigure で反映できます。
<keybind key="W-space">
  <action name="Execute">
    <command>xfce4-terminal --drop-down --hide-menubar --hide-borders --hide-toolbar --hide-scrollbar -e "bash -ic launch"</command>
  </action>
</keybind>

実行画面は以下のような感じ。キャッシュを利用すれば起動時のラグはほぼゼロでストレスもない。



現時点で作り込みの甘さからRofiに劣っているところは、過去の起動履歴から検索候補順を並び替えたりしていないところ。でもそれくらいかなあ。たった数十行でそれくらいしか課題がないなら結構凄いかなと。 xfce4-terminalを応用すると誰でも簡単にドロップダウンメニューを作れるので、ランチャー以外にも応用できそう。