vim-vsnip で複数のディレクトリからスニペットをインポートする
vim でスニペットを使うために vim-vsnip を使いはじめました。
vim-vsnip はファイル形式ごとに JSON でスニペットを定義します。
ex: typescript.json
{ "ReactFC": { "prefix": "fc", "body": [ "import React from 'react';\n", "const $1: React.FC = () => {", " return (", " );", "};\n", "export default $1;" ], "description": "React関数コンポーネントの雛形" } }
このようなファイルを g:vsnip_snippet_dir
に設定したディレクトリに置くと、スニペットとして展開できるようになります。
let g:vsnip_snippet_dir = expand($HOME . '/dotfiles/vsnip')
自分はこのファイルを dotfiles として公開しています。
しかし、そうすると公開できるような内容しかスニペットに登録できず、公開できないコード、例えば仕事でよく使うコードなどを登録できません。
それは不便なので、スニペットの JSON ファイルを参照するディレクトリを複数登録したくなります。
そんなときはg:vsnip_snippet_dirs
に配列で複数のディレクトリを渡すことで解決できます。
let g:vsnip_snippet_dirs = [expand($HOME . '/dotfiles/vsnip'), expand($HOME . '/dotfiles/vsnip-local')]
こうしたうえで、 vsnip-local/
を .gitignore
に登録しておき、 vsnip-local/
に仕事等で使う公開したくないスニペットを保存します。
(自分は gitignore する前に vsnip-local/.gitkeep
を Git 管理下に置いておいて、その後 gitignore して git clone しても vsnip-local/
が存在するようにしています)
iOS 13 ( Safari 13 ) 以降は -webkit-overflow-scrolling: touch の指定は必要ない
iOS Safari で慣性スクロールを有効にするために指定する -webkit-overflow-scrolling: touch
だけど、 Safari 13 ( iOS 13 ) から慣性スクロールがデフォルトになったため、わざわざ -webkit-overflow-scrolling: touch
を指定する必要がなくなった。
Safari 13 Release Notes #Layout and Rendering
Added support for one-finger accelerated scrolling to all frames and overflow:scroll elements eliminating the need to set-webkit-overflow-scrolling: touch.
-webkit-overflow-scrolling
は iOS Safari のみがサポートしているプロパティなので、iOS 13 未満のサポートをしないのであればスタイルシートから消してしまって問題ない。
Docker ( AmazonLinux2 ) 上で Perl から Headless Chrome を操作する
Perl で Headless Chrome を操作する日本語記事がほぼないし、しかもそれを Docker 内で動かすという例がなかったので書いておくことにする。
全部のファイルと、動かし方は gist にまとめておいた。
https://gist.github.com/takaya1992/6fc6878fb936559344fac068ab6e90f2
抜粋して一部を書いておく。
まずは、Dockerfile
FROM amazonlinux:2 WORKDIR /app RUN yum update -y \ && yum install -y perl perl-core perl-App-cpanminus gcc expat-devel \ && rm -rf /var/cache/yum/* \ && yum clean all \ && cpanm Carton COPY google-chrome.repo /etc/yum.repos.d/google-chrome.repo RUN yum install -y google-chrome-stable unzip wget lsof ipa-gothic-fonts ipa-mincho-fonts RUN CHROME_MAJOR_VERSION=$(google-chrome --version | sed -E "s/.* ([0-9]+)(\.[0-9]+){3}.*/\1/") \ && CHROME_DRIVER_VERSION=$(wget --no-verbose -O - "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_${CHROME_MAJOR_VERSION}") \ && echo "Using chromedriver version: "$CHROME_DRIVER_VERSION \ && wget --no-verbose -O /tmp/chromedriver_linux64.zip https://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip \ && unzip /tmp/chromedriver_linux64.zip chromedriver -d /usr/local/bin/
先に断っておくと、サンプルとしてわかりやすく書いているので、Dockerfile を書く上でのベストプラクティスは守っていない。 前半は、Perl とそれに必要なパッケージのインストールなのでとくに説明はしない。
重要なのは後半の Chrome と ChromeDriver のインストール部分で、Chrome のインストールから説明していく。
Chrome のインストール
まずは、Chrome のリポジトリを追加するために設定ファイルをコピーしてくる。google-chrome.repo
の中身は以下のようになってる。
[google-chrome] name=google-chrome baseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearch enabled=1 gpgcheck=1 gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub
これを /etc/yum.repo.d/
以下に置くことで、yum のパッケージ検索対象になる。
Chrome は google-chrome-stable
というパッケージ名で登録されている。
残りの Chrome と一緒にインストールしてるパッケージは、次の ChromeDriver のインストールに必要なもの ( unzip
, wget
)と、Chrome を起動するのに必要なもの ( lsof
) 、Chrome で日本語を表示する際に必要なフォント ( ipa-gothic-fonts
, ipa-mincho-fonts
) 。
ChromeDriver のインストール
Chrome を外から操作するために ChromeDriver を使う。
ChromeDriver はブラウザを操作するための WebDriver という仕様に基づいて実装されており、ChromeDriver を起動すると HTTP サーバーが立ち上がり JSON API でブラウザを操作できる。
他のブラウザ、例えば Firefox では geckodriver というドライバーが用意されている。
この WebDriver を使って各ブラウザを操作できるのが Selenium である。
話がそれたけど、ChromeDriver をインストールする。 ChromeDriver は Chrome のバージョンに合ったバージョンをインストールする必要がある。 そのため、 Chrome のバージョンを確認しそのバージョンに対応する ChromeDriver のバージョンを取得し、ダウンロードしている。
Perl から Headless な Chrome を操作する
直接 Docker を実行するのも面倒なので、docker-compose.yml
を用意して Docker Compose で操作できるようにしてある。
$ docker-compose build
でビルドして、
$ docker-compose run --rm app /bin/bash
で Docker コンテナ内に入る。
cpanfile
を用意しているので Docker コンテナ内で以下のコマンドを実行して必要なパッケージ ( Selenium::Remote::Driver
) をインストールしておく。
$ carton install
以下のスクリプトを carton exec -- perl selenium_chrome_test.pl
で実行すると、 Google
と表示されれば成功。
use strict; use warnings; use utf8; use feature qw/say/; use Selenium::Chrome; # Selenium を介さず直接 chromedriver 経由で Chrome を操作する my $driver = Selenium::Chrome->new( extra_capabilities => { 'goog:chromeOptions' => { args => [ 'headless', 'disable-gpu', 'window-size=1920,1080', 'no-sandbox' ], } } ); $driver->get('https://www.google.com'); say $driver->get_title(); # => Google $driver->shutdown_binary();
Headless な Chrome として実行するポイントは、Selenium::Chrome->new
時のオプションで headless
を指定すること。
順番に説明していく。
まず、インストールした Selenium::Remote::Driver
にはいくつかのパッケージが含まれていて、 Selenium::Chrome
もその一つ。
Selenium::Chrome
は Selenium を介さずに前述した ChromeDriver に直接アクセスし、API をコールして Chrome の操作を行う。
Selenium::Chrome
に渡した goog:chromeOptions
は、ChromeDriver へセッションを作成する際に渡され、 goog:chromeOptions
内の args
配列は Chrome 起動時の引数として設定される。
headless
を指定するとヘッドレスな Chrome として起動される。
disable-gpu
は headless
指定時に追加で指定することが推奨されるオプションである。
window-size
はその名の通りウィンドウのサイズを指定している。これは必須ではない。
最後に no-sandbox
は Chrome のサンドボックスを無効化するオプション。詳しく調べられていないけど、これをつけないと実行できなかった。セキュリティはゆるくなるので信用できないサイトを開かないように注意する。
【脱jQuery】jQuery の width, height の取得を Pure JavaScript に置き換える
jQuery は window や document 、element に対して幅 ( width
, innerWidth
, outerWidth
) と高さ ( height
, innerHeight
, outerHeight
) の取得ができる。
element に対して width や height を取得するための互換コードを紹介してる記事が多いが、 window
や document
に対しての取得について触れてる記事がなさそうだったので、調べてみた。
jQuery 3.5 をベースに調査している。
$(window)
に対しての width, height の取得
jQuery のソースコードではこの部分 https://github.com/jquery/jquery/blob/7a0a850f3d41c0412609c1d32b1e602d4afe2f4e/src/dimensions.js#L23-L29
$(window).width
document.documentElement.clientWidth
window
に対しての width
の取得なのに、いきなり document
が出てくるのでびっくりすると思うが、間違いではない。
window
には width
プロパティはなく、 innerWidth
か outerWidth
しかない。
また、window.innerWidth
は スクロールバーを含む ウィンドウのビューポートの幅を返す。
https://developer.mozilla.org/ja/docs/Web/API/Window/innerWidth
たいていの場合、取得したいのは描画が可能なエリア、つまりスクロールバーを除いた幅なので、その利用者側の意図と JavaScript の使用の差を jQuery が吸収してくれている結果。
逆に、スクロールバーを含めたウィンドウのビューポートの幅を取得したい場合は window.innerWidth
を使うことになる。
$(window).innerWidth
document.documentElement.clientWidth
$(window).innerWidth
で取得できる値は、 $(window).width
と同じである。
$(window).outerWidth
window.innerWidth
$(window).innerWidth
はスクロールバーを含めた幅が返ってくる。
window.outerWidth
はブラウザの外側の幅(サイドバーやその他ブラウザのUIを含めたもの)を返すので注意する。
$(window).height
document.documentElement.clientHeight
詳細は $(window).width
と同じで、width
を height
に読み替えれば大丈夫。
$(window).innerHeight
document.documentElement.clientHeight
$(window).innerHeight
で取得できる値は、 $(window).height
と同じである。
$(window).outerHeight
window.innerHeight
詳細は $(window).outerWidth
と同じで、width
を height
に読み替えれば大丈夫。
$(document)
に対しての width, height の取得
jQuery のソースコードではこの部分 https://github.com/jquery/jquery/blob/7a0a850f3d41c0412609c1d32b1e602d4afe2f4e/src/dimensions.js#L32-L42
$(document).width
Math.max( document.body.scrollWidth, document.documentElement.scrollWidth, document.body.offsetWidth, document.documentElement.offsetWidth, document.documentElement.clientWidth )
$(document).innerWidth
$(document).width
と同じ値を返す。
$(document).outerWidth
$(document).width
と同じ値を返す。
$(document).height
Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.documentElement.clientHeight )
$(document).innerHeight
$(document).height
と同じ値を返す。
$(document).outerHeight
$(document).height
と同じ値を返す。
友達の頼みでノートパソコンを見繕った
高校の時の友達から「パソコン買い替えたいんだけど、おすすめとか教えてくれない?」と連絡がきて「え〜俺も詳しくないし〜」とか思いつつ、なんだかんだ乗り気にヒアリングをしてよさげな端末を見繕ってしまった。
要望
要望を受けての想定スペック
- HDDまたはSSD: 256GB以上
- メモリ: 8GB(値段を抑えたければ4GB)
- Office: あり。Office Home & Business であること
- USB: USB type-A (USB type-C のみは避ける)
- サイズ: 13〜15インチ (優先度低め)
選んだポイント
- スマホのバックアップは子供の写真が多いだろうからできるだけストレージ容量の大きいもの。最低でも 256GB 以上がよさげ。
- 速さにこだわるんだったら SSD 。ただし、容量に対して HDD よりは割高。コストを抑えつつストレージ容量を重視したい場合は HDD 。
- メモリは 8GB 以上あれば Office の操作も快適。16GB はオーバースペック感。
- 価格を抑えるためにメモリ 4GB という選択肢もあるけど、若干動作は遅くなる。
- Office あり。Office Personal 2019 だと Powerpoint が含まれないので注意。
- USB type-A のポートが最低1つ、できれば2つ以上あればOK。 type-Cは変換アダプタが必要な場面が多いので避ける。
選んだ商品
- Inspiron 14 (7472) / DELL ... 96,984円
- MateBook 13 WRT19AH58BNC9NUA / ファーウェイ ... 109,792円
- LAVIE Note Standard(NS300/MAシリーズ PC-NS300MAW-2) / NEC ... 113,184円
- m-Book B401H / マウスコンピューター ... 118,584円
- Inspiron 13 7000 プレミアム / DELL ... 118,584円
けっこうお高いのね。と言われ、スペックを落とせば少し価格も落ちるよといって、メモリを4GBに落としたもの。
それでもやっぱりそれくらいするのね。と言われ、MS Office の値段も含まれてるから本体価格にしたら普通に安いほうだよ。と言ったら、え。Officeって買うものなの?と聞かれ、なるほどーという気持ちになった。
そして、その高校の友達、高校生の頃にお付き合いをしたことがあり、さらに今のLINEのプロフィール画像が子供の写真になっていて、聞くといつのまにか結婚・出産をしておりとてもショックを受けた、ということを最後に記しておく。
GASでサイボウズ ガルーンの予定をSlackに通知する
今勤めている会社では、スケジューラーとしてサイボウズのガルーンを利用しています。
サイボウズにはKUNAIという公式のスマホアプリがあり、それが予定の更新や予定のn分前のリマインドを通知してくれます。
しかし、仕事中はスマホの通知には気づきづらく、それなりの頻度でガルーンをチェックする必要があります。
ガルーンが公式にブラウザ通知やSlack連携をサポートしてくれれば嬉しいんですがそんな機能もいまだなく、 またガルーンが提供するAPIはいままでSOAP APIしかなく、SOAPは扱いづらいためずっと自作も避けていました。
そんななか、いつのまにかガルーンのAPIにREST APIが追加されていたので、予定のn分前になったらSlackに通知するGAS(Google Apps Script)を書いてみました。
Garoon Slack Notificator
使い方
使い方はGitHub Pagesで用意してみました。
サイボウズ ガルーンのREST APIを使ってみて
APIのユーザー認証方法がイケてないなと思いました。
ドキュメントを参照すると「パスワード認証」と「セッション認証」が用意されており、「パスワード認証」はID
とパスワード
を、:
で連結した文字列をBASE64エンコードしたものをX-Cybozu-Authorization
ヘッダーに乗せて、リクエストを送ります。
この「パスワード認証」のトークンの作り方はBASIC認証とまったく同じで、ただHTTPヘッダーが違うだけです。
生のIDとパスワードを扱うのはつらいので、リジェネレートしやすい別のAPIトークンを発行できたりとか、OAuthできるようになるととても嬉しいなと思います。
CSSのカラーコードを一括で短縮する
#fa05ab
のようにCSS等で指定するカラーコード。これは6桁または3桁の16進数で表現をしている。
6桁の場合はそれぞれ2桁ずつ、3桁の場合はそれぞれ1桁ずつを、RGBの順番にそれぞれの色の強さとして指定している。
6桁の指定で、2桁ずつ同じ文字を指定している場合は、3桁のカラーコードに短縮ができる。
例えば、#000000
は#000
、#ff00aa
は#f0a
と。
このように短縮できるカラーコードを一括で変換したい事情があり、備忘録として残しておく。
変換
Macを想定。Linuxでもgsed
をsed
と読み替えればOK。
GNU版のsedを使いたいので、brewでインストールしておく。
brew install gnu-sed
filelist.txt
にファイルのパス一覧が入ってることを想定してるけど、ここはよしなに。
cat filelist.txt | xargs gsed -i -e 's/#\([0-9a-fA-F]\)\1\+\([0-9a-fA-F]\)\2\+\([0-9a-fA-F]\)\3\+/#\1\2\3/g'