Atom の Package 開発でよく使うフレーズ、知識等を気まぐれに追記していきます。
自分の理解整理の為の dump が目的です。
API の使い方は、本体のコード や、ユーザー atom の Package を読むのが一番よい。
ちなみに、ここにまとめる為に整理、変更して書いてるので、自分の Package 内で使っているものとは若干違います。
整理変更後、全部の動作確認はしていないので、何かあればコメントで指摘して下さい。
便利キーマップ
基本的に、cmd-t や、cmd-r で表示されるミニエディタの絞込時に、;
セミコロンを入力する事は無いので、これを決定(core:confirm
)として使っている。
また、ctrl-u で行頭まで文字列を一気に消せるようにもしている。
'.select-list':
';': 'core:confirm'
'ctrl-u': 'editor:delete-to-beginning-of-line'
Atom 自体の Hack
ATOM_DEV_RESOURCE_PATH 環境変数
atom コマンドのヘルプを見れば書いてあるが、ATOM_DEV_RESOURCE_PATH
という環境変数がある。
ここに指定したPATHは、dev モードで起動した時、source をロードする PATH として使われる。
つまり、直接 coffee の source を変更して、dev モードで起動するだけで、動作を直ぐに確認出来る。
デフォルトでは、~/github/atom
が使われるので、~/github
直下に atom を clone しておけば、
$ atom -d
で起動するだけで良い。
$ atom --help
Atom Editor v1.0.3-9774b20
Usage: atom [options] [path ...]
One or more paths to files or folders may be specified. If there is an
existing Atom window that contains all of the given folders, the paths
will be opened in that window. Otherwise, they will be opened in a new
window.
Environment Variables:
ATOM_DEV_RESOURCE_PATH The path from which Atom loads source code in dev mode.
Defaults to `~/github/atom`.
ATOM_HOME The root path for all configuration files and folders.
Defaults to `~/.atom`.
<以下省略>
TextEditor 内で使われている単語リストを取得する
lazy-motion 内で似たようなことをやっている。
二回目の get 以降は、キャッシュを返すので、取得しなおしたければ、destroy() 後、get すればいける(はず)。
# 指定したパターンにマッチするテキストのリストを返す
getTokenProvider: (editor, pattern) ->
matches = null
get: ->
return matches if matches
matches = []
editor.scan pattern, ({matchText}) =>
matches.push matchText
matches
destroy: ->
matches = null
Usage
editor = atom.workspace.getActiveTextEditor()
@tokenProvider ?= @getTokenProvider(editor, /\w+/g)
console.log @tokenProvider.get()
@tokenProvider.destroy()
@tokenProvider = null
Markdown 内のソースコード部分の Grammar スコープ名を得る。
例えば、Markdown 内の、CoffeeScript のコード部分にカーソルがある時、source.coffee
のようなスコープ名を取得したい。
単に以下の様にしたのでは取得できない。
scopeName = atom.workspace.getActiveTextEditor().getGrammar().scopeName
scopeName # => 'source.gfm'
方法
# カーソル位置の ScopeDescriptor を得る
getCursorScope: ->
editor = atom.workspace.getActiveTextEditor()
[rowStart, rowEnd] = editor.getLastSelection().getBufferRowRange()
editor.scopeDescriptorForBufferPosition([rowStart, 0])
# 渡された ScopeDescriptor から最もカーソル位置に近い、Grammar Scope を得る。
# scopesArray は、`comment.line.number-signe.coffee` のような scope も含まれるので
# grammarScopename に絞って探す。
getGrammarScopeNameForScope: (scope)->
scopeNames = scope.getScopesArray().slice().reverse()
for scopeName in scopeNames when scopeName in @getGrammarScopeNames()
return scopeName
null
# 利用できる Grammarの ScopeName のリストを得る。
getGrammarScopeNames: ->
atom.grammars.getGrammars().map (grammar) ->
grammar.scopeName
Usage
scopeName = @getGrammarScopeNameForScope @getCursorScope()
画面をフラッシュする
注意を促したいときに。Screen Beep 的なもん。
ScreenRow の範囲でフラッシュしてるので、Fold があっても大丈夫。
- coffee
flashScreen: (editor, duration=150) ->
[startRow, endRow] = editor.getVisibleRowRange().map (row) ->
editor.bufferRowForScreenRow row
range = [[startRow, 0], [endRow, Infinity]]
marker = editor.markBufferRange range,
invalidate: 'never'
persistent: false
flashingDecoration = editor.decorateMarker marker,
type: 'highlight'
class: 'sample-flash'
setTimeout =>
flashingDecoration.getMarker().destroy()
, duration
- less
@import "syntax-variables";
atom-text-editor::shadow {
.sample-flash .region {
background-color: @syntax-selection-flash-color;
}
}
- Usage
@flashScreen atom.workspace.getActiveTextEditor(), 200
ヒストリ管理
ヒストリ管理をしたいことは良くある。
簡単版.
_ = require 'underscore-plus'
getHistoryManager: (maxSize) ->
entries = []
index = -1
get: (direction) ->
if direction is 'prev'
index = (index + 1) % entries.length
else if direction is 'next'
index -= 1
index = (entries.length - 1) if index < 0
entries[index]
save: (entry) ->
return if _.isEmpty(entry)
entries.unshift entry
entries = _.uniq entries # Eliminate duplicates
if entries.length > maxSize
entries.splice maxSize
reset: ->
index = -1
destroy: ->
entries = null
index = null
Usage
historySize = 10
@historyManager = @getHistoryManager historySize
# 保存
@historyManager.save 'foo'
# 取り出し
if entry = @historyManager.get 'prev'
console.log entry
# 不要になったら開放
@historyManager.destroy()
画面に見えている、TextEditor を得る。
path はオプションで、 同じPATHの TextEditor のみを取得したい場合に指定する。
getVisibleEditors: ({path}={}) ->
editors = atom.workspace.getPanes()
.map (pane) -> pane.getActiveEditor()
.filter (editor) -> editor?
if path
editors = editors.filter (editor) ->
editor.getPath() is path
editors
Usage
# case-1
editors = @getVisibleEditors()
# case-2
editor = atom.workspace.getActiveTextEditor()
editors = @getVisibleEditors path: editor.getPath()
TextEditor の状態を保存して復旧する
エディタの状態を復旧する関数を返す関数。
Emacs には save-excursion という関数(スペシャル・フォーム)があって、いろいろやった後にエディタの見た目の状態を一発で元に戻すことができて便利だった。
それには全く及ばないが、screenTop と、fold を元の状態に戻せる。
スクロールしたり、fold を開いたりしても、元に戻せるという事。
# Return function to restore editor state.
saveEditorState: (editor) ->
scrollTop = editor.getScrollTop()
foldStartRows = editor.displayBuffer.findFoldMarkers().map (m) =>
editor.displayBuffer.foldForMarker(m).getStartRow()
->
for row in foldStartRows.reverse() when not editor.isFoldedAtBufferRow(row)
editor.foldBufferRow row
editor.setScrollTop scrollTop
Usage
editor = atom.workspace.getActiveTextEditor()
@restoreEditorState = @saveEditorState editor
# <このあと, scroll や unfold が必要な処理>
@restoreEditorState()