単発の発表用原稿などを置く。
発表用フォントサイズセット。
(org-timer-set-timer 5)
発表用フォントサイズ。
コードのメモをするとき、 コメント/コード/実行結果を1つにまとめる とわかりやすい。
→ うまくやるための道具があります。
貴島 大悟 資格スクエア プログラマー
外観は もう中学生
(吉本興業のお笑い芸人)に似ているようです。
2つの方法があります。
- gem(ライブラリ)
- 外部ツール
- Rubyには実行結果をコードに出力するgemがある
- Ruby gem rcodetools/rcodetoolsに同梱されている
names = %w[aaa bbb] # => ["aaa", "bbb"]
e = names.to_enum # => #<Enumerator: ["aaa", "bbb"]:each>
e.class # => Enumerator
(Markdownに読み替えても同じことができるはずです)
- クラスが定義するインスタンスメソッドを調べる方法
p Enumerable.instance_methods.sort
- (とくにSQLは実行結果が出ないとコードを把握しにくい感じがします)
TO_CHAR
を使って日付→文字列へ変換する
SELECT customer_name, customer_id, TO_CHAR(birth_day, 'YYYY年MM月DD日')
FROM customer
LIMIT 10
- コードのメモは文脈がなく、後から見て意味不明、ということがよくある
メモ
、実行コード
、実行結果
を同じ場所に書くとわかりやすい- だが普通にやるとめんどくさい
- ツールでかんたんにできる
ご清聴ありがとうございました。
TextLint GitHub - kijimaD/textlint-plugin-org GitHub - textlint/textlint
textlintのプラグインを作成しました。
npmに登録+公式のREADMEにリンクしました。
npm install textlint-plugin-org
orgファイル(Emacs独自のアウトライン形式)で使えるようにしました。 (orgデモ)
TextLintはその名の通り自然言語用のLintです。 単純な間違いや、わかりづらい言い回し、語数制限などを検知してくれます。たくさんルールがあって面白いです。
Markdownは標準、ほかにもHTMLなどは対応してます。
対応してないフォーマットの場合、たとえば見出しで 。
がないとか、コードブロックに対して検知をしてまともに使用できません。
どうしても orgで使いたかったので作成することにしました。
https://azu.github.io/JavaScript-Plugin-Architecture/
中段の動作イメージがとてもわかりやすい。
AST変換というのが重要だということがわかります。
ESLintはコードをパースしてASTにして、そのASTをJavaScriptで書いたルールを使いチェックするという大まかな仕組みは分かりました。
textlint-plugin-org/test/OrgProcessor-test.ts テストから実際にASTオブジェクトの中身を見てみます。
it('heading should Header', () => {
const result = parse(`
** Heading
`);
const section = result.children[0];
const header = section.children[0];
assert.equal(header.type, Syntax.headline);
});
console.log(section)
↓
{
type: 'UNKNOWN',
level: 2,
properties: {},
children: [
{
type: 'Header',
actionable: false,
content: 'Heading',
children: [Array],
level: 2,
loc: [Object],
range: [Array],
raw: '** Heading\n'
},
type: 'UNKNOWN'
],
loc: { start: { line: 2, column: 0 }, end: { line: 3, column: 0 } },
range: [ 1, 12 ],
raw: '** Heading\n'
}
console.log(header)
↓
{
type: 'Header',
actionable: false,
content: 'Heading',
children: [
{
type: 'UNKNOWN',
level: 2,
loc: [Object],
range: [Array],
raw: '**'
},
{
type: 'Str',
value: 'Heading',
loc: [Object],
range: [Array],
raw: 'Heading'
},
{ type: 'UNKNOWN', loc: [Object], range: [Array], raw: '\n' },
type: 'UNKNOWN'
],
level: 2,
loc: { start: { line: 2, column: 0 }, end: { line: 3, column: 0 } },
range: [ 1, 12 ],
raw: '** Heading\n'
}
Lintは、このASTオブジェクトのTypeに基づいてそれぞれのルールを適用してます。 なので見出しの星は対象外にできます。
- ファイル形式の文字列 → (ここが必要) → AST → Lint
やる必要があるのは、オブジェクトの形式を揃えることです。 typeの名前がtextlintに対応したシンボルへマッピングします。
変換器はすでにあります。
なので、本質的に必要なことはこのマッピングです(ほかにも位置や範囲を付加する必要がありますが、HTMLとかとほぼ同じ)。
export const nodeTypes = {
document: ASTNodeTypes.Document,
paragraph: ASTNodeTypes.Paragraph,
list: ASTNodeTypes.List,
'list.item': ASTNodeTypes.ListItem,
headline: ASTNodeTypes.Header,
block: ASTNodeTypes.CodeBlock,
hr: ASTNodeTypes.HorizontalRule,
// inline block
'text.plain': ASTNodeTypes.Str,
'text.code': ASTNodeTypes.Code,
'text.bold': ASTNodeTypes.Emphasis,
link: ASTNodeTypes.Link,
footnote: 'FootnoteReference',
};
orgajsがどんな名前で出力するかは実行しないとわからなかったので、ちゃんとすべてテストを書いて調べました。上流の不慮の変更も検知できます。
ということで使えるようになりました🎉。
便利です。
Emacsエコシステムを少し広げることができました。
digger
GitHub - kijimaD/digger CLIのゲームを作っています(WIP)。
(デモ)
まだ移動しかできない。
- 画像表示はあきらめる or 見下ろし
- ターン制にする。リアルタイムではなく。
- テストを書く(テストが書ける構造にする)
時代に逆行した開発ですが、よいところもあります。
- 真のRubyだけに集中できる(ライブラリすら必要ではない。CLI用のCursesくらい)
- オブジェクト指向をやらなければならない状況。ゲームそのものがゲームオブジェクトの相互作用なので、オブジェクト指向でないと条件ありすぎて死ぬ。フツーに命令的に書けるプログラムが二者間だとしたら、ゲームは三者間。
- 例
- 壁に当たるのは自キャラだけでない。敵キャラや銃弾も当たる。各オブジェクトに判断してもらわないといけない。
- 例
- 弾がヒットしたら、誰のスコアになるのか => その銃弾オブジェクトを生成したキャラクターオブジェクト。みたいな。
- 例
- 毎ターンフィールドにあるすべてのオブジェクトを更新+新描画したい => すべて入れ物オブジェクトに入れておいて、mapですべてを一括処理しよう、とか。
1ヶ月くらい頑張ってみます(宣言)。
ローグライクになる予定です。↓みたいなゲーム。超好きなジャンルです。
- Cataclysm-DDA
- ゾンビサバイバル 参考
- Dwarf Fortress
- サバイバル/シミュレーション 参考
- Elona
- RPG風 参考
これらは商業的な作品ではなく、貧弱なグラフィックですが、超濃密なゲーム世界を作り上げています。 個人がめざす(めざせる)のはこういう方向性だと考えてます。
仕事につく前、何度か作りはじめては挫折してきました。
直近だと去年開発してましたが、開発が進まなくなってやめました↓。
- GitHub - kijimaD/ban-ban-don
- rubyのゲームライブラリGosuを使った、シューティングゲーム。
- (本に載ってたコードをベースに開発しました。根本部分のコード構造はほとんどオリジナル性ないです)
これの問題点、挫折した理由…。
- 要件を高望みしすぎた。
- 疑似3Dにした。座標に、ひし形の画像を敷き詰めると疑似3Dができます…画面確認が大変だった。特に重なりとか、接触判定が…。
- アニメーションする画像の用意が大変すぎた。方向分の画像を作る必要がある。
- リアルタイムなので再現しにくい。
- パフォーマンスを考えないとまともに動かなくなる。黒魔術がある(四分木とか)。
- つらい目視確認開発。
- 新機能を作るときも、いちいち起動して該当箇所までいって開発していた。
- テストがない、lintがない(まだ知らなかった)
- いつのまにかどこかが壊れて動かなくなること多数
=> ムリ \(^o^)/
https://github.com/kijimaD/create-link
CreateLink
というChrome拡張があります。
それのEmacs版を作成しました。 公式パッケージ集での審査中(まだ返信来ない)。
現在のページの名前のついたリンクを取得する拡張です。GitHubとかSlackに貼り付けるとき、便利なやつです。
- CreateLinkのリンク(Chromeウェブストア)
https://chrome.google.com/webstore/detail/create-link/gcmghdmnkfdbncmnmlkkglmnnhagajbm?hl=ja
- 例: Markdownリンクだと、
https://www.google.com ->[Google](https://www.google.com/) みたいな。
(ブラウザのデモ)
- Emacs上の各種ブラウザeww, w3m
- 各種フォーマットHTML(default), LaTeX, Markdown, MediaWiki, Org-mode
- ブラウザ以外のときはローカルファイルのパスを取得する
に対応してます。
(実行・オプション操作のデモ)
ライセンスの部分を除くと、90行くらいしかありません。
半分くらいはユーザ設定のための決まりきった記述のため、実際は40行ほど。
;;; Code:
(require 'eww)
(require 'w3m)
(defgroup create-link nil
"Generate a formatted current page link."
:group 'convenience
:prefix "create-link-")
(defcustom create-link-default-format 'html
"Default link format."
:group 'create-link
:type '(choice (const :tag "html" html)
(const :tag "markdown" markdown)
(other :tag "org" org)
(other :tag "media-wiki" media-wiki)
(other :tag "latex" latex)))
;; 🌟オプション設定
;; Format keywords:
;; %url% - http://www.google.com/
;; %title% - Google
(defcustom create-link-format-html "<a href='%url%'>%title%</a>"
"HTML link format."
:group 'create-link
:type 'string)
(defcustom create-link-format-markdown "[%title%](%url%)"
"Markdown link format."
:group 'create-link
:type 'string)
(defcustom create-link-format-org "[[%url%][%title%]]"
"Org-mode link format."
:group 'create-link
:type 'string)
(defcustom create-link-format-media-wiki "[%url% %title%]"
"Media Wiki link format."
:group 'create-link
:type 'string)
(defcustom create-link-format-latex "\\href{%url%}{%title%}"
"Latex link format."
:group 'create-link
:type 'string)
(defun create-link-raw-format ()
"Choose a format type by the custom variable."
(pcase create-link-default-format
(`html
create-link-format-html)
(`markdown
create-link-format-markdown)
(`org
create-link-format-org)
(`media-wiki
create-link-format-media-wiki)
(`latex
create-link-format-latex)))
(defun create-link-replace-dictionary ()
"Convert format keyword to corresponding one."
`(("%url%" . ,(cdr (assoc 'url (create-link-get-information))))
("%title%" . ,(cdr (assoc 'title (create-link-get-information))))))
(defun create-link-make-format ()
"Fill format keywords."
(seq-reduce
(lambda (string regexp-replacement-pair)
(replace-regexp-in-string
(car regexp-replacement-pair)
(cdr regexp-replacement-pair)
string))
(create-link-replace-dictionary)
(create-link-raw-format))) ;; <a href='%url%'>%title%</a> とか。ループのinitial value。
;; <a href='%url%'>%title%</a>
;; <a href='https://...'>%title%</a> 前の値を保持
;; <a href='https://...'>Google</a> さらに置換
#+begin_comment
;; ここを綺麗に書くのが一番むずかしかった。...複数の文字列置換
;; 一つの置換(replace-regexp-in-string)は関数があるが、複数指定はできない。
;; (seq-reduce)の第一引数はコードブロックに相当するところ。ループ一回で何をするか。
;; stringはraw-format(<a href='%url%'>%title%</a>など)を受け取る。
;; regexp-replacement-pairはreplace-dictionaryのイテレーション分が入る。ブロック引数。
#+end_comment
;; 🌟ブラウザやその他をラップしてtitle, urlを返す!
(defun create-link-get-information ()
"Get keyword information on your browser."
(cond ((string-match-p "eww" (buffer-name))
`((title . ,(plist-get eww-data :title))
(url . ,(plist-get eww-data :url))))
((string-match-p "w3m" (buffer-name))
`((title . ,w3m-current-title)
(url . ,w3m-current-url)))
;; otherwise, create-link to the file-buffer
(t
`((title . ,(buffer-name))
(url . ,(buffer-file-name))))))
;; 🌟エントリーポイント
;;;###autoload
(defun create-link ()
"Create formatted link."
(interactive)
(message "Copied! %s" (create-link-make-format))
(kill-new (create-link-make-format)))
(provide 'create-link)
;;; create-link.el ends here
大きなパッケージに比べてこれはゴミみたいなもんだな、と思ってました。
でもコードやアイデアの参考にするため使っているパッケージのコードを眺めていて、こういう短いものでも自分が日々使ってたり、多くの人に使われているパッケージはけっこうあることに気づきました。
たとえば。
add-node-modules-path.el
- node環境の読み込み 86行
- リストをいい感じに表示する 109行
- オンライン辞書 132行
- rubocopをいい感じに 267行
- 重要なのは1つのことをうまくやること。
使ってくれた+PRが来ました。 褒めてくれてテンション上がる。 kijimaD/create-link#7
I like this package, is simple and useful.
審査にむけてやったこと。
- わかりやすいコンセプト。
- 空気を読んだ動作をする、限られたインタフェース(create-link)という関数1つで、複数フォーマット・ブラウザに対応できる。
- ちゃんとドキュメントを用意したkijimaD/create-link
- オプションを用意した。フォーマットの種類やブラウザを増やすのは、とても簡単です。
フォーマットリンクを取得するだけのシンプルなコードではありますが、拡張はいろいろ考えられます。
やらない。 helmから選べたらベスト。選択をどうやってやればいいのかよくわからない org-roamのファイル選択で出てくるhelmなど参考になりそう。 elisp-checkはcask環境のためうまくできない。 なので、elisp-check.elを直に読み込んで実行するようにすればよさそう。elisp-lintというパッケージに同梱されてたのでそれで一気にできるようになった。
フックでは式が使えるのでなんでもできる。動的にタイムスタンプを加えたり、連番を振ったりとか。単なる文字列フィルターよりはるかに強力。誰かがもっと便利な使い方を編み出してくれる。make-formatと、message+killの前にフックを差し込むか。 でも、文字列を受け取れないからあまり意味ない気がしてきた。 フックはその処理に追加するというより、別の処理を差し込むためのものだ(ある関数を実行すると、別の全く関係ない)モードをオンにするとか。その意味でいうと、フックする処理はまったく思いつかない。
別のフォーマットに変換するのもあっていいな。 すでに書式があるから、そこからURL, Titleを取り出せればいい。- 判定関数
thing-at-pointの拡張だな。フォーマットリンク上にカーソルがある場合、タイトルとURLを取得して変換…。 どのフォーマットか判定できれば、タイトルとURLを取れる。 markdown-mode.elの(markdown-kill-thing-at-point)が参考になりそう。
別に独自実装しなくても、各modeのregexpを使えばいいかな。いや、フル装備でめちゃくちゃ複雑だし、いろんな依存(5つも増えるのはさすがに…)があるので独自でやろう。 https://ayatakesi.github.io/emacs/25.1/Regexps.html
たとえばlatexの場合、ファイルリンクにはプレフィクスrun:がつくらしい。 今のコードだとファイルリンクだという検知はget-informationでしかできないのでそこに書くしかない。 一般的関数に特定のファイルフォーマットの処理が挟まれると非常に醜い。 なので、最終的な個別変換を分離する。そうするとhtmlがついてないときはrunをつけるとか、好きに追加できるだろう。git-link
の整形バージョン。
そこまではちょっとやりすぎ感。依存が増えすぎるのも微妙な感じか。でも欲しいよな…。
各PRまではいいけど、少なくともリポジトリのホームページくらいならいいかな。
ブラウザみたく、変数が用意されてはない模様。まあこれについてはあまりいらないか。 パスを取得したいときはあるけど、それをhtmlリンクにしたいってあまりないしな。
パスはdefault-directoryで取れる。
つまりパスだけ。 主題とはずれる気がする。シェルとかだとタイトルの取りようがないのでこれを追加するのが必要。
リポジトリからリンクを辿れるようになる。でもEmacs上でどうなんだろう。 辿れないけど、人にディレクトリを示すときには使える。今は絶対パスで取って前のを削除している。めんど い。 うむむ。リモートリポジトリのURLがわかるなら意味はありそう。git-linkとあまり変わらないけどな。 git-linkのコードを見てるけど、まだあまりよくわからない。
今は /home/kijima...
で出てるからな。汎用性があまりよくない。あとで絶対変わるし、ほかで使えない。
たとえばivyのinfoページにいたとする。(info “ivy”) を出力する。 これを実行するとivyに飛べるので、リンクといえそう。環境も関係ない。
infoバッファからの検索キーワードの割り出し方… 実行ディレクトリをdefault-directoryか何かで取る。(.*).infoというファイルがあるはずなのでそのファイル名をinfoの引数に渡す。
- 移植技を覚えました。要件が明確+元ソースを読むことができると楽。プログラムに集中できて美味しい。
- ちょっとした不便さは少ないコードで解決できる。
- ごく単純なコンセプトでも、拡張の方向性は意外と多いです。
おわり。