YukiTask - 結城浩のタスク管理ツール(結城タスク)
はじめに
このスクラップには、YukiTaskに関する結城の個人的なメモを書いていこうと思います。
YukiTaskに関してはいろんなアイディアやグッドプラクティスがあるのですが、それに気づくのは仕事まっ最中であることが多く、なかなか腰を落ち着けてまとめることができません。
なのでZennのスクラップを使って、思いついたことを書き残していくのがいいかなと考えています。
のんびり気長に更新していきます。
結城の個人的なメモなので、YukiTaskの基本的な情報については特に解説していません。YukiTaskに関する基本的な情報は(だいぶ古くなっていますが)下記をごらんください。
Contributionのグラフはほとんど見ていない
YukiTaskのアイコンでお化け坊やがContributionのグラフを持っていますが、現在はまったく見てませんね。どのプロジェクトをどれだけやっているかの記録自体は粛々と取っていますが、グラフとして「このプロジェクトは最近サボっている」などとみることはありません。
見るようにしてもいいな。
make help
helpは、そのプロジェクトでのYukiTaskのターゲット一覧を表示するターゲットです。
久しぶりにそのプロジェクトを訪れたとき、ここでできることを忘れていたりします。そんなときにmake helpを実行すると何ができるかのターゲット一覧を表示してくれます。
例
$ make help
make g --- OmniGraffleを開く
up --- snap "360ch5"を行う
make ev --- 進捗状況とgrep TODO
make link --- link.hyuki.net更新へ
make preview --- 自動的にプレビューするためのプログラムを起動します。 -here と書いたところがトップになります。
make pkill --- make previewで起動したプレビューアを終了します
ターゲット
make TARGET のTARGETの部分をターゲットと呼びます。これはmakeの用語です。
YukiTaskでは実際にターゲットを作ることは少なく、phony targetを利用します。
コマンド
YukiTaskのmakefile中で呼びだすプログラムやツールをコマンドと呼びます。
「ターゲット」はmake TARGETのTARGET部分ですが、「コマンド」はそのOS上で動作するプログラムです。
変数
YukTaskのmakefile中で使っている「現在の処理対象」を表すものを「変数」と呼びます。これはmakeの用語です。currentやmainなど。
make fig
figは、そのプロジェクトで作成している画像一覧を表示するターゲットです。
本を書いているときの図版一覧などを表示します。
関連コマンド
-
fig-thumbnail指定したディレクトリ中の画像ファイルをサムネ付きで一覧表示するコマンド。
相互関連をつけるならScrapboxで作った方がいいかもしれない。
make g
g は、本を書くプロジェクトで使っているOmniGraffleを起動するターゲットです。
一文字のターゲットは意外に忘れないものです。忘れてもmake helpで表示するようにしておけば大丈夫。
make show
showは、標準的に使っているターゲットで「最新成果物を表示する」ものです。
showはコマンドでもあります。「標準的に使っているターゲット」はそれ自体をコマンドにしている場合があります。
- 「標準的に使っているターゲット」には名前があった方がいいかもしれませんね。
- また「標準的に使っているけれど、コマンドにしていないターゲット」もあります。たとえば
helpなど。 - そのあたりの使い分けは現在のところかなりアドホックです。
基本的な作業の流れ
YukiTaskでの基本的な作業の流れは、e→mkの繰り返しで成果物を作り、upで成果物を公開/アップロードし、bkでバックアップするというもの。
作業自体の管理として、mでmakefileの編集をし、fでアップロードの設定ファイルを編集します。
補助的な作業として、showやmake viewで成果物や参考資料を表示したり、helpでターゲット一覧をみたりします。
このくらいの抽象度でプロジェクトを管理するのがYukiTaskです。
make ev
evは、現在の進捗状況を評価・表示するためのターゲットです。
たとえばメルマガを書いているときには以下のように進捗が表示されます。
$ make ev
11573 mm523.txt 96% ************************************************..|
11411 mm524.txt 95% ***********************************************...|
9458 mm525.txt 79% ***************************************...........|
10243 mm526.txt 85% ******************************************........|
11104 mm527.txt 93% **********************************************....|
11800 mm528.txt 98% *************************************************.|
10414 mm529.txt 87% *******************************************.......|
10097 mm530.txt 84% ******************************************........|
11717 mm531.txt 98% ************************************************..|
10432 mm532.txt 87% *******************************************.......|
make link
link は結城が使っているURL Shortenerの更新をうながすターゲットです。
たとえばWeb連載を書いているときにmake linkを実行すると、URL Shortenerの設定ファイルをエディタでオープンし、編集すべき当該箇所を検索してくれます。さらに、保存して終了すると設定ファイルをgit commit && git pushすることでURL Shortenerの内容を実際に更新します。
current = 現在の編集対象物
currentは「現在の編集対象物」を表す変数です。
結城メルマガを書いているときには current = mm123.txt のように次に配信する号のためのテキストファイル名を設定しておきます。そしてもちろん、この変数を使って、eというターゲットで編集したり、mkやallで成果物を作ったり、showというターゲットで表示したりするのです。
最近は currentではなくてidを使う場合もあって、プロジェクトごとにばらつきがあります。idを使うのは短いからです。
main = 現在のメインとなる編集対象物
mainは「現在のメインとなる編集対象物」を表す変数です。
currentの違いがわかりにくいので、本を書く場合で説明します。
-
currentは現在書いている章のファイル(たとえばchapter2.tex) -
mainは各章をincludeしているメインのファイル(たとえばmybook.tex)
make tweet
tweetは「そのプロジェクトに関するツイートをする」ためのターゲットです。
典型的な処理は「ツイートのテンプレートをエディタで起動する」や、もっと積極的に「ツイートのテンプレートをpbcopyコマンドでクリップボードに入れる」などです。
たとえば、ニュースレターを発行した後、その告知ツイートを行うときに使います。
pbcopy
pbcopyは、クリップボードにテキストをコピーするMac標準のコマンドです。詳しくはman pbcopyでマニュアルが得られます。
EDITOR = 標準テキストエディタ
EDITORは「標準テキストエディタ」のコマンドを表す変数です。これはUNIXで標準的に使われている変数になりますので、makefile内で明示的に記述する必要はないかもしれません。
たとえば結城は、~/.bash_profile中で以下のように設定しています。
export EDITOR=/opt/homebrew/bin/vim
makefile中では、以下のように使います。eはターゲット、@はコマンドラインのエコーバックを抑止する文字、currentは現在の編集対象となっているファイル名を表す変数です。
e:
@ $(EDITOR) $(current)
make delete-sharing
delete-sharingは「共有の期限切れになったファイルを削除する」というターゲットです。
このターゲットそのものが重要というよりも、ターゲットのネーミングに関する知見がここにあります。
通常はYukiTaskのターゲットは「よく使うもの」を設定します。よく使うので短いターゲット名にすることが多いでしょう。
でもターゲットの中には「頻度は低いけれど、重要で、繰り返し実行される」というものもあります。そのときには意識的に長めの名前、複合的な名前を付けるのがよいでしょう。誤って実行されることを防いだり、それを実行したら何が起こるかわかりやすくなるからです。
here SHORTNAME と here LONGNAME.WITH.DOMAIN
hereコマンドで現在のプロジェクトに移動するショートカット(alias)を登録するときには、いつも使う短い名前(SHORTNAME)と、しばらくたって忘れたときでも使えるドメイン付きの長い名前(LONGNAME.WITH.DOMAIN)の二種類を登録するといいでしょう。
たとえば、結城浩の作業ログについてはSHORTNAMEとしてlogを、LONGNAME.WITH.DOMAINとしてはlog.hyuki.netを登録しています。
ふだんはlogで十分なのですが、何かの拍子に別のプロジェクト名でlogを上書きしたときや、すっかりプロジェクトにくるショートカットを忘れてしまったときのために、log.hyuki.netでもプロジェクトに行けるようにするのです。
soコマンドと_aliasファイル
soコマンドでsource _aliasを実行します。
_aliasにはそのプロジェクト固有のaliasを書いておきます。
いつも編集するファイルがいつも複数あるような場合、eターゲットだけではまかなえない場合があるので、その対処のためです。
全体のaliasに指定するとコンフリクトを起こす危険性があるので、そのプロジェクト固有のaliasとして_aliasファイルに明記しておくのです。
たとえば、いつもstyle.cssとindex.htmlを編集するような場合、次のように_aliasに書いておきます。
alias css=`vi style.css`
alias ind=`vi index.html`
これで、soすると、cssとindがそのプロジェクトで使えるコマンドになります。
_aliasで指定する名前はアドホックに決めて構いませんが、指定する前にtype cssなどとしてaliasやコマンドとコンフリクトしていないかチェックするといいでしょう。
mkするのに複数のケースがある場合
mkするのに複数のケースがある場合の対処法です。
以下のように_aliasファイルに書いておきます。
alias mmk='make all'
alias mmi='make ids'
そしてmakefileには次のように書きます。
mk:
@ iputs 'mmk はmake allを実行します。`
@ iputs 'mmi はmake idsを実行します。'
@ iputs 'ただし、最初に so によって source _alias を実行してください。'
all:
# allの実行内容
ids:
# idsの実行内容
このようにすると、いつもの手癖でmkを実行したときに次のようなガイダンスが表示されます。
$ mk
mmk はmake allを実行します。
mmi はmake idsを実行します。
ただし、最初に so によって source _alias を実行してください。
iputsコマンドとcputsコマンド
iputsコマンドは情報表示用に青色で表示するechoです。
cputsコマンドはエラー表示用に赤色で表示するechoです。
make diff
diffは「ある特定の差分を表示する」ターゲットです。
たとえば、前回のリリースからの差分を表示するときなどに使います。
ls -lD format で特定のファイルのタイムスタンプ表示をフォーマットする
$ ls -lD 'DATE=%Y-%m-%d TIME=%H:%M:%S' filename
..... DATE=2022-06-30 TIME=22:14:35 filename
Rコマンド
RコマンドはREADME.mdを編集するコマンドです。
make new
newは新しい何かを作るためのターゲットです。
たとえばブログ記事で新しい投稿を作るときなどに利用します。
make lint
lintは成果物をチェックするためのターゲットです。
たとえば文法事項のチェック、いわゆるlintツールの起動、あるいは音声合成による読み上げなどに利用します。
make url
urlは関連URLを表示するためのターゲットです。
たとえば成果物が公開されるWebサイトのURLなどです。
Hコマンド
Hコマンドはhistory.txtを編集するコマンドです。
類似のコマンドに、R(README.md)やT(TODO)などがあります。
結城は使っていませんが、人によってはC(Change.log)も便利かもしれません。
id = 現在の編集対象物を示すID
idは「現在の編集対象物を示すID」を表す変数です。
Web連載を書くときに、連載第369回を編集しているときのmakefileの冒頭は次のようになっていました。
...
id = 368# 2022-09-09
id = 369# 2022-09-16
# latest_id
# id = 370# 2022-09-23
current = ../doc/$(id).tex
つまり、連載の回をidで指定しておき、コメントにそれを公開するはずの日付を書いておき、最前線を表すためにmakefile中にlatest_idというコメントを書いておくということです。
さらに、編集ファイル名currentは変数idを用いて構成しています。
make LS
LS はリモートでlsに類することを行うターゲットです。
ローカルとリモートで同じmakefileを使い回しているので、大文字の実行によってリモート実行(ssh)を意味することにしています。
LS:
@ ssh YourHostName '(cd /Your/RemoteWorking/Dir ; ls )'
YoutHostNameは~/.ssh/configで指定するホスト名のつもりです。
make MAKE
make LSと同様です。
MAKE:
@ ssh YourHostName '(cd /Your/Remote/Working?dir ; make )'
make env, make showenv
envは環境変数に関わるターゲットです。
プロジェクトによっては、envとshowenvの二つを使います。
Netlifyなどの静的Webサイトホスティングの環境変数設定セクションをブラウザで表示したり、あるいはローカルな~/.bash_profileに記述されている環境変数をgrepなどで表示したりします。
env:
@ open 'https://app.netlify.com/sites/EXAMPLE-DOT-COM/settings/deploys#environment'
showenv:
@ grep EXAMPLE_ACCESS_TOKEN ~/.bash_profile
make func
funcはFunctionsに関わるターゲットです。
Netlifyは静的Webサイトのホスティングを行いますが、サーバサイドで処理を実行できるFunctionsという機能があります。それに関わる設定画面を表示します。
func:
@ open https://app.netlify.com/sites/EXAMPLE-DOT-COM/functions
make ENV
ENVはリモートホストの環境変数に関わるターゲットです。
単純にsshを利用してcat .envを行う場合もありますし、sshを利用してリモートホストでmake envを利用することもあります。
ENV:
@ ssh REMOTE-HOST '(cd ~/MyProject && cat .env)'
make logseq, make dyna, make graffle
logseq,dyna,graffleはそれぞれLogseq, Dynalist, OmniGraffleを表しているターゲットです。
そのプロジェクトで標準的に使うアプリやファイルをターゲットに結びつけておき、make アプリ名でそのアプリを起動します。
make helpで一覧が表示されるようにしておきます。
アプリによっては特定のスキーマを持っており、そのURLを利用してファイルをすぐに開いた状態にできます。たとえばLogseqの場合にはlogseq://graph/dbname?page=ページ名という形のURLになります。
logseq:
@ open "logseq://graph/dbname?page=xxxxxxxxxxx"
help:
@ echo 'make logseq でLogseqを起動します。'
make mid
mid は画像生成AI midjourney のプロンプト例を表示するターゲットです。
そのプロジェクトでバナー画像やアイキャッチ画像を作るときに使います。
関連コマンドmid-bannerによって記事のタイトルやアイコン画像を付加します。
h
hはmake helpのaliasです。
YukiTaskのコマンドやターゲットが充実してくるとともに、make helpの重要性も高まります。hはシェルのhistoryコマンドのaliasにすることも多いですが、make helpにするのもよいでしょう。
alias h='make help'
c
cはmake configのaliasです。
そのプロジェクトの設定やconfigurationを行うために使います。直接的に、たとえばcをvi config.yamlのように実装してもかまいませんが、プロジェクトごとに「設定」の意味はかわりますので、make configという形で間接的に参照し、実装はそのプロジェクトのmakefileに記述する方が柔軟性は高くなります。
alias c='make config'
.PHONY: config
config:
@ vi config.yaml
make config
configは設定を行うためのターゲットです。vi config.yamlのように実装したり、vi ~/.ssh/configのように実装します。実装するというのはmakefileに記述するという意味です。
make list
listは一覧を得るためのターゲットです。そのプロジェクトでの「一覧」を適切なフォーマットで表示します。特定のファイルのlsを取るのでもいいですし、特定のファイルの内容の一行目だけを表示することもあります。
たとえばLaTeXで原稿を書いているとき、各ファイルが章に対応しているとします。一行目にその章のタイトル\chapterがあると仮定して、make listによってLaTeXファイルを見て章のタイトル一覧を得ることができるでしょう。
llなどにmake listをaliasすればさらに便利になります。
~/.bash_profile
alias ll='make list'
以下の例では、make listを実行すると、そのプロジェクトの bin/list-filesを実行します。bin/list-filesは自分で実装しておきます。
makefile
list:
@ bin/list-files
お知らせ:今週のYukiTask
結城浩のメールマガジンで「今週のYukiTask」というコーナーが始まりました。
Webページで公開している内容がベースになりますが、そこに書かれている情報だけではなく「何を考えてそうしたのか」という部分も合わせてご紹介できたらいいなと思っています。そしてもちろん、私自身もそこを明確に言語化したいと思っています。
make readme (r)
readmeはGitHubのREADME.mdのプレビューを表示するターゲットです。rをaliasにしたらどうかと検討しています。
-
Tは、TODOを編集するalias -
Rは、README.mdを編集するalias -
make readmeは、README.mdのプレビューを表示するコマンド(readmeがターゲット) -
rは、make readmeのalias
make howto
howtoは手順書やマニュアルを表示するターゲットです。GitHubのreadme, GitHub Gist, esa, テキストファイルの表示、Logseqなどに置かれた「そのプロジェクトの手順書」を表示します。
バリエーションとして howto-SOMETHING でSOMETHINGをするための手順書を表示するターゲットもあり得るでしょう。
howto:
@ open 'https://example.com/howto.html'
make usage
usageはそのプロジェクト固有の自作ツールの使い方をまとめて表示するターゲットです。作ったツールを順番に--helpオプションを付けて実行するイメージです。
usage:
@ puts "bin/myTool1"
@ bin/myTool1 --help
@ puts "bin/myTool2"
@ bin/myTool2 --help
関連ターゲット
helpはmakefileそのもののヘルプを表示します。
TODOでコミットログの下書きをする
TODOの末尾には最前線の情報が集まるので、そこでコミットログの下書きをしておきます。TODO末尾をコピーしてしてからupを実行し、git commitで起動されるコミットログ編集画面でペーストするとスムーズに流れます。
make aws-user
aws-userはそのプロジェクトに関係したAWSユーザの管理ページを表示するターゲットです。同様にaws-domainやaws-roleなども使うことができるでしょう。
aws-user:
@ open "https://REGION.console.aws.amazon.com/iam/...”
make ai
'ai' はそのプロジェクトでチャットしているAIサービスのページを表示するターゲットです。前回の続きの会話をするときに使います。
ai:
@ open 'https://chatgpt.com/c/XXXXXXXXXXXXXXXXXXXXX'
show_cover
hereでそのプロジェクトに行ったときにcover.jpgやCover.pngなどの画像があったら、それを表示するようにします。すると「プロジェクトを移動した」ことが直感的に分かりやすくなります。 iTerm2 の「画像表示機能」(OSC 1337)を用いて画像を表示できます。
Rubyコード例(show_cover)
#!/usr/bin/ruby
require 'base64'
require 'optparse'
APPNAME = 'show_cover'
# オプション解析
options = {
width: 300
}
# iTerm2 の OSC 出力
def print_osc
if ENV['TERM']&.start_with?('screen')
print "\033Ptmux;\033\033]"
else
print "\033]"
end
end
def print_st
if ENV['TERM']&.start_with?('screen')
print "\a\033\\"
else
print "\a"
end
end
# メイン画像出力処理
def print_image(filename, base64data, width: nil)
size = Base64.decode64(base64data).bytesize
extras = []
extras << "width=#{width}px" if width
extras << "preserveAspectRatio=1" if width
print_osc
print "1337;File="
print "name=#{Base64.strict_encode64(filename)};" unless filename.empty?
print "size=#{size};inline=1"
extras.each { |e| print ";#{e}" }
print ":"
print base64data
print_st
print "\n"
end
cover = Dir.glob("cover.{jpg,png}", File::FNM_CASEFOLD).find { |f| File.file?(f) }
if !cover
abort "#{APPNAME}: カバー画像 cover.{jpg,png} がありません。"
end
b64 = Base64.strict_encode64(File.binread(cover))
print_image(cover, b64, width: options[:width])

make sand
sandは現在編集対象になっているファイルを sandbox にコピーするターゲットです。編集対象のファイルに対してちょっと実験したり、書き換えたり、別のツールに入れてみたりするときに使います。現在の編集対象は非常に重要ですので、手動でコピーするときに誤って削除したり編集してしまったりするのは困ります。cpとmvを間違えるのも困るし、また編集対象ファイルを間違う恐れもあります。make sand を使えばまちがいなく「何をしてもいい場所」にcpできます。
here PROGRAM-dev
PROGRAMを開発するプロジェクト名にPROGRAM-devというYukiTaskプロジェクト名をつけるのはよい習慣です。 開発したいプログラムの名前とYukiTaskプロジェクト名が重なると「プログラムの実行」と「プログラムの開発場所への移動」がコンフリクトすることがあるからです。
-devを後置するとシェルの補完機能を有効に使うことができます。PROGRAMからPROGRAM-devを補完することができるからです。
AIエージェントにhelpを書いてもらうとよい
問題
makefileにターゲットを追加しているとmake helpとのずれが大きくなってくる。
解決
AIエージェントに「makefileのhelpターゲットを更新して」と伝えるとよい。
そのときに一つ二つhelpを書いた例を置いておくと、それにならって書くのでとてもよい。
make diary
執筆の記録をhistory.txtやChangeLogに書いていくのもいいけれど、commit logに書いたらどうなるだろうという実験。私の場合には一人で使っているのでこういう使い方をしてもいいのではというお気持ち。history.txtやChangeLogだと遡って書き換えやすいので、むしろ「書き換えられない記録」がほしいという気持ち。
diary := _diary.sh
diary:
@ git log | grep diary: | head -10
@ pause "執筆に関して気になることを書いてください。"
@ echo 'git add . && git commit -m "diary: "' > $(diary)
@ $(EDITOR) $(diary)
@ cat $(diary)
@ pause "記録するならEnter"
@ sh $(diary)
@ rm $(diary)
