2018年のVimファイル検索・文字列検索はfzfとripgrep(rg)で決まり
sublime2 -> atom -> vscode -> sublime3 を経て5年ぶりぐらいにVimに帰ってきたわけですが、当時から色々変わっていて軽い浦島太郎状態です。ともかく大変なのはプロジェクト内のファイル検索と文字列検索。一度、sublimeのようなテキストサーチを経験してしまうとこれなしには開発できなくなってしまいました。
deinをパッケージのインストールに選び、deniteを試すも大きなプロジェクトではその遅さに困り、ctrlPとfzf両方試し、fzfを利用することに決めました。決め手はその速さ。Blazing fastというやつです。
deinを利用しているので、.vimrcにjunegunn/fzfとjunegunn/fzf.vimを追加。
if dein#load_state($HOME . '/.cache/dein')
call dein#begin($HOME . '/.cache/dein')
..
call dein#add('junegunn/fzf', { 'build': './install --all', 'merged': 0 })
call dein#add('junegunn/fzf.vim', { 'depends': 'fzf' })
..
あとはショートカットを追加。ctrl-Pでファイル検索。ctrl-gで文字列検索です。私はバッファ検索はタブを利用しているのであまり使わないと思っていますが、一応追加。\\でvimコマンド一覧を表示できます。
" FZF
fun! FzfOmniFiles()
let is_git = system('git status')
if v:shell_error
:Files
else
:GitFiles
endif
endfun
nnoremap <C-b> :Buffers<CR>
nnoremap <C-g> :Rg<Space>
nnoremap <leader><leader> :Commands<CR>
nnoremap <C-p> :call FzfOmniFiles()<CR>
私はタブを利用してて、かつ私のtmuxのprefixキーのctl-tが被って利用できなそうだったので、ctrl-oで新しいタブを開くに変更。
let g:fzf_action = {
\ 'ctrl-o': 'tab split'
\ }
文字列検索はripgrep(rg)を採用

ripgrepをインストールして、Rgコマンドにpreviewを追加。ctrl-gで:Rgが出て、検索する文字列を入れて、Enter。それから?を押すとpreviewモードスタート。ファイルが右側に表示されて便利の極みです。
command! -bang -nargs=* Rg
\ call fzf#vim#grep(
\ 'rg --column --line-number --hidden --ignore-case --no-heading --color=always '.shellescape(<q-args>), 1,
\ <bang>0 ? fzf#vim#with_preview({'options': '--delimiter : --nth 4..'}, 'up:60%')
\ : fzf#vim#with_preview({'options': '--delimiter : --nth 4..'}, 'right:50%:hidden', '?'),
\ <bang>0)
私の整理されてないvimrcはこちら
[Ubuntu] grepからSilver Searcher(ag)。2018年はRipgrep(rg)をインストールする
昔は、find . | xargs grep 2>/dev/nullを使ってました。agに変更後、その速さに驚き。2018年はそれよりも早いRipgrepを採用しています。
Ubuntuでのインストールは、下記の通り。
# ripgrep curl -LO https://github.com/BurntSushi/ripgrep/releases/download/0.8.1/ripgrep_0.8.1_amd64.deb sudo dpkg -i ripgrep_0.8.1_amd64.deb && rm ripgrep_0.8.1_amd64.deb
使い方はシンプルでrg 検索ワード。
shohey1226@pro79.local:/Users/shohey1226/dotfiles> rg vim init.vim 1:set runtimepath^=~/.vim runtimepath+=~/.vim/after 3:source ~/.vimrc starttmux.sh 10: # create a new tmux session, starting vim from a saved session in the new window 13: # Select pane 1, set dir to api, run vim 23: tmux send-keys -t $session:1 "cd ~/git/Gauss; vim -S $HOME/.vim/sessions/gauss.vim" C-m 44:# return to main vim window README.markdown 19: $ git submodule init .vim/vundle.git/ 20: $ git submodule update .vim/vundle.git/
[Rails] Action Cableの実装方法
JQueryは古いテクノロジーとはいえ、さくっと動くものを作るときは異常に簡単です。 古いテクノロジーは悪ではなく適材適所で使っていくのが大事だと思っています。
まずは、最初からあるapp/assets/javascripts/cable.jsを該当layoutで読み込みます。
# app/assets/javascripts/application.js ... //= require cable.js
全部のViewでApp.cableを呼ぶ必要はないのでcontent_forでActionCableとの通信をとるViewだけJSを走らせるようにします。
#app/views/layouts/application.html.erb <head> ... <%= yield :page_scripts %> </head>
JSでは、App.cableにイベントを登録していきます。 引数のchannelにはクラス名、引数を渡すとparamsに入ってサーバ側で処理できます。this.performを使ってクラス内のメソッドを呼ぶことができます。development環境では別プロセスで動作確認ができないのでsetTimeoutを用いてテストしています。
<% content_for :page_scripts do %>
<script>
$(function(){
// Subscrubung host status
$('span.host-status')
.filter(function(i){
return $(this).text() !== "terminated";
})
.each(function(i){
var hostId = $(this).data('hostId');
var self = this;
App.cable.subscriptions.create({channel: "HostStatusChannel", host_id: hostId}, {
connected: function(){
console.log('connected');
//var self = this;
//setTimeout(function(){
// console.log('say now');
// self.perform("say");
//}, 1000);
},
received: function (data) {
var currentStatus = $(self).text();
if(data.status !== currentStatus){
$(self).fadeOut(500, function(){
$(self).text(data.status);
$(self).fadeIn();
});
}
},
});
});
});
</script>
<% end %>
HTML部分は下記のような感じ。
<span class="host-status" data-host-id="<%= host.id %>"><%= host.status %></span>
で最後になりますが、ActionCableを継承したクラスです。subscribedがconnectionとともに走ります。 stream_for MODELでモデルに関係したチャネルが接続されます。 そして、broadcast_to(MODEL, object)でそのモデルへの接続を確率したチャネルにプッシュすることができます。
# app/channels/host_status_channel.rb
class HostStatusChannel < ApplicationCable::Channel
def subscribed
host = Host.find(params[:host_id])
stream_for host
end
def say # for testing
HostStatusChannel.broadcast_to(Host.find(1), "hi")
end
end
これでダイナミックにDOMを操作できるようになりました。
[Rails] Device利用時のconnection.rb(Action Cable)
Railsガイドで説明されているconnection.rbはcookieを利用しているもので、deviseを利用する場合は、request.envに設定されているwardenのものを取ってくる必要がある。 もしくはsessionの中を漁る感じ、request.envの方が綺麗に書けるのでこちらを採用した。 (Essentially, the both are cookie tho..)
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
end
private
def find_verified_user
if verified_user = request.env['warden'].user
verified_user
else
reject_unauthorized_connection
end
end
end
end
参考: https://stackoverflow.com/questions/38470463/rails-devise-action-cable