LoginSignup
13
13

More than 5 years have passed since last update.

Package 作成時の便利フレーズ、知識など

Last updated at Posted at 2015-07-17

Atom の Package 開発でよく使うフレーズ、知識等を気まぐれに追記していきます。

自分の理解整理の為の dump が目的です。
API の使い方は、本体のコード や、ユーザー atom の Package を読むのが一番よい。

ちなみに、ここにまとめる為に整理、変更して書いてるので、自分の Package 内で使っているものとは若干違います。
整理変更後、全部の動作確認はしていないので、何かあればコメントで指摘して下さい。

便利キーマップ

基本的に、cmd-t や、cmd-r で表示されるミニエディタの絞込時に、; セミコロンを入力する事は無いので、これを決定(core:confirm)として使っている。
また、ctrl-u で行頭まで文字列を一気に消せるようにもしている。

keymap.cson
'.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()
13
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
13