読者です 読者をやめる 読者になる 読者になる

DRYな備忘録

Don't Repeat Yourself.

RedHatにGo言語をインストール(というか配置)

$ cd
$ mkdir -p opt/src
$ cd opt/src
$ wget https://storage.googleapis.com/golang/go1.8.1.linux-amd64.tar.gz
$ tar zxvf go1.8.1.linux-amd64.tar.gz
$ mv go ~/opt/.go # GOROOT用
$ mkdir -p ~/proj/go # GOPATH用
$ export GOROOT=~/opt/.go
$ export GOPATH=~/proj/go
$ export PATH=$GOROOT/bin:$GOPATH/bin:$PATH
$ go version
go version go1.8.1 linux/amd64

確認

$ go get github.com/otiai10/primes/primes
$ which primes
~/proj/go/bin/primes
$ primes p 100
[2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]

いけてる。Goのインストールは手軽で明確でほんとに好きだなあ。

DRYな備忘録として

Macにsamtoolsをインストール

ゴール

  • macOS Sierra上でsamtoolsコマンドが使える

参考

ログ

% cd
% mkdir opt
% mkdir opt/src
% cd opt/src
% wget https://github.com/samtools/htslib/releases/download/1.4/htslib-1.4.tar.bz2
% tar jxvf htslib-1.4.tar.bz2
% cd htslib-1.4
% ./configure --prefix=$HOME/opt
# 中略
configure: error: liblzma development files not found
# 後略

ふむ

% brew search liblzma
lzma is now part of the xz formula.
% brew search lzma-devel
lzma is now part of the xz formula.
% brew search xz-devel
No formula found for "xz-devel".

lzmaはxzになったけど、liblzmaの名前で探しにこられててnot foundとなっているような気がする。xzを入れればいいのかな。

% brew install xz
% ./configure --prefix=$HOME/opt
# いけたっぽい
% make
# warningは多数出てるけどとりあえず最後まで行ったっぽい
% make install
% ll ~/opt
total 0
drwxr-xr-x   7 otiai10  staff   238  4 13 10:24 .
drwxr-xr-x+ 39 otiai10  staff  1326  4 13 10:06 ..
drwxr-xr-x   5 otiai10  staff   170  4 13 10:24 bin
drwxr-xr-x   3 otiai10  staff   102  4 13 10:24 include
drwxr-xr-x   7 otiai10  staff   238  4 13 10:24 lib
drwxr-xr-x   3 otiai10  staff   102  4 13 10:24 share
drwxr-xr-x   4 otiai10  staff   136  4 13 10:06 src

コマンドPATHを通す

% which htsfile
htsfile not found
% export PATH=$HOME/opt/bin:$PATH
% which htsfile
/Users/otiai10/opt/bin/htsfile
% man htsfile
# いい感じ

LIBRARY PATHを通す

export LD_LIBRARY_PATH=$HOME/opt/lib:$LD_LIBRARY_PATH

samtoolsのインストール

% cd $HOME/opt/src
% wget https://github.com/samtools/samtools/releases/download/1.4/samtools-1.4.tar.bz2
% tar jxvf samtools-1.4.tar.bz2
% cd samtools-1.4
% ./configure --prefix=$HOME/opt
% make
% make install

確認

% which samtools
/Users/otiai10/opt/bin/samtools
% man samtools

イケてる。

はじめてのバイオインフォマティクス (KS生命科学専門書)

はじめてのバイオインフォマティクス (KS生命科学専門書)

DRYな備忘録

RustをMacにインストールしてHelloWorldとFizzBuzz

Rust、話題なので、やってみる。ミーハーなので。

brew install rust

% brew install rust
% rustc -V
rustc 1.16.0
% cargo -V
cargo-0.17.0-dev (f9e5481 2017-03-03)

Hello, Rust!

% cd
% mkdir -p proj/rust/playground/hello
% cd proj/rust/playground/hello
fn main() {
    println("ハロー, Rust!");
}
% rustc hello.rs
error[E0423]: expected function, found macro `println`
 --> hello.rs:2:5
  |
2 |     println("ハロー, Rust!");
  |     ^^^^^^^ did you mean `println!(...)`?

error: aborting due to previous error

%

めっちゃ親切やん

fn main() {
-    println("ハロー, Rust!");
+    println!("ハロー, Rust!");
}
% rustc hello.rs
% ./hello
ハロー, Rust!
%

できた

Write & Runがだるい

コンパイルして、実行ファイルを実行、っていう流れがだるいな、って思ったら、cargo runというのがあるっぽい。本当はプロジェクトつくるときにcargo newするのが作法のようで、cargo newするとtestsも自動的につくってくれるっぽい。いいっぽい。今回は後からCargo.tomlを追加した。

FizzBuzz

こういう感じにしたい

% fizzbuzz 15
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
FizzBuzz!!!

こうなった

use std::env;

fn fizzbuzz(x: i8) {
    for i in 1..(x + 1) {
        match (i % 3, i % 5) {
            (0, 0) => println!("FizzBuzz!!!"),
            (0, _) => println!("fizz"),
            (_, 0) => println!("buzz"),
            _ => println!("{}", i),
        }
    }
}

fn main() {
    match env::args().last().unwrap().parse::<i8>() {
        Ok(x) => fizzbuzz(x),
        Err(err) => println!("数字を指定してください: {}", err),
    }
}

結果

% cargo run 18
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/fizzbuzz 18`
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
FizzBuzz!!!
16
17
fizz

いい感じ。成果物です。

github.com

コミットの細かさには定評がある僕です。

参考

雑感

  • とりあえず書き始めたけど、思ったより難しくて、ちゃんとチュートリアル読まなあかんな、と思った
  • わりと楽しく書けそう

Programming Rust: Fast, Safe Systems Development

Programming Rust: Fast, Safe Systems Development

webpackのプロジェクトでWebWorker書いててつまずいたメモ

まずnew Worker(“./my/worker”) というやつ

Workerのコンストラクタにファイルパスを渡すやつからしてwebpackだとどう解決されるのか問題。

以上を参考にして、まず

npm install --save-dev worker-loader

つぎに、webpack.config.jsで

var plugins = [
    new webpack.LoaderOptionsPlugin({
        options: {
            worker: {
                output: {
                    filename: "dest/js/worker.[id].js",
                }
            }
        }
    })
];

として、自作のWorkerを使いたいほうは、

var Worker = require("worker-loader?inline!../../../Workers/my/worker");

とかしとくと

webpack 2.2の標準出力では

Child worker:
                  Asset     Size  Chunks             Chunk Names
    dest/js/worker.0.js  4.59 kB       0  [emitted]  main
       [1] ./~/babel-loader/lib!./src/js/Components/Workers/my/worker.js 1.24 kB {0} [built]
        + 1 hidden modules

となって、生成物としては、以下の648がWorkerを引っ張る共通処理、649が、648を使って自作のWorkerを提供する処理になっているので、

/***/ 648:
/***/ (function(module, exports) {

// http://stackoverflow.com/questions/10343913/how-to-create-a-web-worker-from-a-string

var URL = window.URL || window.webkitURL;
module.exports = function(content, url) {
    try {
        try {
            var blob;
            try { // BlobBuilder = Deprecated, but widely implemented
                var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
                blob = new BlobBuilder();
                blob.append(content);
                blob = blob.getBlob();
            } catch(e) { // The proposed API
                blob = new Blob([content]);
            }
            return new Worker(URL.createObjectURL(blob));
        } catch(e) {
            return new Worker('data:application/javascript,' + encodeURIComponent(content));
        }
    } catch(e) {
        return new Worker(url);
    }
}

/***/ }),

/***/ 649:
/***/ (function(module, exports, __webpack_require__) {

module.exports = function() {
    return __webpack_require__(648)("/** 略 **/", __webpack_require__.p + "dest/js/worker.0.js");
};

このWorkerを使いたいほうでは、649を使ってWorkerインスタンスを作っていることが予想される。以下の通り。

var Worker = __webpack_require__(649);

const worker = new Worker();

となって、うまいことWorkerをwebpackでロードできている感じになった。

importScriptsがどこなの問題

このエントリ書いてるのが2017/02/19 (CET) で、このissueが立ったのが02/08、コントリビュータがbugのlabelをつけたのが02/17なので、なかなかホット。実際、webpackの成果物で、importScriptsをしている部分を見ると、

importScripts("../foo.js", "../bar.js");

importScripts("../foo.js", "../bar.js");

となっており、webpack@2.2.1の時点でimportScripts内のコンテキストは解決されず、生成されたworkerなjsファイル(今回のケースでいうとdest/js/worker.0.js)に対する相対pathを書く必要がある。

TODO: このissueに動きがあったらここに追記する

番外: Chrome拡張において

Chrome拡張においてうまいことdest/js/worker.0.jsというworkerから相対pathでimportScriptsしてくれなかったので、完全なURLを渡す必要があり、以下のようにした。

自作Worker

import imports from "../imports";

const _init = (data) => {
    imports(data.root)("dest/js/nice-lib-x.js", "dest/js/cool-lib-y.js");
};
onmessage = (ev) => {
    switch(ev.data.cmd) {
    case "init": return _init(ev.data);
    case "なんか他のこといろいろ": return _awesome_action(ev.data);
    default:
        return;
    };
};

自作べんりimports関数

/**
 * Workerのコンテキストではchromeは参照できないので、
 * Chrome拡張自体の持つルートディレクトリのURLを
 * アプリケーション側からもらって、それをimportScriptsする必要があるよ。
 */
export default function imports(root) {
    return function() {
        // ↑
        // ここをアローで書くと、argumentsの参照がwebpackによって
        // カリー化関数自体のargumentsに固定されてしまうので
        // functionキーワードで書く必要がある
        if (!root) throw "importScriptsする場合は必ずrootを指定してください";
        const _root = root.replace(/\/+$/, "/"); // ケツの/の重複をきれいにするだけ
        importScripts(...Array.prototype.map.call(arguments, path => _root + path));
    };
}

自作Worker呼ぶ方

var Worker = require("worker-loader?inline!../../../Workers/my/worker");

const worker = new Worker();
worker.postMessage({
    cmd: "init",
    root: chrome.extension.getURL("/")
});

これでうまい感じに

chrome-extension://{extensionId}/dest/js/nice-lib-x.jsに定義した色々が自作Workerの中でアレできるようになった。

雑感

  • webpackちょっとわかってきた
  • さいきんReact/ReactNativeばっかり書いてて頭おかしくなりそう
  • ベルリンのスタートアップはいろいろつらい。早く日本に帰りたい
  • ベルリンは好きだ
    • ビール安い
    • ソーセージをはじめ、肉が安い
    • 食材が安いので料理がたのしい
  • SAOの劇場版、ドイツでやってるっぽい

sao-movie.net

DRYな備忘録として

初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発

初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発

react-routerでページを共通Layoutに乗せたりログイン画面は乗せなかったりするルーティングの設定

import React from 'react';
import ReactDOM from 'react-dom'
import {Router, Routes, browserHistory} from 'react-router';

import {MyFancyLayout} from '../../layouts';
import {
    LoginPage, // これと
    HomePage,
    SettingPage,
    NotFoundPage, // これは、レイアウト適用外
} from '../../pages';

ReactDOM.render(
    <Router history={browserHistory}>
        <Route path="/login" component={LoginPage} />
        <Route path="/" component={MyFancyLayout}>
            <IndexRoute component={HomePage} />
            <Route path="/home" component={HomePage} />
            <Route path="/settings" component={SettingsPage} />
        </Route>
        <Route path="*" component={NotFoundPage} />
    </Router>,
    document.querySelector('div#app')
);
// こうしとくと、MyFancyLayoutコンポーネントにおいて
// ネストされたroutesで指定されたコンポーネントが
// props.childrenとして得られるので、renderとかで使えばよい
  • IndexRoute を定義しないと、/レンダリングされない
  • MyFancyLayoutのRouteで*とするとMyFancyLayoutのprops.childrenがundefinedになる

のでちょっとハマった

DRYな備忘録として

入門 React ―コンポーネントベースのWebフロントエンド開発

入門 React ―コンポーネントベースのWebフロントエンド開発

Draft.jsを使ってContentEditableなdivに絵文字をレンダリングしつつ編集可能にする

ぜったいなんかやり方あるだろと思いつつなかなか見つからなくてググり続けたりして6時間ぐらいハマったのでメモ。

f:id:otiai10:20170208000633g:plain

import React from 'react';

import {Editor, EditorState, CompositeDecorator} from 'draft-js';

const getEmojiURL = (key) => {
  // TODO: ここで、:shit:とかくるので、対応したURLを返せばよい
  switch(key) {
  case ':smile:': return 'https://twemoji.maxcdn.com/svg/1f603.svg';
  case ':shit:':  return 'https://twemoji.maxcdn.com/svg/1f4a9.svg';
  default: return null;
  }
};

const Emoji = (props) => {
  const url = getEmojiURL(props.decoratedText);
  if (!url) return <span>{props.children}</span>;
  return (
    <div style={{
      display:'inline-block',
      overflow:'hidden',
      width:'16px',
      height:'16px',
      backgroundImage: `url('${url}')`,
      color: 'transparent',
    }}>{props.children}</div>
  );
};

const EmojiDecorator = {
  strategy: (block, callback /* , content */) => {
    const text = block.getText();
    const regex = /:[^(:| )]+:/g;
    let matched;
    while ((matched = regex.exec(text)) !== null) {
      const start = matched.index, end = start + matched[0].length;
      callback(start, end);
    }
  },
  component: Emoji,
};

const decorator = new CompositeDecorator([
  EmojiDecorator,
]);

export default class MyNiceEditor extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      editorState: EditorState.createEmpty(decorator),
    };
  }
  onChange(editorState) {
    this.setState({editorState});
  }
  render() {
    return (
        <Editor
          editorState={this.state.editorState}
          onChange={this.onChange.bind(this)}
        />
    );
  }
}

とりあえず欲しい感じになったけど、もっと良い方法あるだろうという気持ちですので、ご存知の方おられましたら是非ともご教示ください :bow:

DRYな備忘録として

jestでTypeError: Cannot read property 'instrument' of undefinedと叱られる

とりあえず

./node_modules/.bin/jest --no-cache
# package.jsonのscriptsや、-gで入れてる場合は、 "jest --no-cache" ですもちろん。

としたら通った。

DRY

Learning React Native: Building Native Mobile Apps with JavaScript

Learning React Native: Building Native Mobile Apps with JavaScript