neovimの導入
neovim
はbrew
でインストールします。
https://github.com/neovim/neovim
foo$ brew install neovim/neovim/neovim Updating Homebrew... ==> Auto-updated Homebrew! Updated 2 taps (homebrew/core, homebrew/php). ==> New Formulae alexjs dmtx-utils gtef httpflow llvm@3.9 teleport ... ==> Renamed Formulae bash-completion2 -> bash-completion@2 gsl1 -> gsl@1 percona-server56 -> percona-server@5.6 ... ==> Tapping neovim/neovim Cloning into '/usr/local/Homebrew/Library/Taps/neovim/homebrew-neovim'... remote: Counting objects: 7, done. remote: Compressing objects: 100% (6/6), done. remote: Total 7 (delta 0), reused 3 (delta 0), pack-reused 0 Unpacking objects: 100% (7/7), done. Checking connectivity... done. Tapped 1 formula (32 files, 35.2KB) ==> Installing neovim from neovim/neovim ==> Installing dependencies for neovim/neovim/neovim: cmake, libtool, autoconf, automake, pkg-config, jemalloc, libuv, msgpack, unibilium, libtermkey, libvterm ==> Installing neovim/neovim/neovim dependency: cmake ==> Downloading https://homebrew.bintray.com/bottles/cmake-3.7.2.yosemite.bottle.tar.gz ######################################################################## 100.0% ==> Pouring cmake-3.7.2.yosemite.bottle.tar.gz ==> Caveats Emacs Lisp files have been installed to: /usr/local/share/emacs/site-lisp/cmake ==> Summary 🍺 /usr/local/Cellar/cmake/3.7.2: 2,143 files, 29.3MB ==> Installing neovim/neovim/neovim dependency: libtool ==> Downloading https://homebrew.bintray.com/bottles/libtool-2.4.6_1.yosemite.bottle.tar.gz ######################################################################## 100.0% ==> Pouring libtool-2.4.6_1.yosemite.bottle.tar.gz ==> Caveats In order to prevent conflicts with Apple's own libtool we have prepended a "g" so, you have instead: glibtool and glibtoolize. ==> Summary 🍺 /usr/local/Cellar/libtool/2.4.6_1: 70 files, 3.7MB ==> Installing neovim/neovim/neovim dependency: autoconf ==> Downloading https://homebrew.bintray.com/bottles/autoconf-2.69.yosemite.bottle.4.tar.gz ######################################################################## 100.0% ==> Pouring autoconf-2.69.yosemite.bottle.4.tar.gz ==> Caveats Emacs Lisp files have been installed to: /usr/local/share/emacs/site-lisp/autoconf ==> Summary 🍺 /usr/local/Cellar/autoconf/2.69: 70 files, 3.0MB ==> Installing neovim/neovim/neovim dependency: automake ==> Downloading https://homebrew.bintray.com/bottles/automake-1.15.yosemite.bottle.2.tar.gz ######################################################################## 100.0% ==> Pouring automake-1.15.yosemite.bottle.2.tar.gz 🍺 /usr/local/Cellar/automake/1.15: 130 files, 2.9MB ==> Installing neovim/neovim/neovim dependency: pkg-config ==> Downloading https://homebrew.bintray.com/bottles/pkg-config-0.29.2.yosemite.bottle.tar.gz ######################################################################## 100.0% ==> Pouring pkg-config-0.29.2.yosemite.bottle.tar.gz 🍺 /usr/local/Cellar/pkg-config/0.29.2: 11 files, 631KB ==> Installing neovim/neovim/neovim dependency: jemalloc ==> Downloading https://homebrew.bintray.com/bottles/jemalloc-4.5.0.yosemite.bottle.tar.gz ######################################################################## 100.0% ==> Pouring jemalloc-4.5.0.yosemite.bottle.tar.gz 🍺 /usr/local/Cellar/jemalloc/4.5.0: 16 files, 1.4MB ==> Installing neovim/neovim/neovim dependency: libuv ==> Downloading https://homebrew.bintray.com/bottles/libuv-1.11.0.yosemite.bottle.tar.gz ######################################################################## 100.0% ==> Pouring libuv-1.11.0.yosemite.bottle.tar.gz 🍺 /usr/local/Cellar/libuv/1.11.0: 56 files, 2.3MB ==> Installing neovim/neovim/neovim dependency: msgpack ==> Downloading https://homebrew.bintray.com/bottles/msgpack-2.1.1.yosemite.bottle.tar.gz ######################################################################## 100.0% ==> Pouring msgpack-2.1.1.yosemite.bottle.tar.gz 🍺 /usr/local/Cellar/msgpack/2.1.1: 662 files, 5MB ==> Installing neovim/neovim/neovim dependency: unibilium ==> Downloading https://homebrew.bintray.com/bottles/unibilium-1.2.0.yosemite.bottle.tar.gz ######################################################################## 100.0% ==> Pouring unibilium-1.2.0.yosemite.bottle.tar.gz 🍺 /usr/local/Cellar/unibilium/1.2.0: 62 files, 271.3KB ==> Installing neovim/neovim/neovim dependency: libtermkey ==> Downloading https://homebrew.bintray.com/bottles/libtermkey-0.19.yosemite.bottle.tar.gz ######################################################################## 100.0% ==> Pouring libtermkey-0.19.yosemite.bottle.tar.gz 🍺 /usr/local/Cellar/libtermkey/0.19: 32 files, 103.8KB ==> Installing neovim/neovim/neovim dependency: libvterm ==> Downloading https://homebrew.bintray.com/bottles/libvterm-681.yosemite.bottle.tar.gz ######################################################################## 100.0% ==> Pouring libvterm-681.yosemite.bottle.tar.gz 🍺 /usr/local/Cellar/libvterm/681: 11 files, 167.8KB ==> Installing neovim/neovim/neovim ==> Downloading https://github.com/neovim/neovim/archive/v0.1.7.tar.gz ==> Downloading from https://codeload.github.com/neovim/neovim/tar.gz/v0.1.7 ######################################################################## 100.0% ==> Downloading https://github.com/luvit/luv/archive/146f1ce4c08c3b67f604c9ee1e124b1cf5c15cf3.tar.gz ==> Downloading from https://codeload.github.com/luvit/luv/tar.gz/146f1ce4c08c3b67f604c9ee1e124b1cf5c15cf3 ######################################################################## 100.0% ==> Downloading https://raw.githubusercontent.com/neovim/deps/master/opt/LuaJIT-2.0.4.tar.gz ######################################################################## 100.0% ==> Downloading https://github.com/keplerproject/luarocks/archive/5d8a16526573b36d5b22aa74866120c998466697.tar.gz ==> Downloading from https://codeload.github.com/luarocks/luarocks/tar.gz/5d8a16526573b36d5b22aa74866120c998466697 ######################################################################## 100.0% ==> Building third-party dependencies. ==> cmake ../third-party -DUSE_BUNDLED_BUSTED=OFF -DUSE_BUNDLED_GPERF=OFF -DUSE_BUNDLED_LIBUV=OFF -DUSE_BUNDLED_MSGPACK=OFF -DUSE_BUNDLED_UNIBILIUM=OFF -DUSE_BUNDLED_LIBTERMKEY=O ==> make VERBOSE=1 ==> Building Neovim. ==> cmake .. -DCMAKE_C_FLAGS_RELEASE=-DNDEBUG -DCMAKE_CXX_FLAGS_RELEASE=-DNDEBUG -DCMAKE_INSTALL_PREFIX=/usr/local/Cellar/neovim/0.1.7 -DCMAKE_BUILD_TYPE=Release -DCMAKE_FIND_FRA ==> make VERBOSE=1 install ==> Caveats To run Neovim, use the "nvim" command (not "neovim"): nvim After installing or upgrading, run the "CheckHealth" command: :CheckHealth To use your existing Vim configuration: ln -s ~/.vim ~/.config/nvim ln -s ~/.vimrc ~/.config/nvim/init.vim See ':help nvim' for more information. Breaking changes (if any) are documented at: https://github.com/neovim/neovim/wiki/Following-HEAD For other questions: https://github.com/neovim/neovim/wiki/FAQ ==> Summary 🍺 /usr/local/Cellar/neovim/0.1.7: 1,333 files, 16.9MB, built in 2 minutes 34 seconds foo$ nvim foo$ brew install neovim/neovim/neovim
設定ファイルの場所
~/.config/nvim/init.vim
記載内容は下記を参考にしてdein
を導入します。
導入するプラグインは下記に記述します。
/Users/foo/.dein.toml
[[plugins]] repo = 'Shougo/dein.vim' [[plugins]] repo = 'Shougo/vimproc.vim' build = 'make' [[plugins]] repo = 'Shougo/neosnippet-snippets'
/Users/foo/.dein_lazy.toml
[[plugins]] repo = 'Shougo/neomru.vim' on_path = '.*' [[plugins]] repo = 'jiangmiao/auto-pairs' on_i = 1 [[plugins]] repo = 'Shougo/neoyank.vim' on_path = '.*' on_i = 1 [[plugins]] repo = 'Shougo/neosnippet' depends = ['neosnippet-snippets'] on_i = 1 on_ft = ['snippet'] [[plugins]] repo = 'Shougo/neocomplete' if = 'has("lua")' on_i = 1 [[plugins]] repo = 'Shougo/deoplete.nvim' if = 'has("nvim")' on_i = 1 [[plugins]] repo = 'Shougo/unite.vim' depends = 'neomru.vim' # [[plugins]] # repo = 'begriffs/haskell-vim-now' # on_ft = ['haskell'] # [[plugins]] # repo = 'neovimhaskell/haskell-vim' # on_ft = ['haskell'] [[plugins]] repo = 'eagletmt/neco-ghc' on_ft = ['haskell'] [[plugins]] repo = 'eagletmt/ghcmod-vim' on_ft = ['haskell'] [[plugins]] repo = 'scrooloose/nerdtree'
foo$ nvim ./servant03/MyWebApp1.hs [dein] Not installed plugins: ['ghcmod-vim'] [dein] Update started: (2017/04/02 14:45:54) [dein] Updated plugins: [dein] ghcmod-vim(1 change) [dein] Done: (2017/04/02 14:45:59) 続けるにはENTERを押すかコマンドを入力してください
foo$ ls ~/.cache/dein/repos/github.com/ Shougo/ altercation/ begriffs/ dag/ eagletmt/ jiangmiao/ morhetz/ nanotech/ neovimhaskell/ scrooloose/ vim-scripts/ foo$ ls ~/.cache/dein/repos/github.com/
react-bootstrap-tableでcolumnが動的の場合のテーブル生成
React
のテーブルコンポーネントはどれがデファクトなのでしょうか。よくわからなかったので、目についたreact-bootstrap-table
を使ってみました。
ライブラリの取り込み
<script src="https://unpkg.com/react@15/dist/react.js"></script> <script src="https://unpkg.com/react-dom@15/dist/react-dom.js"></script> <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
要素の作成
<div id="result"></div>
以下のようなデータをAPI
で取得できるとします。
{ colomuns : ["col_a", "col_b", "col_c"] .resultSet : [ {"id" : 1, "col_a" : "val_foo_a", "col_b" : "val_foo_b", "col_c" : "val_foo_c"} ,{"id" : 2, "col_a" : "val_bar_a", "col_b" : "val_bar_b", "col_c" : "val_bar_c"} ,{"id" : 3, "col_a" : "val_bazz_a", "col_b" : "val_bazz_b", "col_c" : "val_bazz_c"} ] }
ライブラリ自体に動的にカラムを生成する機能はありませんが、下記にある通り、少しコードを書けば実現できます。
ただし、ここでの、やり取りでは述べられていませんが、React
の仮想DOMの管理上1つのカラムのデータはユニークである必要があり、そのカラムに対してisKey
属性で指定する必要があります。
下記がfetch
でAPI
アクセスして、テーブル反映までのコードになります。id
列をユニークキーとしています。
function query() { fetch('http://127.0.0.1:8081/query', { method : 'POST', mode : 'cors', headers: new Headers({"Content-Type" : "application/x-www-form-urlencoded"}), body : 'foo=bar' }).then(function(response) { response.json().then( (json) => { ReactDOM.render( <BootstrapTable data={json.resultSet} striped hover> {json.columns.map( (name) => <TableHeaderColumn dataField = { name } isKey = { name === "id" } > { name } </TableHeaderColumn> )} </BootstrapTable>, document.getElementById('result') ); // render }); // then }).catch(function(err) { console.log(err); }); }
ReactでHTMLの共通化
SBAdmin2のダッシュボードページにあるカードのUI部分をReactにて共通化してみました。
ここの部分です。
下記が4枚あるカードのコードになります。これをReactを使って共通化します。背景色と表示内容だけが異なり、タグの構造は全く同じです。
<div class="row"> <div class="col-lg-3 col-md-6"> <div class="panel panel-primary"> <div class="panel-heading"> <div class="row"> <div class="col-xs-3"> <i class="fa fa-comments fa-5x"></i> </div> <div class="col-xs-9 text-right"> <div class="huge">26</div> <div>New Comments!</div> </div> </div> </div> <a href="#"> <div class="panel-footer"> <span class="pull-left">View Details</span> <span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span> <div class="clearfix"></div> </div> </a> </div> </div> <div class="col-lg-3 col-md-6"> <div class="panel panel-green"> <div class="panel-heading"> <div class="row"> <div class="col-xs-3"> <i class="fa fa-tasks fa-5x"></i> </div> <div class="col-xs-9 text-right"> <div class="huge">12</div> <div>New Tasks!</div> </div> </div> </div> <a href="#"> <div class="panel-footer"> <span class="pull-left">View Details</span> <span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span> <div class="clearfix"></div> </div> </a> </div> </div> <div class="col-lg-3 col-md-6"> <div class="panel panel-yellow"> <div class="panel-heading"> <div class="row"> <div class="col-xs-3"> <i class="fa fa-shopping-cart fa-5x"></i> </div> <div class="col-xs-9 text-right"> <div class="huge">124</div> <div>New Orders!</div> </div> </div> </div> <a href="#"> <div class="panel-footer"> <span class="pull-left">View Details</span> <span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span> <div class="clearfix"></div> </div> </a> </div> </div> <div class="col-lg-3 col-md-6"> <div class="panel panel-red"> <div class="panel-heading"> <div class="row"> <div class="col-xs-3"> <i class="fa fa-support fa-5x"></i> </div> <div class="col-xs-9 text-right"> <div class="huge">13</div> <div>Support Tickets!</div> </div> </div> </div> <a href="#"> <div class="panel-footer"> <span class="pull-left">View Details</span> <span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span> <div class="clearfix"></div> </div> </a> </div> </div> </div>
まず、ライブラリを取り込みます。
<!-- React.js --> <script src="https://unpkg.com/react@15/dist/react.js"></script> <script src="https://unpkg.com/react-dom@15/dist/react-dom.js"></script> <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
カードのHTML
部分はdiv
要素のみにします。
<div class="row"> <div id="card1"></div> <div id="card2"></div> <div id="card3"></div> <div id="card4"></div> </div>
カードのコードはJSX
で書き直します。class
属性はclassName
属性に書き換えます。そして、カードごとに異なる部分はパラメータとします。{
と}
で囲った部分に値を埋め込みます。
function getCard(prop) { return <div className="col-lg-3 col-md-6"> <div className={prop.mainStyle}> <div className="panel-heading"> <div className="row"> <div className="col-xs-3"> <i className="fa fa-comments fa-5x"></i> </div> <div className="col-xs-9 text-right"> <div className="huge">{prop.num}</div> <div>{prop.text}</div> </div> </div> </div> <a href="#"> <div className="panel-footer"> <span className="pull-left">View Details</span> <span className="pull-right"><i className="fa fa-arrow-circle-right"></i></span> <div className="clearfix"></div> </div> </a> </div> </div>; }
共通化したコードに実引数を与えて、先ほど定義したdiv要素と関連付けさせます。
ReactDOM.render( getCard({num : 26, text : "New Comments!", mainStyle : "panel panel-primary"}), document.getElementById('card1') ) ReactDOM.render( getCard({num : 12, text : "New Tasks!", mainStyle : "panel panel-green"}), document.getElementById('card2') ) ReactDOM.render( getCard({num : 124, text : "New Orders!", mainStyle : "panel panel-yellow"}), document.getElementById('card3') ) ReactDOM.render( getCard({num : 13, text : "Support Tickets!", mainStyle : "panel panel-red"}), document.getElementById('card4') )
Flux
としてイベントやデータバインディングの実装をしないで、単なるUIの共通化として利用するのもありかと思いました。
ServantのCSVファイルダウンロードのサンプル
$ curl -i http://127.0.0.1:8081/csv/UNdata_Export_pork HTTP/1.1 200 OK Transfer-Encoding: chunked Date: Mon, 20 Jun 2016 16:12:16 GMT Server: Warp/3.2.9 Content-Type: application/csv "Country or Area","Year","Unit","Value","Value Footnotes" "Albania","2013","Mil. USD","3.86207176515949","" "Albania","2013","Thousand metric tons","0.8","" "Albania","2012","Mil. USD","3.17974879791774","" "Albania","2012","Thousand metric tons","0.8",""
HaskellのCSV読み込み
利用ライブラリ
インポート
Prelude> import Text.CSV
1行読み込み
Prelude Text.CSV> parseCSVTest "aaa,bbb" [["aaa","bbb"]] Prelude Text.CSV> parseCSVTest "aaa,bbb,ccc" [["aaa","bbb","ccc"]]
トリムはしない
Prelude Text.CSV> parseCSVTest "aaa,bbb, ccc" [["aaa","bbb"," ccc"]]
複数行読み込み
Prelude Text.CSV> parseCSVTest "aaa,bbb, ccc\naaa," [["aaa","bbb"," ccc"],["aaa",""]] Prelude Text.CSV> parseCSVTest "aaa,bbb, ccc\naaa,,bbb" [["aaa","bbb"," ccc"],["aaa","","bbb"]]
出力
Prelude Text.CSV> printCSV [["1","2","3"],["4","5"],["6"]] "\"1\",\"2\",\"3\"\n\"4\",\"5\"\n\"6\""
読み込み件数取得
Prelude Text.CSV> parseCSVFromFile "./data/UNdata_Export_pork.csv" >>= \x -> either (\x -> return 0) (return . length) x 1376
10行目出力
Prelude Text.CSV> parseCSVFromFile "./data/UNdata_Export_pork.csv" >>= \x -> return $ either (\x -> []) (\x -> x !! 10) x ["Albania","2009","Thousand metric tons","0.63",""]
全件出力
Prelude Text.CSV> either (\x -> putStrLn "error") (mapM_ (putStrLn . show)) =<< parseCSVFromFile "./data/UNdata_Export_pork.csv" ["Country or Area","Year","Unit","Value","Value Footnotes"] ["Albania","2013","Mil. USD","3.86207176515949",""] ["Albania","2013","Thousand metric tons","0.8",""]
ServantのFileUploadサンプル
package
servant-multipart: multipart/form-data (e.g file upload) support for servant
$ cabal install servant-multipart Resolving dependencies... Notice: installing into a sandbox located at foo/.cabal-sandbox Downloading http-client-0.5.6.1... Configuring natural-transformation-0.4... Configuring http-client-0.5.6.1... Building natural-transformation-0.4... ...
sample
client
$ curl -i -X PUT http://127.0.0.1:8081/file -F "upfile1=@MyWebApp_upload.hs" -F "xx=yy" HTTP/1.1 100 Continue HTTP/1.1 200 OK Transfer-Encoding: chunked Date: Tue, 14 Mar 2017 12:03:05 GMT Server: Warp/3.2.9 Content-Type: application/json;charset=utf-8 {"msg":"\"upfile doesn't exist\"","len":-1} $ $ curl -i -X PUT http://127.0.0.1:8081/file -F "upfile=@MyWebApp_upload.hs" -F "xx=yy" HTTP/1.1 100 Continue HTTP/1.1 200 OK Transfer-Encoding: chunked Date: Tue, 14 Mar 2017 12:03:13 GMT Server: Warp/3.2.9 Content-Type: application/json;charset=utf-8 {"msg":"uploaded","len":1633} $ ls -al MyWebApp_upload.hs -rw-r--r-- 1 foo bar 1633 3 4 11:01 MyWebApp_upload.hs $
server log
*Main> main FileData {fdInputName = "upfile1", fdFileName = "MyWebApp_upload.hs", fdFileCType = "application/octet-stream", fdFilePath = "/var/folders/hw/p4bp49hd7v9_1j60sjvmhqnr0000gn/T/servant-multipart1974930991404280278.buf"} not exist FileData {fdInputName = "upfile", fdFileName = "MyWebApp_upload.hs", fdFileCType = "application/octet-stream", fdFilePath = "/var/folders/hw/p4bp49hd7v9_1j60sjvmhqnr0000gn/T/servant-multipart8933518161505795335.buf"}
HaskellでYamlの任意項目の取り扱い
Applicative
スタイルで.*?
で任意項目、.!=
でデフォルト値を設定します。`
parseJSON (Object m) = AppConfig <$> m .:? "port" .!= 8081 -- default