d.sunnyone.org
sunnyone.org

ページ

2016-06-15

Rust で Git クライアントを書き始めた

Twitterでちょいちょいスクリーンショットをあげてたので、もはや見慣れた人もいるかもしれないですが、Xで使うためのGitクライアントを書き始めました。
https://github.com/sunnyone/metal-git

リリースにUbuntu 14.04でビルドしたバイナリが置いてありますが、おまけレベルです。


言語はRust。以前にチュートリアルっぽいものを書いたgtk-rsと、libgit2のラッパーであるgit2-rsを使って書いています。最初はコマンドのラッパーで行こうかなと思ったけど、今にして思うとgit2-rsの手助けがあって本当によかった。

Rustはまだまだ慣れてないので、ここはこうするとすっきり行くみたいなのは、細かいところでも教えてもらえるとうれしいです(ただマクロは控えられるところは控えようかなと思っていますが)。

もうちょっとそこそこ使えるようになってから公開しようかなとも思いましたが、まぁコミットの部分はとりあえず使えるようになったので書き始めたということで出そうかなと。無駄なコードが多いので結構恥ずかしいのだけど。

一応gtk-rsもgit2-rsのどちらもmingwでビルドできるみたいなことは見たので、Windowsでもビルドできるかもしれませんが、とりあえず当面は考えない方向でいきます。

ひとまずMetal Gitという名前にしました。良い名前があれば変えるかもしれません。

---

今のソースの規模はこんな感じ。モデルの分離もうまくできていないし、もう少し分割したい。
metal-git/src$ wc -l *.rs
  621 commit_window.rs
   81 gobject_utils.rs
   70 gtk_utils.rs
  166 history_window.rs
   40 main.rs
  337 railway.rs
   29 repository_manager.rs
   16 static_resource.rs
  241 station_cell_renderer.rs
   98 station_renderer.rs
  107 station_wrapper.rs
   62 window_manager.rs

作り始めたのはこれがきっかけなので、なんやかんやもう3ヶ月。長かったなぁ。


2016-05-10

Xubuntu 16.04 をインストールして最初に行う設定

Xubuntuは、XFceを使ったUbuntuのフレーバー。ここからダウンロードできる。デフォルトではGNOME2ライクな見た目の画面が使える。


そのままでも使えるのだが、自分はもうちょっとWindowsライクに使いたいので、いつもやっている設定を書いておく。

パネルを下側に移動する(いわゆる「タスクバー」を下に)

デフォルトでは上側にある黒いバー「パネル」には、デフォルトではアプリケーションを呼び出すメニュー、ウィンドウ一覧、インジケータ、時計が置いてある。要はタスクバーのようなものだ。これを下側に移動する。


下側に移動するには、パネルを右クリックし、パネル>パネルの設定を選択し、「パネル」ウィンドウを開く。

そして「パネルをロックする」チェックボックスをオフにして、パネル左側に出る取っ手を掴んで下に移動する。

Whisker Menu を押しやすくする(「スタート」ボタンを作る)

左下にある(左下に移動された)青いボタンを押すといわゆるスタートメニュー的なもの(Whisker Menuという名前らしい)が出てくるが、青いアイコンだけなので押しにくい。領域を増やして押しやすくする。

領域を増やすには、まずWhisker Menuを右クリックして「プロパティ」を選択し、「Whisker Menu」ウィンドウを開く。


「パネルボタン」の「表示」を「アイコンとタイトル」に変更して、「タイトル」を表示するようにする。「タイトル」はデフォルトでは「Application Menu」であるが、これはちょっと大きすぎるので自分は「Start」にしている。

時計の表示内容を変更

右下の時計はデフォルトでは「4 5月, 15:03」みたいな変な感じなので、カスタマイズしてそれっぽくする。

時計の表示内容をカスタマイズするには、時計を右クリックして「プロパティ」を選択して「時計」ウィンドウを表示する。


あとは「表示形式」を「カスタム」に設定し「%m/%d(%a) %H:%M:%S」などとする。選べる値はヘルプボタンを押せば飛べるがhttp://docs.xfce.org/xfce/xfce4-panel/clockを見ればわかる。

クイック起動(ピン)のショートカットを追加

クイック起動やピン留めのように、アプリケーションをパネルから起動したい。

パネルにアプリケーションの起動ボタンを配置するには、Whisker Menuを起動し、アプリケーションを右クリックして「パネルに追加」を選ぶ。

すると、パネル右側にアイコンが現れるので、右クリックして移動を選び、好きな場所に配置する。

これでだいたい定番の設定はおしまい。パネルを右クリックして「新しいアイテムの追加」を選ぶと、他にも増やせるものがあるので、好きに選ぶといいかも(ワークスペーススイッチャーとか)

おまけ: $HOMEのディレクトリを英語にする

デフォルトでは$HOMEに置いてある「デスクトップ」や「ピクチャ」はカタカナでcdしにくい。Xubuntuに限った話ではないが、これでは不便なのでいつもこれをしている。

$ LANG=C xdg-user-dirs-gtk-update

変えていいか確認するウィンドウが現れるので、従えばOK。

おまけ2: キーボードショートカットの変更(2017/6/1追記)

画面では設定>キーボード>アプリケーションショートカットキーから設定できる。

毎回やるのはだるいのでコマンドで覚えておく

# 一覧
xfconf-query -c xfce4-keyboard-shortcuts -lv

# Ctrl+Fn でのワークスペース切り替えを無効化
xfconf-query -c xfce4-keyboard-shortcuts -l | grep '/xfwm4/custom/F' | xargs -l1 xfconf-query -c xfce4-keyboard-shortcuts -r -p

# Ctrl+Alt+Lでのロックを無効化し、Super+Lに変更
xfconf-query -c xfce4-keyboard-shortcuts -p "/commands/custom/<primary><alt>l" -r
xfconf-query -c xfce4-keyboard-shortcuts -p "/commands/custom/<super>l" --create -t string -s xflock4

参考:ターミナルなどからXfceの設定をする

2016-04-21

waifu2xAvisynthをY8に対応させた

要望があったので、気分転換に実装して、v0.0.2をリリースした。
http://waifu2x-avisynth.sunnyone.org/

あまり更新することは考えていなかったのだけど、おまけのようなU/V planeの処理を省けば良いだけだったので。

最初のリリースが2015/5/30なので、もうほぼ1年になるのか、というのが衝撃。正直この実装はwaifu2x-converter-cppとAvisynthのつなぎをしただけで、たいしたことはしていないのだけど、それでも今でもStarされたりするあたり、知名度というものはすごいなぁと思う次第である。

2016-04-13

gtk-rs のチュートリアル的文書を書いた

Gtk+のRustラッパーであるgtk-rsの入門を書いた:RustとGtk+で開発するGUIアプリケーション

ほんとはもう少しやるといいことがあるのだけど(GResource、スレッド対応など)、まぁとりあえずここまで書いてあればGUIアプリケーション書いたことある人であれば感じは掴めるのかなと。ということでRev0.1。

(少なくともいまのところは)ニーズはほとんどないと思うけど、やる気があるうちにある程度形にしておかないと絶対書かないので。自分がこれから書いていくアプリケーションを読み進めるにあたっての基礎知識となれば。

2016-04-10

メタプログラミングについて話してきました

ゆるスタック勉強会 #20 で「メタプログラミングとは」という内容で話してきました。「メタプログラミングって何?イメージがつかない」という話を受けて、イメージをつくようにするのがこの話の目的です。



本当はそれぞれの言語のやりかたについて手順を書けばよかったのですが、力つきたので、実際のライブラリから例を持ってくる方向性にしました。話している間はコードや別の資料も見ながら話していたので、このスライド自体というよりは、各スライドでポイントしているライブラリの実装あるいは類似するライブラリの実装を読んでもらうのがイメージをつかみやすいんじゃないかと思います。

それぞれの言語でニワカなところがあるので、全方位からツッコミを受けてもおかしくない内容だと思っています。何かあれば補足していきたいのでぜひどうぞ。

2016-04-01

Rust と C言語 をコールバックで行き来する(Cブリッジが必要なVer)

Rustは C FFI が強いので、はっきりしたstructとCの関数を呼び出すなんていうケースでは、それっぽいstructとexternでの関数の定義を書けば呼び出せる。コールバックもできる。
他言語関数インターフェイス

しかし、以下のようなケースではちょっとやりにくい。
  • 必要な関数の呼び出しにCマクロが必要
  • opaqueなstructの下のほうのメンバにアクセスが必要
要はC言語を解釈してもらえると楽だよねという話なので、「Cでラッパー書いてautotoolsだMakefileだなんだかんだ、ようやくつなげる」となるかと思いきや、このようなCラッパーが必要な状況についてもRustには補助がある。今回はそのやりかたについて紹介する。

自分が必要だったところがC世界からのコールバック呼び出しだったので、それについても触れる。基本的には、RustのアプリケーションがCライブラリを使うという想定。コールバックなので、行ったり来たりなのだけどね。

やりかたの概要

やりかたは概ね以下の通り。
  1. ラッパー関数をCで用意する
  2. CargoのビルドスクリプトでCソースのコンパイル方法を指示する
  3. ラッパー関数をexternで定義する
  4. ラッパー関数を呼び出すstruct & traitを定義する
  5. 実際に呼び出す
実際のソースはhttps://github.com/sunnyone/rust-bridgesampleに置いてあるので、ソースがあればいいという方はこちらでどうぞ。

やりかた

ラッパー関数の準備

Rustから呼び出したい関数を、普通の関数呼び出しにできる形で定義する。本来は何かのコードのラッパーの想定なのだが、そっち側の知識が必要となると話がややこしくなるので、ここでは単なるCソースを例として使う。



上記がsrc/bridge.cに置かれているとする。

Cargo.toml + build.rsにCソースのコンパイル方法の指示する

ここがこの記事のキモ。cargoに、置いたCソースのコンパイル方法を指示する必要がある。

まず、Cargo.tomlにビルドスクリプトが「build.rs」にあるよ、ということを指示する。またコンパイラの実行の面倒を見てくれる「gcc」crateをbuild dependenciesに入れる(gccと言っているが、MSVCも対応しているらしい。試してないが)。

[package]
(略)
build = "build.rs"

[build-dependencies]
gcc = "0.3"

[dependencies]
libc = "0.2"

dependenciesのlibcは、ビルドスクリプト的には必要ないが、C FFIではほぼ使うのでここで入れておく。

上記で定義した「build.rs」に、コンパイラの呼び出しを定義する。

extern crate gcc;

fn main() {
    gcc::compile_library("libbridgesample.a", &["src/bridge.c"]);
}

このあたりの記述、詳しくはCargoのドキュメント「Build Script Support」を参照。
本来ライブラリのリンクの指示も必要だが、ここでは一旦省く。詳しくは上記ドキュメントを参照(下でもすこし触れる)。

ラッパー関数をexternで定義する(いわゆる-sys部分)

ここからはもうRust onlyでのFFIと一緒。externでfnとstructを定義する。opaqueなstructをenumを定義するのがイディオムだそうだ。

Cargoの流儀的には、FFIのためのRustらしくない定義はなんちゃら-sysというcrateに定義するほうがそれらしい。この部分だけの差し替えがしやすいから、とのこと。

ラッパー用のstructを用意する

ffi層を叩く、Rust 的構造にあわせた呼び出し部を用意する。今回は、コールバックをクロージャでもらい、それを実際のCコールバックから呼ぶ形にした。

「外側」と「内側」の2つのstructを作る

Rust世界のコード用のデータを入れておく「内側」と、その「内側」とC関数からもらったポインタを格納しておく「外側」を用意する。


必ずしもこうでなくてよいが、こうしておくことで「内側」をBox(ヒープ)で持つことが出来、ポインタに変換してC関数のポインタに渡すことができる。

git2-rsのsrc/transport.rsでやっていたので参考にした。

Drop traitを実装しポインタが自動で捨てられるようにする

後始末大事。


コールバックとしてC側に渡す関数をexternで定義する

今回はライフタイムをRustが持っているので、キャストするだけ。ここでは、Rust側がライフタイムを握っているのでポインタを渡しているが、もしC側がライフタイムを握るようであれば、Box::into_rawBox::from_rawをうまく使うといいと思う。ライフタイムの制御から外せる。mem::forget というのもあるかな。


ラッパーを実装

あとはffi関数を呼び出すようMyStructにimplする。


呼び出しコードを書く

実際呼ぶコードはこんなかんじになる。 結果はこんな感じ。
mystruct_new
Hello, World: 11
Hello Result: 12345
mystruct_free
これでだいたい使えるはず。

おまけ:pkg-configでライブラリを参照させる

本来ラップする対象があるはずなので、リンク対象やincludeパスを指定する必要がある。基本的には、println!()で、cargoが必要な情報を渡してあげればよいが、build-dependenciesでpkg-config crateを使うと、pkg-configの結果を使える。例えばこんな感じ。 with-glib branchで使ってみてある。実際のところは、panicはやっつけなのでちゃんと分岐させたり、pkg-configに関わらず環境変数で設定できるようにしたりと、工夫がされていることが多いので、詳しくはそこらのライブラリのコードを参照。例えば、glib-sys crateはこんな感じ

2016-03-15

Rust の開発環境を作る (Ubuntu + Visual Studio Code)

今回はRustとその開発環境のセットアップの仕方について。Ubuntu 14.04環境に、Visual Studio Codeをインストールして、コード補完ができるようになるまで。Ubuntu Makeのところ以外は、Macでも大体同じじゃないかなと思う。


Rust コンパイラまわり

multirustのインストール

multirustは、stableやnightlyなどrust環境を切り替えられるようにするツール。普通にrustcをインストールしてもよいが、便利なのでmultirustで入れておく。

$ curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sh
(略)
$ rustc --version
rustc 1.7.0 (a5d1e7a59 2016-02-29)

rustc的にはこれでおしまい。

Visual Studio Codeまわり

アーカイブを展開するだけでも良いのだけど、便利なUbuntu Makeツールを使う。

Ubuntu Makeのインストール

$ sudo add-apt-repository ppa:ubuntu-desktop/ubuntu-make
$ sudo apt-get update
$ sudo apt-get install ubuntu-make
新しいUbuntuではubuntu-makeのppaはいらないかもしれない。

Visual Studio Codeのインストール

$ umake ide visual-studio-code
(インストールパスを聞かれるけどデフォルトでこんな感じに。)
Choose installation path: /home/yoichi/.local/share/umake/ide/visual-studio-code 

便利なので本来のコマンド名codeでシンボリックリンクを貼っておく。
$ ln -s ~/.local/share/umake/ide/visual-studio-code/code ~/.local/share/umake/bin/code

visual-studio-codeのリンクが壊れているようだけど、Gitでは直っているようなので、少しするとvisual-studio-codeでも起動できるようになると思う。

RustyCode extensionのインストール

VSCodeのRust言語用拡張のRustyCodeをインストールする。codeで起動後、Ctrl+Shift+pでコマンドパレットを起動し、install RustyCodeでインストール。

開発支援ツールまわり(racer, rustfmt)

Codeを起動してRustyCodeで書こうとすると、以下のようにエラーが出るので、必要なツールを入れる。
The "racer" command is not available. Make sure it is installed.

racer (コード補完ツール) のインストール

$ cargo install racer
(略)
  Installing /home/yoichi/.multirust/toolchains/stable/cargo/bin/racer
be sure to add `/home/yoichi/.multirust/toolchains/stable/cargo/bin` to your 
PATH to be able to run the installed binaries
cargoに言われる通りPATHを~/.bashrcなどに設定する

export PATH=$PATH:~/.multirust/toolchains/stable/cargo/bin

その後racerを実行するとわかるが、racerには参照用にRustのソースが必要なので、ダウンロードして適当なところに置いておく。

$ racer
RUST_SRC_PATH environment variable must be set to point to the src directory of 
a rust checkout. E.g. "/home/foouser/src/rust/src"
$ mkdir ~/src
$ wget https://static.rust-lang.org/dist/rustc-1.7.0-src.tar.gz
$ tar zxvf rustc-1.7.0-src.tar.gz

racer用にソースの配置場所を環境変数に設定する(~/.bashrcなどに書く)
export RUST_SRC_PATH=~/src/rustc-1.7.0/src

racerコマンドを叩いてusageが出ればOK。

rustfmt (ソースコードフォーマッター) のインストール

なくてもエラーは出ないが、入れておくとCtrl+Shift+I でコードフォーマットできる。cargo fmtでもOK.

インストールはcargoで。
$ cargo install rustfmt

Hello Worldプロジェクトの作成

試すには、適当にプロジェクトを作成してCodeで開く。
$ cargo new hello --bin
$ code hello &

src/main.rsを適当に編集したら、Ctrl+Shift+Rか、コマンドパレット(Ctrl+Shift+p)からRun Debugで実行できる。