2016/12/25

Raspberry Pi Model B+ でベアメタル UART 出力ユーティリティ化

前回、 親知らずの日記: Raspberry Pi 3 Model B+ でベアメタル UART 出力 では、 UART で受信した文字をエコーバックするプログラムを作成した。

プログラム内で任意の文字列を出力させるため、ユーティリティ化したい。

目的

デバッグ目的で UART に任意文字列を出力したい。

こんな感じで使いたい。

int main(void) {

    println("Hello, World!");

    error_code = function();
    print("error_code: ");
    print(error_code);
    println(".");

    return 0;
}

要素技術

  1. UART 出力
  2. '数値 -> 文字列' 変換

UART 出力

こんな感じになった。

uart.h

#ifndef __UART_H__
#define __UART_H__

/**
 * Mini Uart 送受信に使用するレジスタ。
 *
 * 書き込むと送信 FIFO にプッシュ,
 * 読み込むと 受信 FIFO からポップしてくれる素敵仕様らしい。
 */
#define MU_IO (*(volatile unsigned int *)0x3F215040)

/**
 * Mini Uart 送信 FIFO の状態確認をするための情報が入ったレジスタ。
 *
 * 6 ビット目 : Transmitter idle, アイドル状態か?
 *              1: アイドル状態, 0: ビジー状態
 * 5 ビット目 : Transmitter empty, 1 バイト以上送信受付可能か?
 *              1: 可能, 0: 不可能
 * 0 ビット目 : Data ready, 1 バイト以上受信しているか?
 *              1: 受信している, 0: 受信していない
 */
#define MU_LSR          (*(volatile unsigned int *)0X3F215054)

/* Transmitter idle のビットマスク */
#define MU_LSR_TX_IDLE  (1U << 6)

/* Transmitter empty のビットマスク */
#define MU_LSR_TX_EMPTY (1U << 5)

/* Data ready のビットマスク*/
#define MU_LSR_RX_RDY   (1U << 0)

void println(const char* chars);
void print(const char* chars);
void uart_put(const char c);

#endif // __UART_H__

uart.c

#include "uart.h"

/* あとで types.h に追い出す */
typedef unsigned int size_t;

void println(const char* chars) {
    print(chars);
    print("\n\r");
}

void print(const char* chars) {
    char* char_ptr = (char*) chars;

    while (*char_ptr != '\0') {
        uart_put(*char_ptr);
        char_ptr++;
    }
}

void uart_put(const char c) {
    // 送信受付可能状態になるまでビジーループ
    while (!(MU_LSR & MU_LSR_TX_IDLE) && !(MU_LSR & MU_LSR_TX_EMPTY));

    // IO レジスタにデータ書き込み
    MU_IO = c;
}

'数値 -> 文字列' 変換

これはこんな感じ。

string.h

#ifndef __STRING_H__
#define __STRING_H__

unsigned char ltoa_10(const long l, char* str, const int max_length);

#endif // __STRING_H__

string.c

#include "string.h"

/**
 * @fn 10 進数値を文字列へ変換する
 * @param (l)          変換対象数値
 * @param (str)        変換後の文字列を格納するバッファへのポインタ
 * @param (max_length) 変換後の文字列を格納するバッファの長さ
 * @return エラーコード
 *         0 : 正常終了
 *         1 : 変換後文字列を格納するバッファの長さが足りなかった
 */
unsigned char ltoa_10(const long l, char* str, const int max_length) {
    unsigned int  i;
    unsigned long tmp_long_value = l < 0 ? -l : l;
    unsigned char tmp_digit_value;
    unsigned int  length = 0;

    // 桁の数値と文字を対応付けする配列
    const char cmap[]
            = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

    // ゼロ判定, ゼロならさっさと返却する
    if (l == 0) {
        if (max_length < 2) {
            return 1;
        }

        str[0] = '0';
        str[1] = '\0';

        return 0;
    }

    // 桁数判定
    while (tmp_long_value != 0) {
        tmp_long_value = tmp_long_value / 10;
        length++;
    }
    if (l < 0) {
        length++;
    }

    // バッファ長上限判定(NULL 文字を含めるので +1 する)
    // 上限を超えていたら 1 を返却
    if (length + 1 > max_length) {
        return 1;
    }

    // 文字列変換

    // 文字列変換開始インデックス
    i = length - 1;

    // NULL 文字追加
    str[length] = '\0';

    // 各桁の変換
    tmp_long_value = l < 0 ? -l : l;
    while (tmp_long_value != 0) {
        tmp_digit_value = tmp_long_value % 10;
        str[i] = cmap[tmp_digit_value];
        i--;
        tmp_long_value = tmp_long_value / 10;
    }

    // 負数処理
    if (l < 0) {
        str[0] = '-';
    }

    return 0;
}

使い方

こんな感じで使えるようになった。

#include <string.h>
#include <uart.h>

#define BUF_LENGTH 5

int main(void) {

    char cbuf[BUF_LENGTH];

    println("Hello, World!");

    error_code = function();
    ltoa_10(error_code, cbuf, BUF_LENGTH);

    print("error_code: ");
    print(error_code);
    println(".");

    return 0;
}

成果物

この辺りをユーティリティとしてまとめたうえで、 gcc で挙動テスト(string.c のみ)するようにしたものが下記 URL にある。

これでデバッグプリントできるようになったので、 HDMI 出力できない問題を追いかけていく。 (しかし SD カード抜き差しが非常に厳しい...)

以上。

2016/12/24

Windows 10 に mikutter 3.4.8 をインストールした

わけあって moguno/mikutter-windows に頼らずに windows にインストールしてみたいと思い、実際やってみたので作業を記録する。

環境まとめ

  • OS: Windows 10 Pro
  • Ruby: 2.3.3

Ruby 入手

  • RubyInstaller Downloads
    • Ruby 2.3.3 (x64) をダウンロード
      • パスを通す設定をしてください
    • DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe をダウンロード

mikutter ソースコード入手

git インストール済みなのでクローンする。

git clone git://toshia.dip.jp/mikutter.git

mikutter に必要な gem たちのインストール

DevKit を展開してできた msys.bat を実行。

cd /PATH/TO/mikutter
gem install bundler
bundle install --path vendor/bundler

mikutter 実行

bundle exec で起動。

cd /PATH/TO/mikutter
bundle exec ruby mikutter.rb

ショートカット作成

まずはスタート用のバッチファイルを作る。

cd /PATH/TO/mikutter
echo start rubyw mikutter.rb> mikutter.bat

作成したバッチファイルへのショートカットをデスクトップに作る。

TODO

  • display_display_requirements
  • 別窓で画像開くやつの画像が表示されない
  • 音を出す
    • 今は音が鳴らない moguno/mikutter-windows のサウンドプラグイン単独配布してくれないかなぁ...。
  • アイコン
    • ショートカットアイコンに png 指定できないの辛い

音とアイコンについては moguno/mikutter-windows で実現されているので、真似して作業していく。

Raspberry Pi 3 Model B+ でベアメタル UART 出力

前回に引き続き、今回も下記サイトを参考にベアメタルプログラミングをしていく。

今回は UART でのデータ送受信。

参考ページは下記。

必要なハードウェアの調達

UART するには通信ケーブルが必要なので調達した。

ドライバは下記ページを参考にした。

UART を使用するための設定

config.txt を作成し、 enable_uart=1 を記述。 あとで SD カードのルートに格納する。

この辺は今のところ「おまじない」としておく。

このおまじないをすると、 GPU が Mini UART を使えるようにしてくれるようになるらしい。 そのため、我々は、 UART の初期化コードを書くことなくプログラミングできるっぽい。

UART を使うためのレジスタの確認

使うレジスタ

BCM-ARM-Peripherals.pdf の 8 ページ目から UART のレジスタについて説明されている。

今回使うのは、 AUX_MU_LSR_REG(Mini Uart Line Status)AUX_MU_IO_REG(Mini Uart I/O Data)

Raspberry Pi 3 なので、上位アドレスを読みかえ、それぞれ 0x3F215054, 0x3F215040 となる。

ステータスレジスタについて

AUX_MU_LSR については、BCM-ARM-Peripherals.pdf の 15 ページ目に説明が書いてあるみたい。

プログラム作成

/**
 * Mini Uart 送受信に使用するレジスタ。
 *
 * 書き込むと送信 FIFO にプッシュ,
 * 読み込むと 受信 FIFO からポップしてくれる素敵仕様らしい。
 */
#define MU_IO (*(volatile unsigned int *)0x3F215040)

/**
 * Mini Uart 送信 FIFO の状態確認をするための情報が入ったレジスタ。
 *
 * 6 ビット目 : Transmitter idle, アイドル状態か?
 *              1: アイドル状態, 0: ビジー状態
 * 5 ビット目 : Transmitter empty, 1 バイト以上送信受付可能か?
 *              1: 可能, 0: 不可能
 * 0 ビット目 : Data ready, 1 バイト以上受信しているか?
 *              1: 受信している, 0: 受信していない
 */
#define MU_LSR          (*(volatile unsigned int *)0X3F215054)
#define MU_LSR_TX_IDLE  (1U << 6) /* Transmitter idle のビットマスク */
#define MU_LSR_TX_EMPTY (1U << 5) /* Transmitter empty のビットマスク */
#define MU_LSR_RX_RDY   (1U << 0) /* Data ready のビットマスク*/

int main(void) {

    // 受信文字列格納用
    volatile char ch;

    while (1) {
        // 受信するまでビジーループ
        while (!(MU_LSR & MU_LSR_RX_RDY));

        // 受信データ記録
        ch = (char)MU_IO;

        // 送信受付可能状態になるまでビジーループ
        while (!(MU_LSR & MU_LSR_TX_IDLE) && !(MU_LSR & MU_LSR_TX_EMPTY));

        // IO レジスタにデータ書き込み
        MU_IO = (unsigned int)ch;
    }

    return 0;
}

配線

元ネタのページにも記載されているが、ピン番号はこちらで確認した。

まじめな人はこれと BCM2835-ARM-Peripherals.pdf を見比べて、 仕様書の見方に慣れていくのが良いかと。 (多分 102 ページ目からの説明とか 176 ページ目からの説明とかが対応する記述なのだと思う。)

購入した変換ケーブルの説明を見ると、下記のようになっている。

ブラックケーブル ----- GND
グリーンケーブル ----- TXD
ホワイトケーブル ----- RXD
レッドケーブル ------- VCC - 5V

というわけで、下記感じで配線する。

PIN  6(GND) ----- ブラック(GND)
PIN  8(GPIO14) -- ホワイト(RXD)
PIN 10(GPIO15) -- グリーン(TXD)

動作確認

  1. SD カードに bootcode.bin, start.elf, config.txt, kernel8.img をコピーして、Raspberry Pi に挿す
  2. PC に変換ケーブルを挿す
  3. シリアルコンソールを起動し、 Com の設定を行う(後述)
  4. Raspberry Pi に電源供給
  5. 入力文字がエコーバックされれば OK

シリアルコンソールについて

今回は、 RLogin を使用することとした。 sixel 関係で使っていて、使い慣れていたので。

設定は、下記のようにすれば OK のはず。

  • ビット/秒 : 115200
  • データビット : 8
  • パリティ : なし
  • ストップビット : 1
  • フロー制御 : ハードウェア

以上。

2016/12/19

Raspberry Pi 3 Model B+ で、 OS 無し L チカした

Raspberry Pi でベアメタルプログラミンしたかったので、 いろいろ調べた作業記録を残す。

参考資料を探す

とりあえず、自分のレベルに合っていて、 かつ、わかりやすそうなサイトを探す。

...で、見つかったのがこのサイト。

基本ここを参考に環境構築とかしていくこととする。

必要なハードウェア類の調達

L チカに必要なものを買い集める。

必要なソフトウェア類の調達

ビルド環境構築

ダウンロードした gcc-linaro-6.2.1-2016.11-i686-mingw32_aarch64-linux-gnu.tar.xz を適当な場所に展開し、 bin ディレクトリにパスを通す。

L チカプログラムの作成

プログラムを作ってビルドする。

ファイル作成

こんな配置でファイルを作成する。

led_blink_GPIO16
├── main.c
├── Makefile
└── start.S

start.S

/* 現時点ではおまじないスタート地点を調整しているはず */
mov sp, #0x80000
bl  main

main.c

#define GPFSEL1 0x3F200004 /* GPIO のピン設定をするためのレジスタ */
#define GPSET0  0x3F20001C /* GPIO を HIGH にするためのレジスタ */
#define GPCLR0  0x3F200028 /* GPIO を LOW  にするためのレジスタ */

typedef unsigned char bool;

#define TRUE  1
#define FALSE 0

#define WAIT_COUNT 3000000

/*
 * @fn wait_count だけビジーウェイトする
 * @param (wait_count) このカウント数だけビジーウェイトする
 */
void busy_wait(int wait_count);

/*
 * @fn L チカする
 */
int main(void) {

    // GPIO 出力に設定。
    // Peripheral specification の
    // 92 ページ、Field Name が FSEL16 の行の
    // Bit(s) を見ると、18 から 20 ビット目までに
    // 0x001 を設定すればよいことがわかる感じ。
    *(volatile unsigned int*)GPFSEL1 = (1 << (18));

    // セットして待つ、クリアして待つ、を繰り返す。
    while (1) {
        *(volatile unsigned int*)GPSET0 = (1 << 16);
        busy_wait(WAIT_COUNT);
        *(volatile unsigned int*)GPCLR0 = (1 << 16);
        busy_wait(WAIT_COUNT);
    }

    return 0;
}

void busy_wait(int wait_count) {
    volatile unsigned int i;

    for (i = 0; i < WAIT_COUNT; i++);
}

Makefile

CC=aarch64-linux-gnu-gcc
LD=aarch64-linux-gnu-ld
AS=aarch64-linux-gnu-as
OBJCOPY=aarch64-linux-gnu-objcopy

OBJECTS=start.o main.o

all: build link objcopy

objcopy: kernel8.img

kernel8.img: kernel8.elf
    $(OBJCOPY) -O binary kernel8.elf kernel8.img


link: kernel8.elf

kernel8.elf: $(OBJECTS)
    $(LD) -Ttext 0x80000 -o kernel8.elf $(OBJECTS)


build: $(OBJECTS)

start.o: start.S
    $(AS) -o start.o start.S

main.o: main.c
    $(CC) -c -o main.o main.c


clean:
    rm *.o *.elf *.img

ビルド

make して kernel8.img を作成する。

$ make
aarch64-linux-gnu-as -o start.o start.S
aarch64-linux-gnu-gcc -c -o main.o main.c
aarch64-linux-gnu-ld -Ttext 0x80000 -o kernel8.elf start.o main.o
C:\Users\mikoto\app\gcc-linaro-6.2.1-2016.11-i686-mingw32_aarch64-linux-gnu\bin\aarch64-linux-gnu-ld.exe: warning: cannot find entry symbol _start; defaulting to 0000000000080000
aarch64-linux-gnu-objcopy -O binary kernel8.elf kernel8.img

リンカスクリプトを作っていないため、 警告が出ているけど、今回動かす分には問題ない。

Raspberry Pi の準備

ファイルの配置

  1. ダウンロードした firmware_armstub.zip を展開し、bootcode.bin, start.elf を SD カードのルートにコピーする
  2. ビルドした、 kernel8.img を SD カードのルートにコピーする

最終的に、 SD カードに下記感じでファイルを配置する。

SD カード
├── bootcode.bin
├── start.elf
└── kernel8.img

配線

下記感じで配線する。

PIN 36(GPIO16) ─ 抵抗 ─ LED
PIN 6(GND) ────────┘

実行

  1. Raspberry Pi に SD カードを入れる
  2. Raspberry Pi に電源供給

以上。

参考資料

この辺を見て試したはず...。ぬけもれあるかも。

2016/12/13

vim のアウトライン表示プラグイン outline.vim を作った

c 言語の関数一覧が欲しかったので作ったので、 そのあたりの作業について備忘メモしておく。

名前負けはご愛敬。

目的

c 言語の関数一覧が欲しかった。

何を考えたか?

c 言語の関数一覧が欲しいけど、 自分で抽出処理はかけない。

そんなわけで、方針としては

以下、各要素について書いていく。

アウトライン抽出

アウトライン抽出は ctags を使う。

ctags -x FILE_NAME --sort=no

これで member, struct, function のリストが表示される。 ここから member を取り除き、awk で無用な列を削除する。

ctags -x FILE_PATH --sort=no | grep -v member | awk '{$1=\"\";$2=\"\";$3=\"\" + $3;$4=\"\";print}'

これを、vim のバッファに読み込ませるには、 read! コマンドを使う。

silent execute "read !ctags -x " . file_path . " --sort=no | grep -v member | awk '{$1=\"\";$2=\"\";$3=\"\" + $3;$4=\"\";print}'"

これで、 ctags の実行結果を成形したものをバッファに読み込むことができる。

対象にジャンプ

ctags を成形した結果は、各行が 行番号 関数名 となっているので、 split してリストの 0 番目をとってきて、元のバッファに戻って [count]gg すれば OK。

で、できたのが下記な感じ。

以上。

2016/12/04

ファイル検索プラグイン file_selector.vim を作った

ファイル一覧を絞り込んで選択するやつを作ったので、 そのあたりの作業について備忘メモしておく。

目的

netrw でファイルを開くのが面倒。 プロジェクト内のファイル一覧から、文字列打ち込んで絞り込みつつファイル選択したい。 この欲望を満たすプラグインを作る。

何を考えたか?

ファイル絞り込みの構成要素としては、

  1. ファイル一覧取得
  2. 入力文字列取得
  3. 入力文字列を使った絞り込み処理
  4. バッファへの反映

みたいなのがあると思っていて、 2 と 4 のイメージがついてなくって途方に暮れていたところ、 @pink_bangbi さんにつぶやきを拾っていただいた。

そんなわけで、方針としては

  • 文字列取得は InsertCharPre から一文字ずつ取得
  • バッファは全部書き直し

の方針で考えた。

構成要素の実現方法を考える

それぞれ考えていく。

ファイル一覧取得

単純に glob("./**/*") とする。

入力文字列取得

autocmdInsertCharPre を捕まえる。

入力文字列を使った絞り込み処理 + バッファへの反映

v/文字列/d で、文字列が含まれていない行を削除できるので、

  1. バッファクリア
  2. glob("./**/*") で取得した一覧をバッファに流し込む
  3. v/文字列/d で関係ない行を削除

を、文字列入力・削除が行われるたびに実行する。

文字列のハンドリング

InsertCharPre で取得するのはいいけど、それどう管理するの?」を考える。

  • ファイル一覧
    • ファイル一覧はスクリプト変数
    • ファイル絞り込み用バッファを開くときに、``glob("./**/*") する
  • 絞り込み文字列
    • 絞り込み文字列はスクリプト変数
    • ファイル絞り込み用バッファを開くときに、空文字で初期化する
    • InsertCharPre で取得した文字列を絞り込み文字列に追加する
    • <BS> 押下で絞り込み文字列の末尾の文字を消す

file_selector をクラスとして考えると、下図のような感じ。

  • OpenFileSelector() を呼ぶたびに s:patterns:all_file_list を初期化する。
  • 文字入力されるたび( InsertCharPre が呼ばれるたび) AddChar()s:pattern 更新
    • InsertCharPre 内でバッファの更新ができないようなので、バッファの更新は TextChangedI で行う
  • <BS> が押されたら、 DelChar() -> UpdateBuffer() する。

上記のような方針で実装して、下記のような挙動が実現できた。

所感

「OpenFileSelector() を呼び出したバッファでファイルを開きたい」とか、 すでに気に入らないところがあるが、とりあえず絞り込み UI の習作として使用・改良していきたい。

リポジトリはこちら。

以上。

2016/11/28

vim-themis, vital-power-assert を使って vim plugin の単体テストを書いてみた

vim-themis, vital-power-assert を使って単体テストのコードを書いたので、ここに作業を記録する。

手順概要

  1. 必要なパッケージを導入
  2. .themisrc を作成する
  3. テストコードを書く
  4. テストを実行する

以下、各手順を説明していく。

1. vim-themis 導入

vim 標準のパッケージマネージャを使っているので、下記構成で git submodule add した。

.vim
└── pack
     └── test
         └── opt
             ├── vim-themis
             ├── vital.vim
             ├── vital-power-assert
             ├── vital-safe-string
             └── vital-vimlcompiler

注意点 :

  • vital-power-assert は、 vital.vim, vital-vimlcompiler, vital-safe-string に依存しているので忘れず導入する
  • テスト時しか使用しないので、 opt に入れる

2. .themisrc を作成する

vital-power-assert の README, '.themisrc' を参照しつつ .themisrc を作成。

packadd! vital.vim
packadd! vital-vimlcompiler
packadd! vital-safe-string
packadd! vital-power-assert
"
let g:__vital_power_assert_config = {
\   '__debug__': 1,
\   '__pseudo_throw__': 0
\ }

注意点 :

  • 必要なパッケージを packadd! で追加
  • themis へのランタイムパス追加は必要なかった。(packadd! で追加されるのかな?)

3. テストコードを書く

テストコードは、プラグインディレクトリ直下に test ディレクトリを作ってその中に書いていく。

vital-power-assert の README, 'test/Example.vimspec' をマネして Vimspeck-style で記述した。

Describe Test for buffer_selector
  Before all
    let V = vital#of('vital')
    let PowerAssert = V.import('Vim.PowerAssert')
    let s:assert = PowerAssert.assert
  End

  It test_GetBufNo
    let buffers_buffer =  '  1  h   "[無名]"                       行 0'
        \ . "\n" . '  9  h   "[無名]"                       行 0'
        \ . "\n" . ' 10  h   "[無名]"                       行 0'
        \ . "\n" . '119 %a   "[無名]"                       行 1'

    put!=buffers_buffer

    call cursor(1, 1)
    let bufno = buffer_selector#GetBufNo()
    execute s:assert('bufno is# "1"')

    call cursor(2, 1)
    let bufno = buffer_selector#GetBufNo()
    execute s:assert('bufno is# "9"')

    call cursor(3, 1)
    let bufno = buffer_selector#GetBufNo()
    execute s:assert('bufno is# "10"')

    call cursor(4, 1)
    let bufno = buffer_selector#GetBufNo()
    execute s:assert('bufno is# "119"')
  End
End

4. テストを実行する

ターミナルでプラグインのルートディレクトリに移動して、themis を実行すると、 vimspec ファイルを探して実行してくれる。

 ~/.vim/pack/test/opt/vim-themis/bin/themis --reporter spec
Test for buffer_selector
  [✓] test_GetBufNo

tests 1
passes 1

fail の場合は下記のようになる。

~/.vim/pack/test/opt/vim-themis/bin/themis --reporter spec
Test for buffer_selector
  [✖] test_GetBufNo
      function 89() abort dict  Line:22  ()

      vital: PowerAssert:
      bufno is# "120"
      |     |
      '119' 0

tests 1
passes 0
fails 1

実際にやってみたプロジェクトはこちら

buffer_selector.vim - Added test code.

「どうすればテストしやすいか」と、「どうやってテストするか」はまだまだ勉強が必要だ...。

以上。

2016/11/21

シンプルバッファーセレクタープラグイン buffer_selector.vim を作成した

シンプルバッファーセレクタープラグイン buffer_selector.vim を作成した。

mikoto2000/buffer_selector.vim: シンプルで簡単に使えるバッファーセレクター

目的と経緯

目的のバッファーへの切り替えをもっと簡単に行いたい。

今までは、:buffers してバッファー番号を確認した後 :buffer number でバッファを切り替えていた。 これが意外とつらい。

  1. :Unite buffer みたいに選びたいけど、Unite ヘビーなので入れたくない
  2. bufferlist.vim を試したけど、縦分割が気に入らない
  3. 勉強がてら作ってみようか

という感じ。

これ書きながら思ったのが、バッファーセレクターじゃなくて、 ファイルセレクターあたりも視野に入れてプラグイン探したほうが良かった気がする。

手順概要

大体こんな流れで実装していった。

  1. とりあえず書く
  2. 関数化して、それっぽい場所に移動
  3. help ドキュメントを書く
  4. plugin として切り出す

以下、各手順について説明していく。

1. とりあえず書く

適当なファイルにスクリプトを書いて、都度都度 source % で実行していった。

最初は、こんな感じのスクリプトを書いてバッファ一覧がとれるか確認した。

""" 変数 buffer_list に ``ls`` の結果を格納
let buffer_list=""
redir => buffer_list
silent ls
redir END

""" 新しいバッファを作成
new __BUFFERLIST__

""" __BUFFERLIST__ に ``ls`` の結果を表示
put!=buffer_list

その後、インクリメンタルに source % しながら実装していき、最終的にできたのがこれ。

""" 変数 buffer_list に ``:ls`` の結果を格納
let buffer_list=""
redir => buffer_list
silent ls
redir END

""" 新しいバッファを作成
if bufexists(bufnr('__BUFFERLIST__'))
    bwipeout! __BUFFERLIST__
endif
silent bo new __BUFFERLIST__

""" __BUFFERLIST__ に ``:ls`` の結果を表示
silent put!=buffer_list

""" 先頭と末尾が空行になるのでそれを削除
normal G"_dd
normal gg"_dd

""" ウィンドウサイズ調整
let current_win_height=winheight('%')
let line_num=line('$')
if current_win_height - line_num > 0
    execute "normal z" . line_num . "\<Return>"
endif

""" バッファリスト用バッファの設定
setlocal noshowcmd
setlocal noswapfile
setlocal buftype=nofile
setlocal bufhidden=delete
setlocal nobuflisted
setlocal nomodifiable
setlocal nowrap
setlocal nonumber

""" 選択したバッファに移動
map <buffer> <Return> ^viwy:bwipeout!<Return>:buffer <C-r>"<Return>
map <buffer> q :bwipeout!<Return>

2. 関数化して、それっぽい場所に移動

「1.」の段階で、 source % すれば所望の動きになることが確認できているので、 あとは

  1. 関数化して autoload に突っ込む
  2. .vimrc で関数を呼び出すマッピングを定義する

をすれば OK。

具体的に、どこにどう配置したかは、 コミット見るのが早そうなのでリンク張る。

Added simple buffer select process

3. help ドキュメントを書く

はじめてプラグインを作ってみた。それとhelpの書き方など - 反省はしても後悔はしない を参考に、 jax ファイルを作成。

これもコミットへのリンクのほうがわかりやすいか。

Added document of 'buffer_selector'.

4. plugin として切り出す

新しいリポジトリを作って作成したファイルを追加。

mikoto2000/buffer_selector.vim: シンプルで簡単に使えるバッファーセレクター

その後、もともと作っていたソースを削除し、代わりに、新しく作ったリポジトリをパッケージに登録。

Carve out 'buffer_selector.vim' to external plugin.

プラグイン作成作業は以上。

所感

だらだら作っていったけど、 プラグイン管理の仕組みを使ってすぐインストールできる vim プラグインが作れたからとりあえず満足した。

以上。

2016/11/15

Sphinx によるドキュメント執筆管理環境の検討

ここ数週間、隙間時間で悶々と考えていたことを吐き出す。

管理方法

一行で : 『Sphinx + VCS + Redmine + redmine_code_review』

  • Sphinx でドキュメントを作成する
  • ソースは VCS で管理
  • ビルドしたドキュメントはドキュメントサーバーにデプロイ & 共有ディレクトリに格納
  • ドキュメントのレビューは、 redmine_code_review プラグインを使い実施、管理する

※ VCS: できれば git + LFS, 次点で SVN

メリット

  • Excel 共有と比べて
    • 誰がいつ変更したかが失われない
    • コミットコメントのルールを決めることで、「何故」も記録できる
    • redmine_code_review の仕組みを使うことで、レビュー記録も Redmine に集約できる
  • Redmine の wiki と比べて
    • ビルドしてしまえばサーバーなしで参照できる

弱点

  • Excel のようにシームレスな作図ができない
  • reStructuredText がマイナー

reStructuredText 執筆のコツ

reStructuredText は、 tex, html などから続く『文章の意味と見た目が分離されているドキュメント』の一族。 執筆時には、文章構造に意識を集中すること。

これができると、あとは reStructuredText のルールに従って .rst に書き下していくだけで、誰でも同じ見た目の文章が作成できる。

Word, Excel と違い、編集するファイルの中に『見た目の情報』が存在しないため、 『うっかりフォントが変わった』や『ここだけインデントがずれた』 みたいなことがない。

ディレクトリ構成

docroot
   +- ワーキンググループ/
   |  +- ワーキンググループ_XXX/
   |  |  +- work/
   |  |  +- image/
   |  |  +- attachment/
   |  |  +- xxx.rst
   |  |  +- ワーキンググループの規模によってはサブディレクトリ作成も辞さない/
   |  |     +- work/
   |  |     +- image/
   |  |     +- attachment/
   |  |     +- yyy.rst
   |  |
   |  +- ワーキンググループ_ZZZ/
   |     +- ...(略)
   |
   +- 開発資料
   |  +- ...(略)
   |
   +- 運用資料
      +- ...(略)
  • image : 本文に表示する画像(png)を格納
  • work : image 加工用の元ネタを格納(xlsx, xcf 等)
  • attachment : 添付ファイルを格納

うーん、もやもやする。

2016/11/09

オープンソースカンファレンス 2016 Tokyo/Fall にいってきました

オープンソースカンファレンス 2016 Tokyo/Fall への参加記録として、殴り書きメモを張り付けていきます。

.NETで動くチケット管理ツール「プリザンター」

デフォルトで Redmine よりリッチなチケットトラッキングシステム。

  • OS は Windows 前提
  • デフォルトで WBS, ガントチャート, バーンダウンチャート, カンバンが使用可能
  • 既存の、 Excel, メール, 共有フォルダをプリザンターで置き換えられる
  • カスタムフィールドでグルーピングして集計みたいなことがリッチ UI でできる
  • VCS との連携がないのが残念

VCS 連携機能がないのが残念だけど、 全体的に Redmine よりリッチで使いやすそうな印象だった。 今の現場、管理用サーバーが Windows Server なので、これ使ってみたいが、 VCS 連携あたりでメンバに文句言われそう...。

今の現場ならいいけど、 「他の現場でノウハウが使えるか」とか考えてしまうと、 やっぱり導入ためらってしまう感じというのが正直なところか。

とりあえず触ってみないとか。

30分で分かるOSの作り方──自作OSもくもく会・出張版

  • OS とは
    • 他の OS の力を借りずに起動するソフトウェアのこと。
    • それぞれの作者が「OS」だと言い張って、周りが「まぁそうかな」と納得すればそれが OS。
  • 方向性
    • システムプログラミングを楽しむ
    • OS 理論を学ぶ
    • 実用的な OS を作る
    • 既存 OS を改良する
      • この発表でいう「OS 自作」ではない
  • OS 自作方法
    • 入門書を手に入れる
    • とりあえずその通りやる
      • 1 日 2 時間 x 30 日 くらい。
    • 改造する
  • 参考書
    • 30日でできる! OS自作入門
    • 12 ステップで作る組み込み OS 自作入門
  • 2016, osdev-jp 結成
  • 第 4 回 自作 OS もくもく会 11/26(土) 14:00 から

最近低レイヤの仕事してるのもあって、この辺への興味が増してしてきた。 実際作るかは置いておいて、OS 理論的なものの勉強はちょっとやっていかねば...。

ロケットや自動車にも搭載!高品質な組込み向けオープンソースを開発するTOPPERSプロジェクトのご紹介

遅刻。

  • Sessalelt
    • SESSAME(状態遷移図の設計セミナー)の成果物を実際に実装したもの
    • TOPPERS/EV3RT
    • 言語 : C or mruby
    • 状態の入れ子, 入れ子のない状態が存在するモデル
  • 状態マシン図設計セミナー
    • 11/28,29
    • Sessalet のモデルを持ち寄ってレビュー大会を開く
    • メーカーで設計していた人が講師
      • 今は社内でレビューを行っている
    • http://www.sessame.jp/seminar/Seminar2016_11/index.htm

mikutter会議2016東京

  • mikutter は Twitter クライアントではない
  • Pluggaloid
    • Yukari for Android
      • Pluggaloid on mruby on Androi!
  • mikutter 3.5
    • Model
      • ツイート, ユーザー, リストなど
      • ユーザーがカスタムモデルを作れるようになった
        • 適当なモデルを作ってタイムラインに流し込むと、よしなに表示してくれる

この辺からライブコーディングに夢中になってメモを忘れている...。

エンターテイメントなプレゼンだった。

進化の方向としては、モデルをさばくためのフレームワークだけ提供して、 モデルを作る(引っ張ってくる)部分とモデルを処理する部分は プラグインに任せる形になっていくっていう認識でいいのかな? この辺 Embulk とか Fluentd とかを思い出した。 この手のソフトウェア大好き。

ツイート以外のモデルを流しやすくなっているようなので、いろいろ触っていきたい。

AzureでOSSを気軽に試そう!~ LAMPからDevOpsまで ~

  • Microsoft には OS ハラスメントは無いみたい(Mac 使えるみたい)
  • けど、検索エンジンハラスメントはあるみたい(Bing 使えっていわれるみたい)

Azure で VM 作る実演。 Bitnami に、要求にマッチするイメージが存在すれば、数分で作成作業終わる感じ。 初期設定とかイメージの説明書読まないとだけど、その辺に慣れればすごい便利そうだった。

LT

みなさんネタと勢いのある素晴らしいプレゼン。見習いたい。(会社でやったら怒られるか...) Marp って初めて聞いたので試してみようと思った。

2016/11/08

VimConf 2016 に参加しました

VimConf 2016 への参加記録として、殴り書きメモを張り付けていきます。

Introduction to Vim 8.0

  • See :help version8
  • See :help channel-demo
  • See :help job_start()
  • See :help timer_start()
  • See :help Partial
    • Partial : 部分適用, コールバック等で便利らしい
  • See :help lambda
  • See :help closure
  • See :help window-id
    • Window に、不変の、一意な Window ID がつくようになったらしい。
  • See :help test-functions
  • See :help breakindent
    • マージに 10 年!
  • See :help renderoptions
  • Search Coveralls

知らない機能たくさん。特に、「Partial」「window-id」「breakindent」は今の自分に有用そうなので調べる。

VIM AS THE MAIN TEXT EDITOR

  • 「vimrc をオリジナルにする」、同感。
  • Vim に移行するためのモチベーションは何だろうか?
    • 仕事で使う必要があった
  • Vim を使うための準備運動
    • vim tutorial
    • VIMIUM
  • Vim を育てる
    • github で vimrc を検索
    • 内容を把握してコピペ
    • 気になったことを issue で書く
  • Q: Vim に移行して一番テンションの上がった機能は?
    • A: VimFiler, UI, 操作性が直感的で感動した

プロジェクトメンバに Vim 布教するにあたりこの辺のステップを参考にしていきたい。

Denite.nvim ~The next generation of unite~

NeoVim かー、 Python かー、速いのかー、うらやましいなー。って聞いてた。 (NeoVim 専用と誤解してた、NeoVim が Linux でしか動かないと思ってた。)

※ 懇親会にて Shougo さんに NeoVim は Windows ネイティブでも動くようになってるし、Bash on Ubuntu on Windows なら完璧に動くという話をしていただいたので試す。

Go、C、Pythonのためのdeoplete.nvimのソースの紹介と、Neovim専用にpure Goでvim-goをスクラッチした話

NeoVim かー、 Python かー、速いのかー、うらやましいなー。って聞いてた。

エディタの壁を超える Go の開発ツールの文化と作成方法

  • 特徴
    • 強力でシンプルな言語設計と文法
    • 平行プログラミング
    • 豊富なライブラリ
    • 豊富なツール
    • シングルバイナリ/クロスコンパイル
      • Windows 界隈だとシングルバイナリ便利
  • ツール群
    • govet
    • guru
    • gocode
    • errcheck
    • gorename
    • gomvpkg
  • Search gofmt -s

社内ツールで Go 使うときの宣伝文句としてスライド ぱくりたい 超参考になった。

vim-mode-plus for Atom editor

  • Search operation-stack
  • Search Vim で
  • Search occurrence
  • Search Vim で vip
  • Search Vim で「キャメルケース/スネークケース」変換

モーションとオペレータの考え方がわかりやすかった。 そのあたりを意識しながらコマンド使っていきたいと思った。

Vimの日本語ドキュメント

  • vim のドキュメント
    • vim-jp/vimdoc-ja
      • リファレンスとユーザーマニュアル
    • vim-jp/lang-ja
      • メニュー・メッセージ
    • Vim のユーザーマニュアルは、 usr_ で始まるやつ
  • Travis-CI 上で表記ゆれチェック
    • koron/nvcheck
  • vimdoc-ja の課題
    • 訳文の統一
      • 表記ゆれ
      • 文体の統一
    • 翻訳支援ツールの利用
      • 原文成形済み
        • なので、差分検出が難しい
          • なので、マークアップと成形ツールがほしい
      • これで、翻訳の品質向上を目指す

ドキュメント翻訳って、翻訳そのものも大変だけど、翻訳のための仕組み作りもまた大変なんだなぁ。 表記ゆれチェックはうちのプロジェクトに取り込めたら取り込んでいきたい。

Vim script parser written in Go

  • Linter
  • Fixer
  • Formatter
  • Completion

殴り書きで上記単語だけ書かれていた...。完全に内容についていけてなかった...。

僕の友達を紹介するよ

この辺試していきたい。

Best practices for building Vim plugins

  • ドキュメントを書きましょう
    • README を置くだけでは不十分
    • See :help design-documented
  • namespace を意識しましょう
    • 他プラグインと名前がバッティングしないように注意
    • プラグイン名を prefix にする
      • 勝手に省略するのはダメ
      • 実際どう呼ぶかはユーザーに任せる
    • プラグイン名を決める前にググる
    • 外部インターフェースの関数, 変数名も同じなので注意
  • autoload を使いましょう
    • plugin/xxx.vim には UI 定義のみ
    • 逆に言うと、 plugin/xxx.vim から autoload 内のコードを呼ぶのは残念な感じ
  • カスタマイズできるようにするのが Vim っぽい
    • 高カスタマイズ性
  • <Plut> キーマッピングを使いましょう
  • Plugin original buffer is useful
    • 実際のバッファに紐づかないバッファ?
    • BufReadCmd, BufWriteCmd
    • {plugin-name}://...
    • バッファを使うプラグインはスコープに注意
  • デフォルトで移動するキーのマッピングを上書きしちゃうと顰蹙を買うかも...
  • See <Leader>, <LocalReader>
  • Open API
  • マルチプラットフォーム対応しましょう
    • See :help design-multi-platform
  • テスト書くとよい
  • スクリプト内で省略形を使うのはダメ
    • 省略形はコマンドモードで楽に入力するためのもの

もりだくさん。 Vim script 書くときに意識していきたい。

所感

  • 書き殴ったことを消化・吸収しつつ、Vim 力を高めていきたい
  • NeoVim, Go を全くウォッチしていなかったのが悔やまれる
  • Windows で NeoVim 動かして deoplete.nvim を使ってみよう

2016/11/01

[Vim] Vim で、カーソル下の数値を変換したい

上から順に、

  • 2 進数変換
  • 10 進数変換
  • 16 進数変換
  • 数値の桁(ゼロオリジン)のマスク値に変換
  • 数値の桁(1オリジン)のマスク値に変換

という感じ。

マクロ

viwc^R=printf("0b%b", ^R")^M^[
viwc^R=printf("%d", ^R")^M^[
viwc^R=printf("0x%04X", ^R")^M^[
viwc^R=printf("0x%04X", printf("%.f", pow(2, ^R")))^M^[
viwc^R=printf("0x%04X", printf("%.f", pow(2, ^R"-1)))^M^[

コマンドバージョン

command! Num2b execute "normal viwc<C-R>=printf(\"0b%b\", <C-R>\")<Return><Esc>"
command! Num2d execute "normal viwc<C-R>=printf(\"%d\", <C-R>\")<Return><Esc>"
command! Num2x execute "normal viwc<C-R>=printf(\"0x%04X\", <C-R>\")<Return><Esc>"
command! Num2Mask0 execute "normal viwc<C-R>=printf(\"0x%04X\", printf(\"%.f\", pow(2, <C-R>\")))<Return><Esc>"
command! Num2Mask1 execute "normal viwc<C-R>=printf(\"0x%04X\", printf(\"%.f\", pow(2, <C-R>\"-1)))<Return><Esc>"

2016/10/28

[作業記録][Debian] Debian 8.5 最小構成インストールから Redmine3 + redmine_code_review を使えるようになるまで

環境

  • Debian 8.5 最小構成インストール
  • sudo, vim, ssh はインストール済み

目標

Debian 8.5 で、Redmine を使いたい、そしてコードレビューもしたい。

そのため、下記組み合わせで Redmine を使用できるようにする。

  • Redmine 3.3.1
  • redmine_code_review
  • sqlite3
  • Unicorn
  • nginx

Redmine と Nginx, Unicorn の連携については、このあたり の投稿を参考にすれば問題ないはずなので省略。

作業概要

  1. Redmine の準備
    1. 必要パッケージのインストール
    2. Redmine ソースコードの取得
    3. データベース設定
    4. 必要な gem のインストール
    5. デフォルトデータ作成
    6. secret token の準備
    7. 動作確認
  2. redmine_code_review の準備
    1. redmine_code_review ソースコードの取得と配置
    2. データベースのマイグレーション
    3. 動作確認

以下、各作業の詳細を記述していく。

Redmie の準備

必要パッケージのインストール

Redmine インストールにあたり、いろいろ必要なので apt でインストールする。

# ベースの最新化
sudo apt update
sudo apt upgrade

# rails のためのパッケージ
sudo apt install ruby-rails

# redmine の gem インストール時に必要になるものたち
sudo apt install zlib1g-dev pkg-config libmagickcore-dev libmagickwand-dev libsqlite3-dev

# Redmine を svn で取得してこれるように
sudo apt install subversion

Redmine ソースコードの取得

svn の stable ブランチからソースを取得する。今回は、 3.3-stable を取得する。

今回は、Redmine のルートディレクトリは /var/redmine とする。

sudo mkdir /var/redmine
sudo svn co https://svn.redmine.org/redmine/branches/3.3-stable /var/redmine
sudo chown -R www-data:www-data /var/redmine

データベース設定

今回は、 /var/redmine/db/redmine.sqlite3 を Redmine 用のデータベースとする。

1. ひな形コピー

cd /var/redmine
sudo -u www-data cp config/database.yml.example config/database.yml
sudo -u www-data vim config/database.yml

2. 設定ファイル編集

/var/redmine/db/redmine.sqlite3 を編集する。

# SQLite3 configuration example
production:
  adapter: sqlite3
  database: db/redmine.sqlite3

必要な gem のインストール

gem をインストール

cd /var/redmine
sudo -u www-data bundle install --path vendor/bundle

デフォルトデータ作成

cd /var/redmine
sudo -u www-data bundle exec rake db:migrate RAILS_ENV=production
sudo -u www-data bundle exec rake redmine:load_default_data RAILS_ENV=production

secret token の準備

セッション関係で使うトークンを生成するらしい。

cd /var/redmine
sudo -u www-data bundle exec rake generate_session_store

動作確認

cd /var/redmine
sudo -u www-data bundle exec rails server webrick -b 0.0.0.0 -e production

redmine_code_review の準備

redmine_code_review ソースコードの取得と配置

cd ~
wget https://bitbucket.org/haru_iida/redmine_code_review/downloads/redmine_code_review-0.7.0.zip
unzip redmine_code_review-0.7.0.zip
sudo -u www-data cp -r redmine_code_review /var/redmine/plugins

データベースのマイグレーション

cd /var/redmine
sudo -u www-data bundle exec rake redmine:plugins:migrate RAILS_ENV=production

動作確認

cd /var/redmine
sudo -u www-data bundle exec rails server webrick -b 0.0.0.0 -e production

2016/10/26 時点では、「コードレビュー」タブをクリックすると Internal Error になってしまう。 そのため、プロジェクトの設定で「コードレビュータブを隠す」にチェックを入れてタブを隠す。

以上。

2016/10/20

[作業記録] Windows で、Sphinx のスタンドアロンインストーラを試してみる

目標

Windows で Sphinx を使えるようにする。

環境

  • Windows Insider Build 14936
  • msys2 インストール済み
    • なので、コマンドプロンプトでも python 叩くと python 3.4.3 が起動する状態

作業概要

  1. インストーラーのダウンロード
  2. インストール

以下、各作業についての詳細を記述。

インストーラーのダウンロード

下記ページからインストーラーをダウンロードする。

Windowsへのインストール(スタンドアロンインストール) — Python製ドキュメンテーションビルダー、Sphinxの日本ユーザ会 : http://sphinx-users.jp/gettingstarted/install_windows_standalone.html

今回は、SphinxInstaller-1.4.1.20160416-py2.7-win32.zip をダウンロードした。

インストール

展開して出てきた SphinxInstaller-1.4.1.20160416-py2.7-win32.exe を管理者として実行する。

基本、デフォルトで OK, 好みがあれば適宜変更すればよい感じ。

動作確認

msys2 環境で実行。

mikoto@mnhomewin  ~
$ mkdir -p project/sphinx-test

mikoto@mnhomewin  ~
$ cd project/sphinx-test/

mikoto@mnhomewin  ~/project/sphinx-test
$ sphinx-quickstart

Welcome to the Sphinx 1.4.1 quickstart utility.

Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).

Enter the root path for documentation.
> Root path for the documentation [.]:

You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]: y

Inside the root directory, two more directories will be created; "_templates"
for custom HTML templates and "_static" for custom stylesheets and other static
files. You can enter another prefix (such as ".") to replace the underscore.
> Name prefix for templates and static dir [_]:

The project name will occur in several places in the built documentation.
> Project name: Test
> Author name(s): Mikoto2000

Sphinx has the notion of a "version" and a "release" for the
software. Each version can have multiple releases. For example, for
Python the version is something like 2.5 or 3.0, while the release is
something like 2.5.1 or 3.0a1.  If you don't need this dual structure,
just set both to the same value.
> Project version: 1.0.0
> Project release [1.0.0]:

If the documents are to be written in a language other than English,
you can select a language here by its language code. Sphinx will then
translate text that it generates into that language.

For a list of supported codes, see
http://sphinx-doc.org/config.html#confval-language.
> Project language [en]: ja

The file name suffix for source files. Commonly, this is either ".txt"
or ".rst".  Only files with this suffix are considered documents.
> Source file suffix [.rst]:

One document is special in that it is considered the top node of the
"contents tree", that is, it is the root of the hierarchical structure
of the documents. Normally, this is "index", but if your "index"
document is a custom template, you can also set this to another filename.
> Name of your master document (without suffix) [index]:

Sphinx can also add configuration for epub output:
> Do you want to use the epub builder (y/n) [n]:

Please indicate if you want to use one of the following Sphinx extensions:
> autodoc: automatically insert docstrings from modules (y/n) [n]:
> doctest: automatically test code snippets in doctest blocks (y/n) [n]:
> intersphinx: link between Sphinx documentation of different projects (y/n) [n]:
> todo: write "todo" entries that can be shown or hidden on build (y/n) [n]:
> coverage: checks for documentation coverage (y/n) [n]:
> imgmath: include math, rendered as PNG or SVG images (y/n) [n]:
> mathjax: include math, rendered in the browser by MathJax (y/n) [n]:
> ifconfig: conditional inclusion of content based on config values (y/n) [n]:
> viewcode: include links to the source code of documented Python objects (y/n) [n]:
> githubpages: create .nojekyll file to publish the document on GitHub pages (y/n) [n]:

A Makefile and a Windows command file can be generated for you so that you
only have to run e.g. `make html' instead of invoking sphinx-build
directly.
> Create Makefile? (y/n) [y]:
> Create Windows command file? (y/n) [y]:

Creating file .\source\conf.py.
Creating file .\source\index.rst.
Creating file .\Makefile.
Creating file .\make.bat.

Finished: An initial directory structure has been created.

You should now populate your master file .\source\index.rst and create other documentation
source files. Use the Makefile to build the docs, like so:
   make builder
where "builder" is one of the supported builders, e.g. html, latex or linkcheck.

mikoto@mnhomewin  ~/project/sphinx-test
$ make html
sphinx-build -b html -d build/doctrees   source build/html
Running Sphinx v1.4.1
making output directory...
loading translations [ja]... done
loading pickled environment... not yet created
building [mo]: targets for 0 po files that are out of date
building [html]: targets for 1 source files that are out of date
updating environment: 1 added, 0 changed, 0 removed
reading sources... [100%] index
looking for now-outdated files... none found
pickling environment... done
checking consistency... done
preparing documents... done
writing output... [100%] index
generating indices... genindex
writing additional pages... search
copying static files... done
copying extra files... done
dumping search index in Japanese (code: ja) ... done
dumping object inventory... done
build succeeded.

Build finished. The HTML pages are in build/html.

mikoto@mnhomewin  ~/project/sphinx-test
$ start build/html/index.html

これで、 sphinx のウェルカムページが見えるはず。 ...msys2 環境でやるなら pacman で入れたほうが良くなかったか?

動作確認 on コマンドプロンプト

ということでコマンドプロンプトで試す。

C:\Users\mikoto>mkdir -p project\sphinx-test

C:\Users\mikoto>cd project\sphinx-test

C:\Users\mikoto\project\sphinx-test>sphinx-quickstart
Welcome to the Sphinx 1.4.1 quickstart utility.

Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).

Enter the root path for documentation.
> Root path for the documentation [.]:

You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]: y

Inside the root directory, two more directories will be created; "_templates"
for custom HTML templates and "_static" for custom stylesheets and other static
files. You can enter another prefix (such as ".") to replace the underscore.
> Name prefix for templates and static dir [_]:

The project name will occur in several places in the built documentation.
> Project name: Test2
> Author name(s): Mikoto2000

Sphinx has the notion of a "version" and a "release" for the
software. Each version can have multiple releases. For example, for
Python the version is something like 2.5 or 3.0, while the release is
something like 2.5.1 or 3.0a1.  If you don't need this dual structure,
just set both to the same value.
> Project version: 1.0.0
> Project release [1.0.0]:

If the documents are to be written in a language other than English,
you can select a language here by its language code. Sphinx will then
translate text that it generates into that language.

For a list of supported codes, see
http://sphinx-doc.org/config.html#confval-language.
> Project language [en]: ja

The file name suffix for source files. Commonly, this is either ".txt"
or ".rst".  Only files with this suffix are considered documents.
> Source file suffix [.rst]:

One document is special in that it is considered the top node of the
"contents tree", that is, it is the root of the hierarchical structure
of the documents. Normally, this is "index", but if your "index"
document is a custom template, you can also set this to another filename.
> Name of your master document (without suffix) [index]:

Sphinx can also add configuration for epub output:
> Do you want to use the epub builder (y/n) [n]:

Please indicate if you want to use one of the following Sphinx extensions:
> autodoc: automatically insert docstrings from modules (y/n) [n]:
> doctest: automatically test code snippets in doctest blocks (y/n) [n]:
> intersphinx: link between Sphinx documentation of different projects (y/n) [n]:
> todo: write "todo" entries that can be shown or hidden on build (y/n) [n]:
> coverage: checks for documentation coverage (y/n) [n]:
> imgmath: include math, rendered as PNG or SVG images (y/n) [n]:
> mathjax: include math, rendered in the browser by MathJax (y/n) [n]:
> ifconfig: conditional inclusion of content based on config values (y/n) [n]:
> viewcode: include links to the source code of documented Python objects (y/n) [n]:
> githubpages: create .nojekyll file to publish the document on GitHub pages (y/n) [n]:

A Makefile and a Windows command file can be generated for you so that you
only have to run e.g. `make html' instead of invoking sphinx-build
directly.
> Create Makefile? (y/n) [y]:
> Create Windows command file? (y/n) [y]:

Creating file .\source\conf.py.
Creating file .\source\index.rst.
Creating file .\Makefile.
Creating file .\make.bat.

Finished: An initial directory structure has been created.

You should now populate your master file .\source\index.rst and create other documentation
source files. Use the Makefile to build the docs, like so:
   make builder
where "builder" is one of the supported builders, e.g. html, latex or linkcheck.

C:\Users\mikoto\project\sphinx-test>make.bat html
Running Sphinx v1.4.1
making output directory...
loading translations [ja]... done
loading pickled environment... not yet created
building [mo]: targets for 0 po files that are out of date
building [html]: targets for 1 source files that are out of date
updating environment: 1 added, 0 changed, 0 removed
reading sources... [100%] index
looking for now-outdated files... none found
pickling environment... done
checking consistency... done
preparing documents... done
writing output... [100%] index
generating indices... genindex
writing additional pages... search
copying static files... done
copying extra files... done
dumping search index in Japanese (code: ja) ... done
dumping object inventory... done
build succeeded.

Build finished. The HTML pages are in build/html.

C:\Users\mikoto\project\sphinx-test>start build\html\index.html

うん、OK です。

msys2 環境が悪さしないで良かった。

2016/10/19

[作業記録][Debian] Sphinx を使ってみたい

環境

  • Debian 8.5 最小構成インストール
  • sudo, vim, ssh はインストール済み

目標

Sphinx でドキュメントを作成し、生成した html を Nginx で公開する。

作業

下記手順で作業を行う。

  1. 必要パッケージのインストール
  2. sphinx プロジェクトの作成
  3. ドキュメント作成
  4. ドキュメントビルド
  5. html を配置

必要パッケージのインストール

make が必要なの注意。

sudo apt install python3-sphinx
sudo apt install nginx
sudo apt install make

sphinx プロジェクトの作成

Separate source and build directoriesy のほうが管理しやすい感じがした。 その他はよしなにする感じで。

mikoto@debian-base:~$ mkdir -p sphinx/test
mikoto@debian-base:~$ cd sphinx/test/
mikoto@debian-base:~/sphinx/test$ sphinx-quickstart
Welcome to the Sphinx 1.2.3 quickstart utility.

Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).

Enter the root path for documentation.
> Root path for the documentation [.]:     

You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]: y

Inside the root directory, two more directories will be created; "_templates"
for custom HTML templates and "_static" for custom stylesheets and other static
files. You can enter another prefix (such as ".") to replace the underscore.
> Name prefix for templates and static dir [_]: 

The project name will occur in several places in the built documentation.
> Project name: Test
> Author name(s): Mikoto2000

Sphinx has the notion of a "version" and a "release" for the
software. Each version can have multiple releases. For example, for
Python the version is something like 2.5 or 3.0, while the release is
something like 2.5.1 or 3.0a1.  If you don't need this dual structure,
just set both to the same value.
> Project version: 1.0.0
> Project release [1.0.0]: 

The file name suffix for source files. Commonly, this is either ".txt"
or ".rst".  Only files with this suffix are considered documents.
> Source file suffix [.rst]: 

One document is special in that it is considered the top node of the
"contents tree", that is, it is the root of the hierarchical structure
of the documents. Normally, this is "index", but if your "index"
document is a custom template, you can also set this to another filename.
> Name of your master document (without suffix) [index]: 

Sphinx can also add configuration for epub output:
> Do you want to use the epub builder (y/n) [n]: 

Please indicate if you want to use one of the following Sphinx extensions:
> autodoc: automatically insert docstrings from modules (y/n) [n]: 
> doctest: automatically test code snippets in doctest blocks (y/n) [n]: 
> intersphinx: link between Sphinx documentation of different projects (y/n) [n]: 
> todo: write "todo" entries that can be shown or hidden on build (y/n) [n]: 
> coverage: checks for documentation coverage (y/n) [n]: 
> pngmath: include math, rendered as PNG images (y/n) [n]: 
> mathjax: include math, rendered in the browser by MathJax (y/n) [n]: 
> ifconfig: conditional inclusion of content based on config values (y/n) [n]: 
> viewcode: include links to the source code of documented Python objects (y/n) [n]: 

A Makefile and a Windows command file can be generated for you so that you
only have to run e.g. `make html' instead of invoking sphinx-build
directly.
> Create Makefile? (y/n) [y]: 
> Create Windows command file? (y/n) [y]: n

Creating file ./source/conf.py.
Creating file ./source/index.rst.
Creating file ./Makefile.

Finished: An initial directory structure has been created.

You should now populate your master file ./source/index.rst and create other documentation
source files. Use the Makefile to build the docs, like so:
   make builder
where "builder" is one of the supported builders, e.g. html, latex or linkcheck.

こんな感じのディレクトリ構成になります。

mikoto@debian-base:~/sphinx/test$ find ./ -maxdepth 2 
./
./build
./Makefile
./source
./source/conf.py
./source/index.rst
./source/_templates
./source/_static

ドキュメント作成

適当にドキュメントを作ります。

今回は、test.rst を作成して、 index.rsttoctreetest.rst を追加。

mikoto@debian-base:~/sphinx/test$ cat source/test.rst 
====
test
====

Hello Sphinx document!

mikoto@debian-base:~/sphinx/test$ cat source/index.rst 
.. Test documentation master file, created by
   sphinx-quickstart on Tue Oct 18 23:52:34 2016.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

Welcome to Test's documentation!
================================

Contents:

.. toctree::
   :maxdepth: 2

   test


Indices and tables
==================


* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

ドキュメントビルド

プロジェクトルートで make html するだけ。

mikoto@debian-base:~/sphinx/test$ make html
sphinx-build -b html -d build/doctrees   source build/html
Making output directory...
Running Sphinx v1.2.3
loading pickled environment... failed: [Errno 2] No such file or directory: '/home/mikoto/sphinx/test/build/doctrees/environment.pickle'
building [html]: targets for 2 source files that are out of date
updating environment: 2 added, 0 changed, 0 removed
reading sources... [100%] test                                                                                       looking for now-outdated files... none found
pickling environment... done
checking consistency... done
preparing documents... done
writing output... [100%] test                                                                                        writing additional files... genindex search
copying static files... done
copying extra files... done
dumping search index... done
dumping object inventory... done
build succeeded.

build/html に html ファイルが生成される。

html を配置

生成された heml ファイルをそのまま nginx のドキュメントルートに突っ込んでしまえば OK。

mikoto@debian-base:~/sphinx/test$ sudo cp -r build/html/* /var/www/html/

これで、 http://ホスト名/ にアクセスすると、生成した Sphinx ドキュメントが参照できるようになっているはず。

以上。

2016/10/18

[作業記録][Debian] Debian 最小構成から Redmine を動かすまで(3) - Nginx インストールから自動起動設定まで -

環境

  • Debian 8.5 最小構成インストール
  • sudo, vim, ssh はインストール済み
  • Redmine は準備済み(前々回の投稿)
  • Unicorn はインストール済み(前回の投稿)

目標

Redmine + sqlite3 + Nginx + Unicorn な環境を作る。

今回は、 Nginx のインストールから、デーモンとして自動起動するための設定まで。

Unicorn の準備

nginx と unicorn を socket で連携させるための設定を行う。

  1. /var/redmine/config/unicorn.rblisten "/var/redmine/tmp/unicorn.sock" を追加
  2. unicorn リスタート

Nginx の準備

Nginx をインストールし、 Unicorn との連携するための設定を行う。

Nginx のインストール

sudo apt install nginx

Nginx の設定

  1. デフォルトの設定を無効化
  2. redmine 用の設定ファイル作成
  3. redmine 用の設定を有効化

デフォルトの設定を無効化

sudo rm /etc/nginx/sites-enabled/default

redmine 用の設定ファイル作成

デフォルト設定をコピーし、redmine 用の設定ファイルにする。

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/redmine.conf

redmine 用設定ファイル /etc/nginx/sites-available/redmine.conf を修正する。

# redmine minimum configuration
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        location / {
                proxy_pass http://unix:/var/redmine/tmp/unicorn.sock;
        }
}

redmine 用の設定を有効化

sudo ln -s /etc/nginx/sites-available/redmine.conf /etc/nginx/sites-enabled/redmine.conf

Nginx の動作確認

sudo service nginx restart

この後、http://ホスト名:80/ にアクセスすれば、 redmine のトップページが見れるはず。

以上。

2016/10/02

[作業記録][Debian] Debian 最小構成から Redmine を動かすまで(2) - Unicorn インストールから自動起動設定まで -

環境

  • Debian 8.5 最小構成インストール
  • sudo, vim, ssh はインストール済み
  • Redmine は準備済み(前回の投稿)

目標

Redmine + sqlite3 + Nginx + Unicorn な環境を作る。

今回は、 Unicorn のインストールから、デーモンとして自動起動するための設定まで。

手順概要

Unicorn の準備

Unicorn のインストール

sudo apt install unicorn

Unicorn の設定

/etc/default/unicorn

デフォルトで起動する unicorn の起動スクリプト設定ファイルは /etc/default/unicorn にあるのでこれを編集。 APP_ROOT を Redmine のルートディレクトリに修正。

これと、起動スクリプトをコピーして、 Rails アプリごとに Unicorn サーバーを立てるのが普通なのかな?動なんだろうか。

# Change paramentres below to appropriate values and set CONFIGURED to yes.
# CONFIGURED=no
CONFIGURED=yes

# Default timeout until child process is killed during server upgrade,
# it has *no* relation to option "timeout" in server's config.rb.
TIMEOUT=60

# Path to your web application, sh'ld be also set in server's config.rb,
# option "working_directory". Rack's config.ru is located here.
# APP_ROOT=/path/to/your/web/application
APP_ROOT=/var/redmine

# Server's config.rb, it's not a rack's config.ru
# CONFIG_RB="$APP_ROOT/unicorn.conf.rb"
CONFIG_RB="$APP_ROOT/config/unicorn.rb"

# Where to store PID, sh'ld be also set in server's config.rb, option "pid".
# PID=/run/unicorn.pid
PID=/var/redmine/run/unicorn.pid

# Additional arguments passed to unicorn, see man (1) unicorn.
# UNICORN_OPTS="-D -c $CONFIG_RB"
UNICORN_OPTS="/var/redmine/config.ru -D -c $CONFIG_RB -E production"

/var/redmine/config/unicorn.rb

unicorn の設定ファイルは、ひな形が /usr/share/doc/unicorn/examples/unicorn.conf.minimal.rb にあるので、それをコピーして使用する。コピー先は、 /etc/default/unicorn 内の CONFIG_RB の設定値(今回は /var/redmine/config/unicorn.rb)。

sudo -u www-data cp /usr/share/doc/unicorn/examples/unicorn.conf.minimal.rb /var/redmine/config/unicorn.rb

下記のように修正。

# Minimal sample configuration file for Unicorn (not Rack) when used
# with daemonization (unicorn -D) started in your working directory.
#
# See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
# documentation.
# See also http://unicorn.bogomips.org/examples/unicorn.conf.rb for
# a more verbose configuration using more features.

listen 2007 # by default Unicorn listens on port 8080
worker_processes 2 # this should be >= nr_cpus
# pid "/path/to/app/shared/pids/unicorn.pid"
pid "/var/redmine/run/unicorn.pid"
stderr_path "/var/redmine/log/unicorn_stderr.log"
# stderr_path "/path/to/app/shared/log/unicorn.log"
stdout_path "/var/redmine/log/unicorn_stdout.log"
# stdout_path "/path/to/app/shared/log/unicorn.log"

ディレクトリ作成

ログ出力先と PID 出力先を作成。

cd /var/redmine
sudo -u www-data mkdir run log

Unicorn の動作確認(手動)

cd /var/redmine
sudo -u www-data unicorn -c config/unicorn.rb -E production

これで、ホストの 2007 ポートにアクセスすれば、 Redmine のトップページが見れるはず。 終了は Ctrl-D で。

起動スクリプトの準備

/etc/init.c/unicorn がそのままだと動かなかったので修正。

PID と、起動時のオプションを変えた。

起動スクリプト修正

#!/bin/sh
### BEGIN INIT INFO
# Provides:          unicorn
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: unicorn initscript
# Description:       unicorn
### END INIT INFO

set -e

NAME=unicorn
DESC="Unicorn web server"

. /lib/lsb/init-functions

if [ -f /etc/default/unicorn ]; then
  . /etc/default/unicorn
fi

DAEMON=/usr/bin/unicorn
# PID=${PID-/run/unicorn.pid}
PID=/var/redmine/run/unicorn.pid

run_by_init() {
    ([ "${previous-}" ] && [ "${runlevel-}" ]) || [ "${runlevel-}" = S ]
}

exit_with_message() {
  if ! run_by_init; then
    log_action_msg "$1 Not starting."
  fi
  exit 0
}

check_config() {
  if [ $CONFIGURED != "yes" ]; then
    exit_with_message "Unicorn is not configured (see /etc/default/unicorn)."
  fi
}

check_app_root() {
  if ! [ -d $APP_ROOT ]; then
    exit_with_message "Application directory $APP_ROOT is not exist."
  fi
}

set -u

case "$1" in
  start)
        check_config
        check_app_root

        log_daemon_msg "Starting $DESC" $NAME || true
#         if start-stop-daemon --start --quiet --oknodo --pidfile $PID --exec $DAEMON -- $UNICORN_OPTS; then
        if start-stop-daemon --start --chdir /var/redmine --quiet --oknodo --pidfile $PID --exec $DAEMON -- $UNICORN_OPTS; then
          log_end_msg 0 || true
        else
          log_end_msg 1 || true
        fi
              ;;
  stop)
        log_daemon_msg "Stopping $DESC" $NAME || true
        if start-stop-daemon --stop --signal QUIT --quiet --oknodo --pidfile $PID; then
          log_end_msg 0 || true
        else
          log_end_msg 1 || true
        fi
        ;;
  force-stop)
        log_daemon_msg "Forcing stop of $DESC" $NAME || true
        if start-stop-daemon --stop --quiet --oknodo --pidfile $PID; then
          log_end_msg 0 || true
        else
          log_end_msg 1 || true
        fi
        ;;
  restart|force-reload)
        log_daemon_msg "Restarting $DESC" $NAME || true
        start-stop-daemon --stop --quiet --oknodo --pidfile $PID
        sleep 1
        if start-stop-daemon --start --quiet --oknodo --pidfile $PID --exec $DAEMON -- $UNICORN_OPTS; then
          log_end_msg 0 || true
        else
          log_end_msg 1 || true
        fi
        ;;
  reload)
        log_daemon_msg "Reloading $DESC" $NAME || true
        if start-stop-daemon --stop --signal HUP --quiet --oknodo --pidfile $PID; then
          log_end_msg 0 || true
        else
          log_end_msg 1 || true
        fi
        ;;
  reopen-logs)
        log_daemon_msg "Relopening log files of $DESC" $NAME || true
        if start-stop-daemon --stop --signal USR1 --quiet --oknodo --pidfile $PID; then
          log_end_msg 0 || true
        else
          log_end_msg 1 || true
        fi
        ;;
  status)
        status_of_proc -p $PID $DAEMON $NAME && exit 0 || exit $?
        ;;
  *)
        log_action_msg "Usage: $0 <start|stop|restart|force-reload|reload|force-stop|reopen-logs|status>" || true
        exit 1
        ;;
esac

systemctl 更新

sudo systemctl daemon-reload

動作確認

起動確認

sudo service unicorn start

終了確認

sudo service unicorn stop