vimのカレントファイルをブラウザで開く

openコマンドを使う

  • vimでは%でカレントファイルのパスを取得できる
  • !はOS用のコマンド(echopwdなど)の先頭につけることでvimエディタ上からOS用コマンドを実行することができる
  • openはファイルのデフォルトで開くソフトに設定されているソフトで開かれる
1
:!open %

入力の手間を減らす

  • これまでのコマンドをショートカットキーで呼び出せるように.vimrcに追記する
1
2
3
4
5
" スペースキーをショートカットのトリガーとして認識するように設定
let mapleader = "\<Space>"

" スペースキー + o で実行できる
nnoremap <Leader>o :!open %<CR>

フォーカスを戻す(Mac)

  • openコマンドを使うとフォーカスがブラウザになってしまうので、AppleScriptを使ってフォーカスをVim(iTerm)に戻す
    • terminal_focusの対象アプリを変更すればiTerm以外のソフトにも対応可能

~/.vim/plugin/BrowserOpen.vim

1
command! -bar BrowserOpen !open % | osascript $HOME/bin/terminal_focus.scpt

~/bin/terminal_focus.scpt

1
tell application "iTerm" to activate

~/.vimrc

1
2
3
4
5
" スペースキーをショートカットのトリガーとして認識するように設定
let mapleader = "\<Space>"

" スペースキー + o で実行できる
nnoremap <Leader>o :BrowserOpen<CR>

AppleScriptでVimの保存時のファイル更新を取得してブラウザを更新する

概要

Vimでファイルを保存した時にファイルをブラウザで開いている場合(HTMLを書いている場合など)、いちいちブラウザにフォーカスを当てて、ブラウザ再読み込みを行うのは面倒くさいので、

  1. ブラウザにフォーカスを当てる
  2. command + rイベントを発行
  3. フォーカスをターミナルに戻す

の動作を自動化する

Vimで使用するコマンドを実装する

  1. /Users/daiki/.vim/pluginchrome.vimを配置
    • ディレクトリがない場合は作成する
  2. 以下のコードをchrome.vimに書き込んで保存

chrome.vim

1
2
3
command! -bar ChromeReload silent !osascript $HOME/bin/chrome_reload.scpt && osascript $HOME/bin/terminal_focus.scpt
command! -bar ChromeStartObserve ChromeStopObserve | autocmd BufWritePost <buffer> ChromeReload
command! -bar ChromeStopObserve autocmd! BufWritePost <buffer>

ブラウザにフォーカスを当ててリロードするコマンドを実装

  1. /Users/daiki/binchrome_reload.scptを配置
    • ディレクトリがない場合は作成する
  2. 以下のコードをchrome_reload.scptに書き込んで保存

カスタマイズ

  • 1行目:tell application "safari" to activatesafariの部分を別のブラウザの名前に変更すると開くブラウザを変更できる

chrome_reload.scpt

1
2
tell application "safari" to activate
tell application "System Events" to keystroke "r" using {command down}

ターミナルにフォーカスを戻すコマンド

  1. /Users/daiki/binterminal_focus.scptを配置
    • ディレクトリがない場合は作成する
  2. 以下のコードをterminal_focus.scptに書き込んで保存

カスタマイズ

  • "Terminal"の部分を書き換えると別アプリにフォーカスを当てられる

terminal_focus.scpt

1
tell application "Terminal" to activate

Vimで使用するには

vimを開いて、ブラウザで更新したいファイルに対して以下のコマンドを打つ

  • :ChromeReload:1回ブラウザをリロードする
  • :ChromeStartObserve:Vimで保存するたびにブラウザをリロードする
  • :ChromeStopObserve:ChromeStartObserveの保存時の自動リロードを停止する

参考

https://lukesilvia.hatenablog.com/entry/20101023/p2

Swiftで迷路を解く

目的

  • Swiftの勉強

制作時間

  • 4時間

コード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
import UIKit

var targetMaze = [
["#","S","#","#","#","#","#","#","#","#","#"],
["#"," ","#","#","#","#","#","#"," ","#","#"],
["#"," "," "," "," ","#","#"," "," ","#","#"],
["#"," ","#","#"," "," "," "," ","#","#","#"],
["#","#","#","#"," ","#","#","#","#","#","#"],
["#"," "," "," "," ","#"," "," "," ","#","#"],
["#"," ","#","#","#","#"," ","#"," ","#","#"],
["#"," ","#","#","#","#"," ","#"," ","#","#"],
["#"," "," "," "," "," "," ","#"," ","#","#"],
["#","#","#","#","#","#","#","#","G","#","#"]
]

enum MapType:String
{
case Start = "S"
case Goal = "G"
case Wall = "#"
case Root = "+"
}

struct Vec2:Equatable{
var X:Int = 0
var Y:Int = 0
}

struct Direction
{
var Now:Vec2

var Up:Vec2?
var Down:Vec2?
var Right:Vec2?
var Left:Vec2?
}

func CheckRoad(maze:[[String]],pos:Vec2?,beforPos:Vec2,maxPos:Vec2,checkType:MapType)-> Direction?
{
if(pos == nil) {
return nil
}

// 上,右,下,左
var retPos:Direction = Direction(Now:pos!,Up:nil,Down: nil,Right: nil,Left: nil)

// 上下左右の座標を取得
let minusY = retPos.Now.Y - 1
let plusY = retPos.Now.Y + 1
let minusX = retPos.Now.X - 1
let plusX = retPos.Now.X + 1

// マップ内かチェック
if(minusY >= 0){
retPos.Down = Vec2()
}
if(plusY < maxPos.Y){
retPos.Up = Vec2()
}
if(minusX >= 0){
retPos.Left = Vec2()
}
if(plusX < maxPos.X){
retPos.Right = Vec2()
}

// 壁があるかチェック
if(retPos.Down == Vec2() &&
(maze[minusY][retPos.Now.X] != checkType.rawValue) &&
beforPos != Vec2(X: retPos.Now.X, Y: minusY))
{
retPos.Down = Vec2(X:retPos.Now.X,Y:minusY)
}
else{
retPos.Down = nil
}

if(retPos.Up == Vec2() &&
(maze[plusY][retPos.Now.X] != checkType.rawValue) &&
beforPos != Vec2(X: retPos.Now.X, Y: plusY))
{
retPos.Up = Vec2(X:retPos.Now.X,Y:plusY)
}else{
retPos.Up = nil
}

if(retPos.Left == Vec2() &&
(maze[retPos.Now.Y][minusX] != checkType.rawValue) &&
beforPos != Vec2(X: minusX, Y: retPos.Now.Y))
{
retPos.Left = Vec2(X:minusX,Y:retPos.Now.Y)
}else{
retPos.Left = nil
}

if(retPos.Right == Vec2() &&
(maze[retPos.Now.Y][plusX] != checkType.rawValue) &&
beforPos != Vec2(X: plusX, Y: retPos.Now.Y))
{
retPos.Right = Vec2(X:plusX,Y:retPos.Now.Y)
}else{
retPos.Right = nil
}


return retPos
}

// 指定したターゲットの位置を返す
// 見つからなかった場合は、nilが返えってくる
func serchTargetPoint(maze:[[String]],targetMapType:MapType)->Vec2?
{
var retPos:Vec2? = nil

let mazeYCount = maze.count - 1
let mazeXCount = maze[0].count - 1

for Y in 0...mazeYCount
{
for X in 0...mazeXCount{
let checkValue = maze[Y][X]

if(checkValue == targetMapType.rawValue)
{
retPos = Vec2(X:X,Y:Y)
}
}
}

return retPos
}

func printMaze(maze:[[String]]){

let mazeYCount = maze.count - 1
let mazeXCount = maze[0].count - 1

for Y in 0...mazeYCount
{
print("\n")
for X in 0...mazeXCount{
print(maze[Y][X], terminator: "")
}
}

print("\n")
}


printMaze(maze:targetMaze)

let SPos = serchTargetPoint(maze:targetMaze,targetMapType:MapType.Start)
let GPos = serchTargetPoint(maze:targetMaze,targetMapType:MapType.Goal)

print(SPos ?? "スタートなし")
print(GPos ?? "ゴールなし")


let mazeYCount = targetMaze.count - 1
let mazeXCount = targetMaze[0].count - 1

let maxPos = Vec2(X: mazeYCount, Y: mazeXCount)

var RootList:Array<Direction> = Array<Direction>()
RootList.append (CheckRoad(maze:targetMaze,pos: SPos,beforPos: Vec2(X: 0,Y: 0),maxPos: maxPos,checkType: MapType.Wall)!)


var BlackList:Array<Vec2> = Array<Vec2>()

while true {

let direction = CheckRoad(maze:targetMaze,pos: RootList.last?.Up ?? nil,beforPos: RootList.last?.Now ?? Vec2(),maxPos: maxPos,checkType: MapType.Wall)

var checkFlag:Bool = false

for black in BlackList
{
if(black == direction?.Now ?? Vec2())
{
checkFlag = true
}
}

if(GPos == direction?.Now ?? Vec2())
{
break
}


if(direction != nil && !checkFlag)
{
RootList.append(direction!)
}else
{
let direction = CheckRoad(maze:targetMaze,pos: RootList.last?.Right ?? nil,beforPos: RootList.last?.Now ?? Vec2(),maxPos: maxPos,checkType: MapType.Wall)

var checkFlag:Bool = false

for black in BlackList
{
if(black == direction?.Now ?? Vec2())
{
checkFlag = true
}
}

if(GPos == direction?.Now ?? Vec2())
{
break
}


if(direction != nil && !checkFlag)
{
RootList.append(direction!)
}else
{
let direction = CheckRoad(maze:targetMaze,pos: RootList.last?.Down ?? nil,beforPos: RootList.last?.Now ?? Vec2(),maxPos: maxPos,checkType: MapType.Wall)

var checkFlag:Bool = false

for black in BlackList
{
if(black == direction?.Now ?? Vec2())
{
checkFlag = true
}
}

if(GPos == direction?.Now ?? Vec2())
{
break
}


if(direction != nil && !checkFlag)
{
RootList.append(direction!)
}else
{
let direction = CheckRoad(maze:targetMaze,pos: RootList.last?.Left ?? nil,beforPos: RootList.last?.Now ?? Vec2(),maxPos: maxPos,checkType: MapType.Wall)

var checkFlag:Bool = false

for black in BlackList
{
if(black == direction?.Now ?? Vec2())
{
checkFlag = true
}
}

if(GPos == direction?.Now ?? Vec2())
{
break
}

if(direction != nil && !checkFlag)
{
RootList.append(direction!)
}else
{
BlackList.append(RootList.last?.Now ?? Vec2())
if(RootList.count > 0)
{
RootList.removeLast()
}else
{
break
}
}
}
}
}
}

for root in RootList
{
print(root.Now)
targetMaze[root.Now.Y][root.Now.X] = MapType.Root.rawValue
}

printMaze(maze:targetMaze)

感想

  • Enumのコードに値をセットできるので、コードが読みやすい
  • ちょこちょこ出てくる制約に最初はイライラするが、書いているとなれる
  • 制約があるおかげで、コードに統一感が出る

入力補完プラグイン「Deoplete」の導入方法

vimにdeopleteを入れる

インストールに前提条件の多いPluginなので詰まるところが多かった

環境

  • M1 Mac
  • macOS Big Sur(11.2)
  • vim 8.2

公式の手順

日本語訳

最初に

注意: deopleteVimで使用する場合でも Neovim (最新のものを推奨) が必要
Vimを使用する場合Vimバージョン8.1以上 で Python 3.6.1以上timersが有効になっている必要がある。

注意: deopleteはmsgpackパッケージ1.0.0+を必要とします。pipでmsgpackパッケージをインストール/アップグレードしてください。
msgpack/msgpack-python

注意: どうしても古い msgpack を使う必要がある場合は、代わりに deoplete ver.5.2 を使ってください。
Shougo/deoplete.vim

要件

  • neovimをインストールしておく

    1
    pip3 install --user pyvim
  • neovimでpython3が有効かを確認

    • nvimを起動して以下のコマンドで1が出るか確認
      1
      :echo has("python3")

.vimrcに記述

  1. 今回はプラグイン管理ツールのVundleを使用する

    1
    2
    3
    Plugin 'Shougo/deoplete.nvim'
    Plugin 'roxma/nvim-yarp'
    Plugin 'roxma/vim-hug-neovim-rpc'
    1
    2
    " deopleteをVim起動時に有効にする
    let g:deoplete#enable_at_startup = 1
  2. :PluginInstallでインストール

トラブル対応

ファイルを開くとエラーが表示される

1
[deoplete] deoplete failed to load. Try the :UpdateRemotePlugins command and restart Neovim. See also :checkhealth.

VimにPluginマネージャー「Vundle」を入れる

環境

  • Mac MacBook Air (M1, 2020)
  • OS Big Sur v11.0.1
  • VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Oct 29 2020 23:33:57)

手順

1. ホームディレクトリにフォルダを作る

1
mkdir -p ~/.vim/bundle/Vundle.vim

2. GitHubからダウンロード

1
git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim

3. .vimrcにの先頭に設定を記述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
set nocompatible
filetype off
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()

Plugin 'VundleVim/Vundle.vim'

" 導入したいプラグインを以下に列挙
" Plugin '[Github Author]/[Github repo]' の形式で記入
Plugin 'airblade/vim-gitgutter'

call vundle#end()
filetype plugin indent on

" その他のカスタム設定を以下に書く

4. vimを開いた状態でコマンドを打ってインストール

1
:PluginInstall

zshとaliasについて

zshとは

  • 読み方: ズィーシェル
  • シェルの一種でbashの進化版

https://ja.wikipedia.org/wiki/Z_Shell

シェルとは

  • カーネルと対話するためのインターフェイス
    • シェルの名前の由来は、カーネルを包み込んでいることに由来する
  • カーネルの中に入力機能を入れない理由
    • シェル(ロジック)とカーネル(インターフェイス)を分けることでインターフェイスを他のカーネルでも使いまわすことができるようになる
    • インターフェイスのエラーでカーネルをクラッシュする可能性を排除できる

https://recruit.cct-inc.co.jp/tecblog/os/shell/

aliasとは

  • シェル上で、長いコマンドや一連のコマンドをまとめて、ひとまとめにすることのできる機能

使い方(zshの場合)

  1. ~/.zshrcに記述する
    1
    alias 別名='本来のコマンド'
  2. 保存して.zshrcLの再読み込みをする
    1
    source ~/.zshrc
  3. 別名で指定したコマンドを打って期待通り動けばOK

使用例

  • 長いパスのフォルダに移動cdしたい場合
    • このコマンドbcを打つだけで記述したcdコマンドが実行される
      1
      alias bc='cd /Users/daiki/Desktop/Blog/Daiki-Iijima.github.io/source/_posts'

複数のコマンドを1つのaliasにまとめる

  • 各コマンドを;で区切ることで連続したコマンドを記述できる
    1
    alias 別名='コマンド1;コマンド2'

使用例

  • デスクトップへ移動して、testフォルダを生成する
    1
    alias cdmk='cd /Users/daiki/Desktop;mkdir test'

引数を渡す

  • $+数字を本来の引数があるはずの位置に記述することで、引数を渡すことができる
    1
    alias 別名='mkdir $1'
    • 使用する場合
      1
      別名 引数
  • 複数の引数を渡したい場合は、$の後の数字を繰り上げていく
    1
    alias 別名='mkdir $1;mkdir $2'
    • 使用する場合
      1
      別名 引数 引数

使用例

  • メモをとるためにディレクトリとディレクトリの中にディレクトリと同名の.mdファイルをvimで編集する
    1
    alias memo='(){cd /Users/daiki/Desktop/memo;mkdir $1;vim $1.md}'

参照リンク

Ctrl+cとEscの違い

Ctrl+cはEscと同じ挙動をしない場合がある

例えば、矩形選択モードctrl + vでマルチカーソル処理を行おうとした時に、入力内容を確定するために、インサートモードを抜けるが、その時の挙動がCtrl + cEscでは、違ったものになる

  • Ctrl + c : 最初の1行しか入力内容が反映されない
  • Esc : 期待通りの選択している全ての行に入力値が反映される

対策

  1. キーマップを書き換えてCtrl + cEscと同じ扱いにする

    1
    imap <C-c> <Esc>
  2. Ctrl + [を使う

  3. 素直にEscを使用する

Markdownで改行を入れる

改行の入れ方3パターン

1. 半角空白を2つ入れて改行する

  • この改行の入れ方の場合、ブロックは別れない
  • HTMLで言うところの、<br>タグと同じ
    1
    2
    3
    1
    2
    3

2. 改行を1つ入れる

  • ブロックが別れる
  • HTMLで言うところの、<p>タグと同じ
    1
    2
    3
    4
    5
    1

    2

    3

3. <br>タグを入れる

  • HTMLのタグと同じ
    1
    1<br>2<br>3<br>

iframeのaline属性について

alineとは

  • iframe(インラインフレーム)に並ぶテキスト位置を指定できる
  • iframe(インラインフレーム)をフロートさせられる
    • フロート : 左右どちらかに寄せて、後続のテキストを回り込ませる

指定可能文字列

  • left : 左に配置して、後続の内容を右側に回り込ませる
  • right: 右に配置して、後続の内容を左側に回り込ませる
    1
    <iframe width="560" height="315" src="https://www.youtube.com/embed/DrDm7uO4Fu0" align ="right"></iframe>

iframeについて

ページ上に複数のページから読み込んだページを表示する

iframeタグを使用する

  • iframe = Inline Frame(行内フレーム)
    1
    <iframe src="table.html"></iframe>

Youtubeの動画を埋め込む

  1. youtubeで埋め込みたい動画を選択
  2. 動画の再生画面から、埋め込みコードを取得
  3. 埋め込みコードiframeで記述してあるので、そのままコピペする

取得した埋め込みコード例

1
<iframe width="560" height="315" src="https://www.youtube.com/embed/y4noU6qgJlc" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>