Hatena::ブログ(Diary)

そもさん&せっぱさん

2017-05-28

(2017-05) React.js の前に Webpack と Babel ちょっと触ったメモ

ちょっと触った程度のメモです。

標準的なやり方からは外れている(ちょっと試す程度ならいいけど本番には使えない)と思います。

準備

mkdir work && cd work
npm init -y

Babel

Babel で JSX から素の JS に変換できるとのことなので、試す。

なんで Babel で変換できるかは調べてない。とにかくできる。

npm install --save-dev babel-cli

テスト用のファイル。

// test.js
class Foo extends React.Component {
  render() {
    return (
      <p>foo content</p>
    );
  }
}
$ node_modules/.bin/babel test.js
SyntaxError: test.js: Unexpected token (4:6)

babel コマンドは使えるが JSX の部分でエラーになる。

プリセットというのが必要っぽい。

# npm install --save-dev と同じ
npm i -D babel-preset-react

.babelrc で react preset を使うように指定

{
  "presets": [
    "react"
  ]
}

変換できるようになった。

何も指定しないと標準出力に出る。

$ node_modules/.bin/babel test.js
class Foo extends React.Component {
  render() {
    return React.createElement(
      "p",
      null,
      "foo content"
    );
  }
}

-d (--out-dir) で指定したディレクトリに出力。

$ node_modules/.bin/babel test.js -d dist/
test.js -> dist/test.js

$ ls dist
test.js

変換元ファイルの拡張子が .jsx の場合、.js に置き換えられる。

$ node_modules/.bin/babel test.jsx -d dist/
test.jsx -> dist/test.js

変換元にファイルではなくディレクトリを指定すると、そのディレクトリにあるファイルを全部変換してくれる。

$ node_modules/.bin/babel src -d dist
src/test1.jsx -> dist/test1.js
src/test2.jsx -> dist/test2.js

Webpack

だいたい分かったので次は Webpack。

JSX の部分がなくなって素の JS ができてしまえば、後は Webpack のフローに乗せてしまえるという寸法。

src/
↓ Babel で JSX を変換
src_babeled/
↓ Webpack でまとめる
dist/bundle.js

のようにしてみる。

npm i -D webpack

上で作った余計なファイルを消して、src/entry.jsx を作る。

$ ls src
entry.jsx

$ cat src/entry.jsx
class Foo extends React.Component {
  render() {
    return (
      <p>foo content</p>
    );
  }
}
 
window.onload = function(){
  ReactDOM.render(<Foo />, document.querySelector("#content"));
};

webpack.config.js を書く。

module.exports = {
  entry: "./src_babeled/entry.js",
  output: {
    path: __dirname + "/dist",
    filename: "bundle.js"
  }
};
$ node_modules/.bin/babel src -d src_babeled
src/entry.jsx -> src_babeled/entry.js

$ node_modules/.bin/webpack --config webpack.config.js
Hash: 436e069420e6239a9f13
Version: webpack 2.6.1
Time: 37ms
    Asset     Size  Chunks             Chunk Names
bundle.js  2.89 kB       0  [emitted]  main
   [0] ./src_babeled/entry.js 257 bytes {0} [built]

毎回これやるのだるいのでビルド用のスクリプトを書く。

#!/bin/bash

node_modules/.bin/babel src -d src_babeled
node_modules/.bin/webpack --config webpack.config.js

dist/bundle.js が生成された。

html からはこれを使う。

<html>
  <head>
    <script src="dist/bundle.js"></script>
  </head>
  <body>
    <div id="content"></div>
  </body>
</html>

ブラウザで開くとエラーが出る。

Uncaught ReferenceError: React is not defined

React 自体をまだインストールしていなかった。

あと、react-dom も必要なので一緒にインストールする。

npm install --save react react-dom

require する。

// src/entry.jsx の先頭に追加
var React = require("react");
var ReactDOM = require("react-dom");

ビルドして index.html をブラウザで見ると、画面に "foo content" と表示された。

バージョン

$ npm list --depth=0
work@1.0.0 /path/to/work
├── babel-cli@6.24.1
├── babel-preset-react@6.24.1
├── react@15.5.4
├── react-dom@15.5.4
└── webpack@2.6.1

$ node -v
v7.3.0

2017-04-24

コマンドライン引数を簡易にパースする(その2)

その1 を書いた後、もうちょっと良さそうな方法を思いついたのでその2。

こっちの方がオプショナル引数の書き方が自然(シェルでの一般的な書き方からの逸脱が少ない)で、他の人に使ってもらうとしても拒否反応が少ないだろうし説明も楽かなと。

自然ということでいえば、その1では必ず "key=value" のフォーマットで書く仕様にしていましたが、やはりフラグとしての指定もできた方がいいかと思ってそこも変更しました。

目的

  • 使い捨てのスクリプト、プロトタイピング、自分だけ〜何人かだけで使う程度の軽いツールなどを作るときにサッと使いたい
  • なるべく言語非依存にしたい

高機能でなくていいので yak shaving なしでサッと使いたい。

使い方

例として arg1, arg2 が必須で、あとはオプショナルなパラメータとして opt1, opt2, opt3 が指定できるが opt2 は渡さないという場合、次のように指定します。

必須引数 arg1, arg2 の順番は固定。オプショナル引数はその後に置く。

ruby my_cmd.rb arg1 arg2 opt1=11 opt3=33

オプショナル引数はまるごと省略可:

ruby my_cmd.rb arg1 arg2

key=value の形になっていない("=" を含まない)オプショナル引数はフラグとして扱われる。

ruby my_cmd.rb arg1 arg2 enable-foo

実装例

Ruby の場合(説明用コードなので一部 Ruby っぽくない書き方になっていますが意図的なものです)。

def parse_optionals(args)
  optionals = {}

  args.each{ |arg|
    if arg.include? "="
      idx = arg.index("=")
      # assert idx >= 1
      k = arg[0 ... idx]
      v = arg[(idx + 1) .. -1]
      optionals[k] = v
    else
      optionals[arg] = true
    end
  }

  return optionals
end

def parse_args(args, names)
  opts = {}

  if ARGV.size == names.size
    # オプショナル引数なし
  elsif ARGV.size > names.size
    # オプショナル引数あり
    opts = parse_optionals(ARGV[names.size .. -1])
  else
    $stderr.puts "invalid arguments size"
    # print_usage
    exit 1
  end

  names.each_with_index{ |name, i|
    opts[name] = args[i]
  }

  return opts
end

# コマンドライン引数をパース
opts = parse_args( ARGV, ["arg1", "arg2"] )

# 必要に応じてバリデーションとか

# パースされた引数を使ったプログラム本体
do_someting( opts )

パース結果を pretty print しただけの動作例:

$ ruby my_cmd.rb a1 a2 opt1=o1 opt2=o2 opt3=o3
{"opt1"=>"o1", "opt2"=>"o2", "opt3"=>"o3", "arg1"=>"a1", "arg2"=>"a2"}

$ ruby my_cmd.rb a1 a2 opt1=o1 opt3=o3
{"opt1"=>"o1", "opt3"=>"o3", "arg1"=>"a1", "arg2"=>"a2"}

$ ruby my_cmd.rb a1 a2
{"arg1"=>"a1", "arg2"=>"a2"}

$ ruby my_cmd.rb a1 a2 enable-foo
{"enable-foo"=>true, "arg1"=>"a1", "arg2"=>"a2"}

パース結果は Java でいえば Map<String, String> で、そこから先のバリデーションとかは使う側が適宜行います。

備考

  • ライブラリではなくスニペットという扱い。コピペして使う。
  • とにかくサッと書きたいときに毎回適当に書いたりするんだけど、毎回モヤモヤするのでいったん固めて使いまわしたかった。ひとまず自己満足できたので良し。
  • この形に落ち着いた後で「これ Ruby のメソッドのシグネチャだなあ」と思った。解が似ているということは、解こうとしていた問題が似ていたということではないかと。

2017-04-19

コマンドライン引数を簡易にパースする

2017-04-24 追記:

改良版を作りました → その2

目的

  • 使い捨てのスクリプト、プロトタイピング、自分だけ〜何人かだけで使う程度の軽いツールなどを作るときにサッと使いたい
  • なるべく言語非依存にしたい

高機能でなくていいので yak shaving なしでサッと使いたい。

使い方

例として arg1, arg2 が必須で、あとはオプショナルなパラメータとして opt1, opt2, opt3 が指定できるが opt2 は渡さないという場合、次のように指定します。

必須引数 arg1, arg2 の順番は固定。オプショナル引数は一番最後に置く。

ruby my_cmd.rb arg1 arg2 ',opt1=11,opt3=33'

オプショナル引数の1文字目で区切り文字を指定しているのがミソで、パラメータ内に出現しない文字をユーザが任意に指定できます。

オプショナル引数はまるごと省略可:

ruby my_cmd.rb arg1 arg2

実装例

Ruby の場合(説明用コードなので一部 Ruby っぽくない書き方になっていますが意図的なものです)。

def parse_optionals(optional_args)
  delim = optional_args[0]     # 1番目の文字=区切り文字
  body  = optional_args[1..-1] # 2番目の文字から最後まで
  kvs = body.split(delim)
  optionals = {}

  kvs.each{ |kv|
    # 1つ目の "=" で key と value を分ける
    idx = kv.index("=")
    # assert idx >= 1
    k = kv[0 ... idx]
    v = kv[(idx + 1) .. -1]
    optionals[k] = v
  }

  return optionals
end

def parse_args(args, names)
  opts = {}

  if ARGV.size == names.size
    # オプショナル引数なし
  elsif ARGV.size == names.size + 1
    # オプショナル引数あり
    opts = parse_optionals(ARGV[names.size])
  else
    $stderr.puts "invalid arguments size"
    # print_usage
    exit 1
  end

  names.each_with_index{ |name, i|
    opts[name] = args[i]
  }

  return opts
end

# コマンドライン引数をパース
opts = parse_args( ARGV, ["arg1", "arg2"] )

# 必要に応じてバリデーションとか

# パースされた引数を使ったプログラム本体
do_someting( opts )

パース結果を pretty print しただけの動作例:

$ ruby my_cmd.rb a1 a2 ',opt1=o1,opt2=o2,opt3=o3'
{"opt1"=>"o1", "opt2"=>"o2", "opt3"=>"o3", "arg1"=>"a1", "arg2"=>"a2"}

$ ruby my_cmd.rb a1 a2 ',opt1=o1,opt3=o3'
{"opt1"=>"o1", "opt3"=>"o3", "arg1"=>"a1", "arg2"=>"a2"}

$ ruby my_cmd.rb a1 a2
{"arg1"=>"a1", "arg2"=>"a2"}

パース結果は Java でいえば Map<String, String> で、そこから先のバリデーションとかは使う側が適宜行います。

備考

  • ライブラリではなくスニペットという扱い。コピペして使う。
  • とにかくサッと書きたいときに毎回適当に書いたりするんだけど、毎回モヤモヤするのでいったん固めて使いまわしたかった。ひとまず自己満足できたので良し。
  • この形に落ち着いた後で「これ Ruby のメソッドのシグネチャだなあ」と思った。解が似ているということは、解こうとしていた問題が似ていたということではないかと。
  • 区切り文字を "&" にすると URL のクエリ文字列っぽくなる。枯れたフォーマットがあればそれに乗っかりたいので、実際クエリ文字列フォーマットで渡すのも検討したけど、区切り文字固定だと結局エスケープで悩むことになる。他に LTSV や JSON も検討したけど、同様に区切り文字とエスケープの問題とか JSON は煩雑とか言語によっては標準でライブラリがないとかで採用しなかった。
  • たとえば区切り文字をスペースにすると ' opt1=o1 opt2=o2' のように書ける。値にスペースが含まれないならこの方が見やすいかも。

2016-12-01

WEBrick::HTTPServer + 標準ライブラリのLogger + ローテーション

「WEBrick」「Logger」「標準ライブラリ」「ローテーション/ローテート」とかのワードでググってもそれっぽいのがサッと出てこなかったのでメモ。

第 2 引数に 'daily' などの文字列を指定すると、 期間を基準にしてログをローテーションしてくれます。

(略)

サイズを基準にしたローテーションとは違って、 古いログファイルが自動で消えることはありません。 そのため、ディスクの空き容量に注意する必要があります。

Rubyist Magazine - 標準添付ライブラリ紹介 【第 2 回】 Logger

http://magazine.rubyist.net/?0008-BundledLibraries

とのことなので、ひとまずサイズごとローテーションで。

# coding: utf-8

require 'webrick'
require 'logger'

$log_server = Logger.new("./server.log", 5, 1 * 1024 * 1024)
$log_server.level = Logger::INFO

$log_access = Logger.new("./access.log", 5, 1 * 1024 * 1024)

server = WEBrick::HTTPServer.new(
  :DocumentRoot => "./",
  :Port => 5678,
  :Logger => $log_server,
  :AccessLog => [
    [$log_access, WEBrick::AccessLog::COMMON_LOG_FORMAT],
    [$log_access, WEBrick::AccessLog::REFERER_LOG_FORMAT]
  ]
)

server.start

2016-11-06

Ubuntu 16.04 Dolphinのファイルのプロパティの「File Type Options」が動作しない

動かない理由は不明だが関連付けの変更はできた。


古いマシンに Ubuntu 12.10 が入ったままになっていて、そっちでは正しく動いていたのでそれを動かしたりして調べた。

その古いマシンでは設定ウィンドウのタイトルが「... - KEditFileType」となっていて、ps コマンドで探してみると

/usr/bin/keditfiletype --parent 50331822 text/plain

のようなプロセスが見つかる。

keditfiletype 自体はおそらく Dolphin をインストールした時に一緒にインストールされたのか、 /usr/bin の下に入っている。

で、 /usr/bin/keditfiletype text/plain のように自分で実行してやると、設定ウィンドウが開いて設定の変更・保存ができた。

設定は ~/.local/share/applications/mimeapps.list に保存される。


kcmshell4 filetypes でも設定できた。あらかじめ mimetype が分かっていなくてもキーワードで検索できるのでこっちの方が便利かも。

参考

file type options under properties on dolphin does not work. Ubuntu 16.04 - Ask Ubuntu

http://askubuntu.com/questions/800408/file-type-options-under-properties-on-dolphin-does-not-work-ubuntu-16-04/802177

Where does dolphin store file association information? • KDE Community Forums

https://forum.kde.org/viewtopic.php?f=224&t=129534

default programs - How to change file association for files opened in Dolphin from command line in GNOME? - Ask Ubuntu

http://askubuntu.com/questions/165618/how-to-change-file-association-for-files-opened-in-dolphin-from-command-line-in

Connection: close