AlaxalA AX2230Sのパスワードリセット

ax2230sが届いて「さて初期化するか」と思ったらどうにもできない。
公式のマニュアルには「5秒間リセットスイッチを押してデフォルトリスタートしてください」と書いてあるが、これをしても通常の再起動しかしなかった。

次にトラブルシューティングガイドを読むと「起動時にCtrl Nを3回以上押下してください」とあるのでやってみると、ユーザー名operator, パスワード無しで入ることができた。
operatorユーザーでログインしたらenableで管理者モードになりpasswordコマンドでパスワードを変更し再起動すれば完了

なはずだった。
なぜか設定したパスワードでoperatorにログインできない...

その後、再起動をreloadコマンドではなく物理的に行う、rename userでユーザー名を変更してみるなどした結果ログインできるようになったが何が原因かは分からない。
時間があればそのうち調べるかもしれない。

Rubyのgoogle-api-clientでGoogle Custom Search APIを使う

Google Custom Search APIとは

Google検索の結果をJSONで取得できたら便利ですよね。
スクレイピングで頑張るという手も有りますが、ライセンスやサイトの仕様変更を気にする必要が有ります。
そんなときは Google Custom Search API を使いましょう。 手軽に検索結果のJSONを取得できます。

APIキーとCustom Searrch Engine IDの取得

このAPIを使うにはGoogleAPIのAPIキーとCustom Search EngineのIDが必要になります。

その手順については既にいくつか記事があるのでそれらを参照してください。

一点だけ注意事項が有ります、Custom Search Engineの Search the entire web は一先ずONにしておいてください。
OFFだと予め登録したドメインしか検索してくれません。
f:id:u10e10:20190201200848p:plain

動作確認

APIキーとCSE_IDの用意ができたら、curlで動作確認してみましょう。
API_KEYとCSE_IDを取得したキーとIDで置き換えて、QUERYを検索したいワードに置き換えて実行してください。

curl 'https://www.googleapis.com/customsearch/v1?key=API_KEY&cx=CSE_ID&q=QUERY'

大量のJSONが出力されれば成功です。

google-api-client

RubyからこのAPIを使う場合はgoogle-api-ruby-clientを使うと少し手間が省けます。

gem install google-api-client

以下のコードは入力した文字列で検索して、結果のタイトルとURLを出力する例です。

#!/usr/bin/env ruby
require 'google/apis/customsearch_v1'

API_KEY = ''
CSE_ID = ''

searcher = Google::Apis::CustomsearchV1::CustomsearchService.new
searcher.key = API_KEY

print "QUERY> "
query = gets.chomp

results = searcher.list_cses(query, cx: CSE_ID)
items = results.items
pp items.map {|item| { title: item.title, link: item.link} }

指定できるパラメータはここに書いてあります。
developers.google.com

例えば特定のサイトのみ検索対象にしたいばあいは、site_searchを使います。

searcher.list_cses(query, cx: CSE_ID, site_search: 'example.com')

フリーエディションだと1日100件のリクエスト制限があるので検証のときは注意しましょう。
戻り値をいじくり回したいときは binding.pry がおすすめです。

プロキシのストレスをちょっと減らす for Linux

この記事は この記事は、Kogakuin Univ Advent Calendar 2018 の25日目です。 昨日は 研究室のサーバに接続したい です。

弊学のネットワークはプロキシ必須で苦しいですよね。ストレスMAXですよね。
特にラップトップにLinux入れて持ち歩いてる人は大変ですよね、GUICLIのそれぞれでプロキシの設定が必要なので大変ですよね。

この記事はLinuxの面倒なプロキシ切り替えを自動化する方法を書きます。
自動切り替えの対象は主にGUI(chrome系ブラウザ)、CLISSHです。
環境はArchLinux, Plasma, Zshですが細部をちょっと変更すれば動くはずです。

GUI

Gnome系やPlasma(KDE)系のデスクトップには以下のようなProxyの設定画面が用意されています。
f:id:u10e10:20181225221654p:plain

少し前のChrome系のブラウザはGUIのプロキシ設定ではなく、起動時に環境変数でプロキシの設定を渡す必要がありました。
最近はGUIの設定を見てくれるので、プロキシ設定のためにブラウザを再起動する必要がなくなりました。

さて、GUIのプロキシの設定ですが、いちいち手動で設定を切り替えるのは面倒です。これを自動化しましょう。
KDEkwriteconfig5 というコマンドを使うことで、GUIの設定を変更できます。()
プロキシを有効にするコマンドは以下です。1になっている部分を0にすると無効にできます。

kwriteconfig5 --file kioslaverc --group 'Proxy Settings' --key ProxyType 1

これを大学のネットワークに接続したときだけ自動で実行するようにしましょう。 この場合はNetworkManager-dispatcher.serviceが便利です。
sudo systemctl enable --now NetworkManager-dispatcher.service でサービスを起動すると /etc/NetworkManager/dispatcher.d にあるスクリプトを状態変化時に実行してくれます。
ここに、GUIのプロキシを切り替えるスクリプトを設置しましょう。
以下のスクリプトでは大学のネットワーク判定をIPアドレスで行っています。弊学はローカルネットワークにグローバルIPが降ってくるのでこういうとき便利です。
他の判定方法としてはSSIDを確認する(nmcli -t -f name connection show --active)か、domainを見る(nmcli | grep domains | awk '$0=$2')というのが有ります。

#!/bin/zsh

log_tag='ProxyAutoToggle'

ip-sub(){
  default_dev="$(ip -4 route show default | awk '{print $5}' | head -1)"

  if [[ -z $default_dev ]]; then
    return 1
  fi

  ip -4 a show dev "${default_dev}" | grep -m1 'inet' | awk '{print $2}'
}

kde-proxy-toggle() {
  user="${1:? username}"
  mode="${2:? 0 or 1}"

  sudo --user="${user}" --group="${user}" kwriteconfig5 --file kioslaverc --group 'Proxy Settings' --key ProxyType "${mode}"
  sudo --user="${user}" --group="${user}" dbus-send --type=signal /KIO/Scheduler org.kde.KIO.Scheduler.reparseSlaveConfiguration string:''
}

case "$(ip-sub)" in
  133.80.*.*/*)
    logger 'proxy: enable school'

    for user in $(users | tr ' ' '\n' | sort --unique); do
      logger "user: ${user}"
      kde-proxy-toggle "${user}" 1
    done
    ;;
  *)
    logger 'proxy: disable'

    for user in $(users | tr ' ' '\n' | sort --unique); do
      kde-proxy-toggle "${user}" 0
    done
    ;;
esac

logger -p user.notice -t "${log_tag}" "configuration done."

CLI

CLIはhttp_proxyやhttps_proxyなどの環境変数を使ってプロキシの設定をします。
例えば以下のようにします。

export https_proxy="example.com:8080"

プロキシを無効にするには環境変数を消します。

unset https_proxy

さて、環境変数のセットとアンセットを自動化しましょう。
以下のスクリプトをzshrcに貼ってください。
proxy-onは引数にプロキシサーバーを渡すと必要な環境変数に値をセットしてくます。
proxy-offは反対に全てのプロキシ環境変数をアンセットします。
config-proxyはipアドレスでネットワークを判断してproxy-on、もしくはproxy-offを呼んでくれます。
つまり、config-proxyをコマンド実行直前に呼び出せれば良いわけです。
zshではpreexecというフックを使うことでコマンド実行前に関数を実行することができます。
最終行の add-zsh-hook preexec config_proxy がそうです。

proxy-on () {
  proxy="${1:? server:port}"

  export http_proxy="http://${proxy}"
  export HTTP_PROXY="${http_proxy}"
  export https_proxy="http://${proxy}"
  export HTTPS_PROXY="${https_proxy}"
  export ftp_proxy="${proxy}"
  export FTP_PROXY="${ftp_proxy}"
  export rsync_proxy="${proxy}"
  export RSYNC_PROXY="${rsync_proxy}"
  export all_proxy="${proxy}"
  export ALL_PROXY="${all_proxy}"
  export no_proxy='localhost,127.0.0.1,localaddress,.localdomain.com'
  export NO_PROXY="${no_proxy}"
}

proxy-off () {
        unset http_proxy
        unset HTTP_PROXY
        unset https_proxy
        unset HTTPS_PROXY
        unset ftp_proxy
        unset FTP_PROXY
        unset rsync_proxy
        unset RSYNC_PROXY
        unset all_proxy
        unset ALL_PROXY
        unset no_proxy
        unset NO_PROXY
}

ip-sub(){
  default_dev="$(ip -4 route show default | awk '{print $5}' | head -1)"

  if [[ -z $default_dev ]]; then
    exit 1
  fi

  ip -4 a show dev "${default_dev}" | grep -m1 'inet' | awk '{print $2}'
}

config_proxy(){
  case "$(ip-sub)" in
    133.80.*.*/*)
      proxy-on "cache.ccs.kogakuin.ac.jp:8080"
      ;;
    *)
      proxy-off
      ;;
  esac
}


autoload -Uz add-zsh-hook
add-zsh-hook preexec config_proxy

SSH

さて、SSHはサーバーへのアクセス以外にも、GitHubへのアクセスでよく使いますね。
弊学ではsshポートが閉じているので、どうにかしたいと思っている人は多いと思います。 本当は解決方法を書こうと思っていたのですが、書いてる途中に「あれっ グレーじゃね?」と思ってしまい一旦保留することにしました。
ホワイト判定されるか、他のホワイトな方法が見つかり次第、追記します。

終わりに

さて、本日のこの記事でKogakuin Univ Advent Calendar 2018は終了です。
公開がギリギリになってしましすみません :pray:

Arch dm-cryptでデバイスを透過的に暗号化する

前座

先日ThinkPad X1を購入しました。 初期のOSとして当然Windowsが入っているわけですが、最近は初期状態でBitLockerによるデバイスの暗号化が施されているようですね。
少し感動しました。

ちなみに、Linuxを入れるためにSecureBootを無効にするとTPM(セキュリティチップ)にある鍵にアクセスできなくなりWindows起動時にデバイスをオートアンロックできなくなります。
その場合はhttps://account.microsoft.com/devices/recoverykeyに載っている49文字の鍵を入力することでアンロックできます。

本題

さて、PCを新調したのでLinuxを入れたいわけですが、Windowsだとデバイスが暗号化されているのにわざわざ手間を掛けて入れたLinuxは生でデータを保存しているというのはなんだかかっこ悪いですね。
そういう訳で、Linuxでのデバイス暗号化を行います。

この記事はArchWikiを参考にしています。ざっくりと解説はしますが詳細はWikiを見てください。
また、Archをインストールしたことがある方を基準に話を進めます。

インストールガイド - ArchWiki
- ディスク暗号化 - ArchWiki
- - dm-crypt - ArchWiki
- - - dm-crypt/ドライブの準備 - ArchWiki
- - - dm-crypt/デバイスの暗号化 - ArchWiki
- - - dm-crypt/システム設定 - ArchWiki
- - - - mkinitcpio - ArchWiki
- - - dm-crypt/スワップの暗号化 - ArchWiki

バイスを暗号化するには

ディスク暗号化 - ArchWikiによるとLinuxにおける暗号化にはスタックファイルシステムの暗号化とブロックデバイスの暗号化があるようです。
今回はdm-cryptによるブロックデバイスの暗号化を行います。

dm-cryptはLinux標準のdevice-mapperを用いて透過的な暗号化デバイスの利用を可能にします。
dm-cryptにはLUKSモード(Linux Unified Key Setup Mode)とplainモードがあります。
詳細は省きますがplainモードよりLUKSモードのほうが賢く便利です。

LUKS

  • 必要な情報の全てをディスクに保存する
  • 1つのデバイスに対して複数の鍵を保存できる
  • 利用開始後に鍵の追加・削除・変更が可能
  • 鍵はパスフレーズとキーファイルの2種類がある

plainを使うメリットは恐らく無いためLUKSを使いましょう。

作業の流れ

この記事はdm-crypt - ArchWikiを参考に作業を進めていきます。

  1. Archインストール準備のパーティショニングまでを済ませる
  2. dm-cryptで暗号化対象のパーティションをセットアップ
  3. セットアップしたパーティションマッピング
  4. マッピングしたデバイスに通常通りファイルシステムを作成しマウント
  5. 以降は非暗号化時と同様
  6. /をアンロックするためのGRUBとinitramfsの設定

1はパーティションを切るところまです。
ファイルシステム作成やfstabの生成はまだ待ってください。 どの様にパーティションを切るかは自由ですが、ルートパーティションとブート(ESP)パーティションは分けてください。
2によってデバイス暗号化の下地を作ります。
3で暗号化したパーティションを通常のパーティションと同じ様に扱えるようにします。
具体的には /dev/mapper にデバイスを作成します。
4では3で作成された /dev/mapper にあるデバイスに通常通りファイルシステムを作成しマウントします。
3でマッピングされたデバイスに対して操作を行うことで透過的に暗号デバイスを使用できます。
一部の操作では特別な手順を必要としますが、通常は非暗号化時とまったく同じ操作が可能です。

完成形

Windowsとのデュアルブートにしたかったため、パーティション構成は以下の様になりました。
マッピングされたデバイスlsblk コマンドではnvme0n1p5とcrypthomeのように表示されます。
/, /home, /boot, swapWindowsパーティションがあります。
スワップパーティションについては今回は暗号化せずそのまま使います。
暗号化されているのは //homeの2つです。
/boot にはWindowsLinuxブートローダーが入っています。

NAME           TYPE  MOUNTPOINT
nvme0n1        disk  
├─nvme0n1p1    part  /boot (ESPパーティション)
├─nvme0n1p2    part  windows-reserved
├─nvme0n1p3    part  windows-recovery
├─nvme0n1p4    part  windows
├─nvme0n1p5    part
│ └─crypthome  crypt /home
├─nvme0n1p6    part 
│ └─cryptroot  crypt /
└─nvme0n1p9    part  [SWAP]

1. パーティショニング

上の完成形を目標にパーティションを切ります。
/boot パーティションUEFIのESPパーティションです。
最初からある(Windowsによって作られた)ものを使い回します。
既に中身がありますが、これを消すとWindowsが起動しなくなるので注意しましょう。
自分で作成するのは /, /home, swapの3つです。
ArchLinuxのisoで適当なCLIを使うのもいいですが、私はManjaro Linux(XFCE)をライブ起動してGPartedを使うのをおすすめします。
軽くて使い勝手がいいのでレスキューツールとして持ち歩くといいでしょう。

2. 暗号化パーティションのセットアップ

dm-crypt/デバイスの暗号化 - ArchWiki

dm-cryptの操作にはcryptsetupを使用します。

pacman -S cryptsetup

以下のようにパーティションを指定してluksFormatします。
実行するとパスフレーズの入力が求められます。

# /
cryptsetup -y -v --key-size=512 luksFormat /dev/nvme0n1p6
# /home
cryptsetup -y -v --key-size=512 luksFormat /dev/nvme0n1p5

--key-sizeで指定した値の半分の値が実際のサイズになります。
この例ではAES-256を使用しています。
また、cryptsetup luksFormat device /path/to/mykeyfile のようにするとパスフレーズの代わりにキーファイルを使用できます。
LUKSのオプションについてはLUKS モードの暗号化オプション - ArchWikiを見てください。

LUKSの魅力は複数の鍵を登録できることです。
せっかくなので初期のパスフレーズ(もしくはキーファイル)とは別のキーファイルを追加してみましょう。
以下のコマンドで2048ビットのキーファイルを生成できます。
保存場所(of=)は適当に選んでください。

dd bs=512 count=4 if=/dev/urandom of=/luks_keyfile
chmod 400 /luks_keyfile

既存の暗号化デバイスに新たな鍵を登録するには以下のようにします。

cryptsetup luksAddKey /dev/nvme0n1p6 /luks_keyfile
cryptsetup luksAddKey /dev/nvme0n1p5 /luks_keyfile

鍵は最大8つまで登録することができます。 現在登録されている鍵を確認してみましょう。

cryptsetup luksDump /dev/nvme0n1p6 | grep BLED

3. セットアップしたパーティションマッピング

暗号化したパーティションはそのままでは使用できません。
通常のパーティションと同じ様に扱えるようにするためにマッピングします。
cryptrootcrypthome などの名前は自由に付けて構いません。

cryptsetup open /dev/nvme0n1p6 cryptroot
cryptsetup open /dev/nvme0n1p5 crypthome

/dev/mapper/ を確認してみましょう。
指定した名前で新たなデバイスができているはずです。

ls /dev/mapper/

これで暗号化に関する作業はほとんど終了しました。
以降、パーティションに対する操作は全て/dev/mapper/cryptrootなどの/dev/mapper/下のデバイスに対して行います。
/dev/nvme0n1p6などのluksFormatしたデバイスを直接操作してはいけません。

4. ファイルシステム作成とマウント

通常と同じ様にファイルシステムを作成します。
おすすめはBtrfsです。

mkfs.btrfs /dev/mapper/cryptroot
mkfs.btrfs /dev/mapper/crypthome

/, /home, /boot をそれぞれマウントしてみましょう。
下記の-oから始まるマウントオプションは私がBtrfsで使っているものです。 省略して構いません。
/bootは暗号化していないため、そのままのパスを使います。

mount -o noatime,compress=lzo,space_cache,ssd /dev/mapper/cryptroot /mnt
mount -o noatime,compress=lzo,space_cache,ssd /dev/mapper/crypthome /mnt/home
mount /dev/nvme0n1p1 /mnt/boot

5. システムのインストール

通常通りにシステムをインストールしましょう。
注意としてはこの記事では/ をオートアンロックするためにGRUBを使います。

今回の場合は/homeをオートアンロックするためにcrypttabを使います。
オートアンロックに使うキーファイルは/mnt/下の適当なディレクトリにコピーしておきましょう。

echo 'crypthome  /dev/nvme0n1p5 /etc/luks_keyfile' >> /mnt/etc/crypttab
cp /luks_keyfile /mnt/etc/

例では分かり易さを優先してデバイスをパス指定していますが、馴れている方はUUIDを使いましょう。

この記事で前提とする/bootのファイルツリーの抜粋を示しておきます。

/boot
├── BOOT
│   └── BOOT.SDI
├── EFI
│   ├── Boot
│   │   ├── LenovoBT.EFI
│   │   ├── License.txt
│   │   ├── ReadMe.txt
│   │   └── bootx64.efi
│   ├── Microsoft
│   │   ├── Boot
│   │   └── Recovery
│   └── grub
│       └── grubx64.efi
├── grub
│   ├── fonts
│   ├── grub.cfg
│   ├── grubenv
│   └── x86_64-efi
├── initramfs-linux-fallback.img
├── initramfs-linux.img
└── vmlinuz-linux

GRUBのインストールには以下を実行しました。

grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=grub

もし、VirtualBoxEFIを有効にして検証している場合は /boot/EFI/grub/grubx64.efi/boot/EFI/boot/bootx64.efiにリネームしてください。

6. GRUBとinitramfsの設定

dm-crypt/システム設定 - ArchWiki

この記事では/を暗号化しましたが、OSが起動するためにはブートローダーがOSを起動する際にデバイスをアンロックしなければなりません。
起動時のアンロックには主に3つの方法があります。

  1. プロンプトにパスワードを入力
  2. 外部ストレージのキーファイルを読み込む
  3. initramfsにキーファイルを仕込む(あまり意味ない)

1はGRUBからOSを選択した後にプロンプトが表示され、パスワード入力が求められます。
もしあなたが1台のPCを専有(ユーザーが1人)なら、アカウントの自動ログインを有効にすることで今までと同じ回数のパスワード入力でセキュリティを高めることができます。

2はキーファイルを入れたUSBメモリなどを持ち歩くことでパスワード入力を省略できます。
バイスを管理し持ち運ぶ手間を惜しまなければ良い方法です。

3は外部ストレージに入れるべきキーファイルをinitramfsに入れることでパスワード入力や外部ストレージを持ち運ぶ手間を省くことができます。
ただし、initramfsは暗号化されていない/bootにあるため知識のある人間に対する防御力は0です。
GRUBからThinkPadに搭載されているセキュリティチップにアクセスできれば解決しそうですが、それはまた後日検証したいと思います。 解決方法を知っていたら是非教えてください。
この方法に残された唯一の利点はストレージを破棄する際、データの破棄が鍵の削除のみで済むことです。

私は現在パスワード入力を使っていますが、この記事では設定例として多少難しいinitramfsにキーファイルを仕込む方法を示します。
どれも設定方法はほぼ同じです。

/を暗号化した場合のLinux起動は以下です。

  1. 電源が入る
  2. UEFI/bootGRUBを起動
  3. GRUBinitramfsでミニマムなLinuxを起動
  4. /をアンロック(cryptrootにマッピング)
  5. /をルートディレクトリとしてLinuxを起動
  6. /etc/crypttabを読み/homeをアンロック(/dev/mapper/crypthomeマッピング)
  7. /etc/fstabで各パーティションをマウント

mkinitcpio - ArchWiki
起動時にアンロックするためにinitramfsにフックを追加する必要があります。
/etc/mkinitcpio.confを開きHOOKSのudevより後にencryptを挿入してください。
アンロック時にキーボードでパスワードを入力する場合はencryptよりも前にkeyboardを挿入する必要があります。
また、plymouthを無効にする必要があるのでHOOKSからplymouthを削除してください。

以下が設定例です。
BINARIESはbtrfsを使ってる場合に必要です。
もしThinkPad X1(G6)を使っていて、CSMを無効にしているならMODULESi915を追加してください。 FILESにファイルパスを指定すると、initramfs内のミニマムなLinux/の同じパスにファイルが配置されます。
initramfsにキーファイルを含めてオートアンロックする場合はキーファイルのパスを指定してください。

MODULES=(i915)
HOOKS=(base udev autodetect modconf keyboard keymap block encrypt filesystems fsck)
BINARIES=(/usr/bin/btrfs)
FILES=(/etc/luks_keyfile)

設定ファイルを書き換えたらでinitramfsを再生成することで反映されます。

mkinitcpio -p linux

次に、GRUBで暗号化された/を認識するために/etc/default/grubGRUB_CMDLINE_LINUX_DEFAULTカーネルパラメーターを設定しましょう。

GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=/dev/nvme0n1p6:cryptroot cryptkey=rootfs:/etc/luks_keyfile root=/dev/mapper/cryptroot"

cryptdeviceは暗号化(luksFormst)したデバイスマッピング後の名前をコロン区切りで指定します。
例ではデバイスのパスを指定していますが、UUID指定も可能です。
cryptdevice=UUID=aaaaaaaa-bbbb-cccc-dddd-eeee99998888:cryptroot

cryptkeyでキーファイルのパスを指定します。
これを省略すると起動時にパスワード入力のためのプロンプトが表示されます。
フォーマットはdevice:fstype:filepathです。
deviceには/dev/sda1や /dev/disk/by-uuid/aaaaaaaa-bbbb-cccc-dddd-eeee11112222を指定します。 外部ストレージにキーファイルを保存する際はUUIDを使うようにしましょう。 そうでないとある日突然パスが変わりOSが起動できなくなる可能性があります。 fstypeにはvfatなどストレージのファイルシステムを指定してください。 filepathは名前の通りキーファイルまでのパスを指定します。 initramfsにキーファイルを仕込む場合はdevicerootfsを指定しfstype`を省略します。

rootマッピング後の/のパスです。 /dev/mapper/下にあるデバイスを指定しましょう。

grubの設定が終わったらgrub.cfgを再生成して変更を反映してください。

grub-mkconfig -o /boot/grub/grub.cfg

これでシステムの暗号化は完了です。
再起動し、暗号化されたデバイス上でLinuxが動作することを確認したらスワップの暗号化暗号化されていない boot パーティションのセキュア化を試してみるのもいいでしょう。

SlackAppを最小化状態で自動起動する for Linux

私はログイン時にSlackを立ち上げてほしいけど、ウィンドが表示されるのは邪魔だなー と思う派です。

PCを起動してターミナルを立ち上げてコマンドを実行! としようとしたときに自動起動したSlackAppに入力が取られて、変なメッセージを送ってしまったことが何度かあります。

執筆時点(2018/5/12)では最小化状態(トレイアイコン)で起動する設定はありませんでした。 ただ、slack コマンドに引数で --startup を渡して起動するとウィンドを表示せず起動できるようです。

Linuxはログイン時に ~/.config/autostart/ にあるデスクトップエントリ(拡張子が .desktop なファイル)を読み込み、アプリケーションを自動起動します。 ユーザが自動起動にしたアプリケーションはここにデスクトップエントリが置かれているはずです。

SlackAppを自動起動にしている場合は slack.desktop と言うファイルがあります。 私の環境では、slack.desktop/usr/share/applications/slack.desktopシンボリックリンクになっていました。 なので、編集するには sudo が必要です。

[Desktop Entry]
Name=Slack
Comment=Slack Desktop
GenericName=Slack Client for Linux
Exec=env LD_PRELOAD=/usr/lib/libcurl.so.3 /usr/bin/slack %U
Icon=slack
Type=Application
StartupNotify=true
Categories=GNOME;GTK;Network;InstantMessaging;
MimeType=x-scheme-handler/slack;

Exec が実際に実行するコマンドを指定しています。 envなんたらは無視して、/usr/bin/slack が本体です。 なので、この直後に --startup を挿入すれば最小化状態で自動起動するようになります。

Exec=env LD_PRELOAD=/usr/lib/libcurl.so.3 /usr/bin/slack --startup %U

おそらく、SlackAppをアップデートすると /usr/share/applications/slack.desktop は上書きされて --startup が消えるので、~/.config/autostart/ にはシンボリックリンクではなく、コピーを置くなどのしたほうがいいです。

clang-renameをVimからサクッと呼び出してC++のリネームを快適にする。

最近Go言語を使ってるんですが、この言語gofmtgorenamegoimportsなどのツールが充実していて良いですね。

C系の言語にも同じようなツールは存在します。

Welcome to Extra Clang Tools’s documentation! — Extra Clang Tools 5 documentation

この内clang-formatは既にVimプラグインが存在します。

C や C++ のコードを自動で整形する clang-format を Vim で - はやくプログラムになりたい

今回はclang-renameVimプラグインを作りました。
clang-renameは識別子をリネームするツールです。

github.com

clang-renameの導入

Arch

公式リポジトリからclang-tools-extraを入れましょう。

Ubuntu

clang-3.5以上のバージョンに含まれています。
ただしclang-renameのバージョンが古いと後述のqualified name機能が使えません。
この機能を使いたい場合はPPAなどからの導入を検討してください。
clang-rename --help-qualified-nameが表示されれば大丈夫です。

使い方

単一ファイルの場合:ClangRenameCurrent:ClangRenameQualifiedNameを使えば用が済むでしょう。

{new_name}を省略した場合は入力プロンプトが表示されます。

  • ClangRenameOffset [{offset} [{new_name}]]

オフセットを指定してリネームします。
例えばファイルの先頭のオフセットは0です。
-1を指定すると現在のカーソル位置をオフセットとして扱います。

  • ClangRenameCurrent [{new_name}]

カーソル位置のシンボル名を変更します。
内部でClangRenameOffsetを実行しています。

  • ClangRenameQualifiedName [{qualified_name} [{new_name}]]

シンボル名を指定してリネームします。
このコマンドを使うにはclang-rename-qualified-nameオプションをサポートしている必要があります。

  • ClangRename [...]

引数によって動作が変わります。
0個か1個ならClangRenameCurrentが実行されます。
2個ならClangRenameQualifiedNameが実行されます。

その他

  • <Plug>(clang_rename-current) ClangRenameCurrentのキーマップ
  • g:clang_rename#flags clang-renameの引数
  • g:clang_rename#compile_flags clang-renameが解析するときに使うコンパイルオプション(-std=c++11とか)

終わりに

実はclang extra toolsには標準でVimEmacs向けのスクリプトが付属してます。
ですが、微妙に使いづらかったので、このプラグインを作りました。

vim-fakearray ダミー配列を手軽に入力するプラグイン作った

github.com

プログラミングをしていると適当な配列が欲しい時ありますよね。
「0〜100の整数からランダムに10個選んだ配列」などなど。
そんなVimmerの要望を叶えるのがvim-fakearrayです。
vim-fakearrayはvim-fakeに依存しています。

vim-fakeについては作者の記事を参考にしてください。
qiita.com

インサートモードに<Plug>(fakearray)のキーマップを割り当てれば、 プロンプトを呼び出してダーミー配列を手軽に挿入できます。

解説

呼び出し階層

<Plug>(fakearray)fakearray#genfakearray#valfake#gen|fake#int|fake#float|fake#chars

fakearray#val

fakearray#val(first, second)は引数によって呼び出すfake#関数を変えます。

first second 呼び出し
整数 整数 fake#int(first, second)
少数or整数 少数or整数 fake#float(first, second)
文字列 整数 fake#chars(fake#int(1, second), first)
文字列 空文字列 '' fake#gen(first)
fake#int fake#float

この2つは第1引数〜第2引数の範囲の値を返しますが、Vimのバージョンによっては正しく動作しないようです。
恐らくVimが内部で扱う整数のサイズに依存しているのでしょう。
64bit整数が追加されたのは7.4.1976のようです。
Vim8.0とNeovim0.2では正常に動作しました。

fake#chars

第1引数は生成する文字数です。
第2引数は'abc'のような適当な文字列の他に、'\w'などの文字セットを使うことが出来ます。
詳細はvim-fakeのドキュメントを見てください。

fake#gen

'job''country''word'などのカテゴリを渡すことが出来ます。

fakearray#gen

fakearray#gen(num, first, second)fakearray#valnum回呼び出して、結果をg:fakearray#separator区切りで結合します。
b:fakearray_separatorも使えます。

(fakearray)

プロンプトに入力する値の個数によって動作が変わります。

入力数 動作
1 fakearray#gen({input num}, g:fakearray#prompt_first, g:fakearray#prompt_second)
2 fakearray#gen({input1 num}, {input2 str}, '')
3 fakearray#gen({input1}, {input2}, {input3})

入力数1と3は見たまんまです。
2のときはfakearray#genの第3引数を''にしているのでfake#genが呼ばれます。
内部で入力値にevalをかけているので文字列を入力するときはクオートを省略してはいけません。

キーマップ

インサートモードのキーマップは悩みますよね。
Emacsバインドにしている人は特に。
プラグインのデフォルトでは<F3>に割り当てていますが、私は<c-/>aに割り当てています。
ただし、<c-/>をテキストとして入力しても動作しないので、代わりに<c-v><c-/>特殊文字を入力する必要があります。

最後に

Vimには乱数を生成する関数がないので、このプラグインではvim-fakeを使いました。
乱数を生成する方法は他にもあります。

初めてvim-themisでテストを書きました。
なかなか面白かったです。