コーディングしてる時「こういうのあったら書きやすいな」的な Extension まとめ（主に俺得）

ここ2ヶ月なかなか忙しくて振り返りができなかったが、そろそろ一旦今までの進捗とかをまとめておかないと次のステップに進まないじゃないかと思って、とりあえずよく使ってるやつをフレームワーク化して[Github に上げました](https://github.com/el-hoshino/Eltaso)。というわけで簡単に解説します

# 演算子系
## サイズやポイントを等倍で拡大縮小する

```swift:CustomOperators.swift
public func * (lhs: CGSize, rhs: CGFloat) -> CGSize {
	return CGSize(width: lhs.width * rhs, height: lhs.height * rhs)
}

public func * (lhs: CGPoint, rhs: CGFloat) -> CGPoint {
	return CGPoint(x: lhs.x * rhs, y: lhs.y * rhs)
}

public func *= (inout lhs: CGSize, rhs: CGFloat) {
	lhs = lhs * rhs
}

public func *= (inout lhs: CGPoint, rhs: CGFloat) {
	lhs = lhs * rhs
}
```


まあいうほど解説するポイントないんじゃないかな。割と `UIView` とかのリサイズとかがよくやりますが、横縦を同じスケールで拡大縮小するときによく使っています。

## 数字や範囲が決められた範囲内にあるかどうかを調べる

```swift:CustomOperators.swift
infix operator …= {
	associativity none
	precedence 130
}

public func …= <T where T: Comparable> (lhs: Range<T>, rhs: Range<T>) -> Bool {
	if lhs.startIndex >= rhs.startIndex && lhs.endIndex <= rhs.endIndex {
		return true
	} else {
		return false
	}
}

public func …= <T where T: Comparable> (lhs: HalfOpenInterval<T>, rhs: HalfOpenInterval<T>) -> Bool {
	if lhs.start >= rhs.start && lhs.end <= rhs.end {
		return true
	} else {
		return false
	}
}

public func …= <T where T: Comparable> (lhs: ClosedInterval<T>, rhs: ClosedInterval<T>) -> Bool {
	if lhs.start >= rhs.start && lhs.end <= rhs.end {
		return true
	} else {
		return false
	}
}

public func …= <T where T: Comparable> (lhs: T, rhs: Range<T>) -> Bool {
	if lhs >= rhs.startIndex && lhs < rhs.endIndex {
		return true
	} else {
		return false
	}
}

public func …= <T where T: Comparable> (lhs: T, rhs: HalfOpenInterval<T>) -> Bool {
	if lhs >= rhs.start && lhs < rhs.end {
		return true
	} else {
		return false
	}
}

public func …= <T where T: Comparable> (lhs: T, rhs: ClosedInterval<T>) -> Bool {
	if lhs >= rhs.start && lhs <= rhs.end {
		return true
	} else {
		return false
	}
}
```

まあ[以前の記事にも書いた通り](http://qiita.com/lovee/items/32ceca1effbeceb959d6)、`~=` 演算のオペランド順番がなんか気にくわないからこれ作った。

# `RandomAccessIndexType`

```swift:RandomAccessIndexType.swift
public extension RandomAccessIndexType {
	
	var increased: Self {
		return self.advancedBy(1)
	}
	
	var decreased: Self {
		return self.advancedBy(-1)
	}
	
	mutating func increase(by n: Self.Distance = 1) {
		self = self.advancedBy(n)
	}
	
	mutating func decrease(by n: Self.Distance = 1) {
		self = self.advancedBy(-n)
	}
	
}
```

こっちも割というほど解説するポイントないかな。まあぶっちゃけ普通に `a + 1` とか書いても全然大丈夫ですがこっちの方が補完が効くのと、コード読むとき目的がわかりやすいから好きです。特に `0 ..< n` などのように範囲を作るとき、最後の `n` は実際の範囲に含まれないから `n.decreased` は結構よく使います。あと一応まだ Swift の現行バージョンは 2.X だけど先に 3.X の命名規則に沿って by をラベルに入れちゃいました。あとで直すの大変そうだから（）

# `SequenceType`
## Optional じゃない要素を抽出する

```swift:SequenceType.swift
public protocol OptionalType {
	associatedtype T
	var optionalValue: T? { get }
}

extension Optional: OptionalType {
	public var optionalValue: Wrapped? { return self }
}

public extension SequenceType where Generator.Element: OptionalType {
	
	var flatten: [Generator.Element.T] {
		return self.flatMap { $0.optionalValue }
	}
	
}
```

これは例えば `[Int?]` を [Int] に直すやつです。普通なら `let flatMapped = array.flatMap { $0 }` みたいな書き方が必要ですが補完効かないのが嫌だったからこういうの作りました。使う時は `let flatMapped = array.flatten` で一発でできます。

でも実は本当は例えば `subviews` の中の `UIImageView` とかを抽出できるものが作りたいのですが…いろいろ書いてみたけど結局うまくいかなくて誰か教えていただけると助かります。要するに `let imageViews = view.subviews.flatMap { $0 as? UIImageView }` とかを一発で作れるメソッドが欲しいです。（もちろんこの場合 `UIImageView` は引数として使いたい）

# `Int`
## 決まった範囲内での乱数を作る

```swift:Int.swift
public extension Int {
	
	static func createRandom(range range: Range<Int>) -> Int {
		let rangeLength = range.endIndex - range.startIndex
		let random = arc4random_uniform(UInt32(rangeLength))
		return Int(random) + range.startIndex
	}
	
}
```

[以前の記事にも書いた通り](http://qiita.com/lovee/items/942de12e9edb5ad01f48)、例えば -10 から 10 までの乱数を作りたいときは `Int.createRandom(range: -10 ... 10)` で書けば一発で作れます。便利。

# `Double`
## ラジアン値に変換する

```swift:Double.swift
public extension Double {
	
	public var radianValue: Double {
		return self / 180 * M_PI
	}
	
}
```

特に回転とかによく使われるラジアン値ですが、普段生活してる中度数の方が馴染みがあるので、例えば 30° の回転をしたいと思ってもその 30° に対応するラジアン値がすぐ頭に出てこないので、いちいち変換の計算式を書くのもだるいですしわかりづらいですから、これを使えば `view.transform = CGAffineTransformMakeRotation(30.0.radianValue)` のように一発で書けます。（ただあくまでここは `Double` で作っているので、`30.radianValue` で書くと `30` というリテラルは `Int` になるから `Double` のメソッドは使えなくてエラーになる）

# `Bool`
## 自分自身を反転する

```swift:Bool.swift
public extension Bool {
	
	mutating public func reverse() {
		self = !self
	}
	
}
```

まあ普通に `value = !value` で書いてもいうほど不便はないがやはり補完が(ry

# `String`
## 文字列から何文字目からの文字列を取得する

```swift:String.swift
public extension String {
	
	public func droppingFirst(n: Int = 1) -> String {
		
		let remainingIndex = self.startIndex.advancedBy(n, limit: self.endIndex)
		return self.substringFromIndex(remainingIndex)
		
	}
	
	public func droppingLast(n: Int = 1) -> String {
		
		let remainingIndex = self.endIndex.advancedBy(-n, limit: self.startIndex)
		return self.substringToIndex(remainingIndex)
		
	}
	
}
```

Swift の文字列の何文字目というのは `Int` 型ではなく `Index` 型なのでいつも使うのにひと手間かかるから、それが面倒なのでこんなの作りました。どうせなら `Array` の要素も `Index` 型でやればいいのにと思ったり思わなかったり。

# `Array`
## 要素範囲を取得する

```swift:Array.swift
public extension Array {
	
	public var indexRange: Range<Int> {
		return self.startIndex ..< self.endIndex
	}
	
}
```


主に `for` ループで使ってますが、他にも例えば何番目の要素を取得したいというときに、その「何番目」がちゃんと配列の範囲内にあるかどうかを `…=` と併用して調べるときに使います。

## 要素を一個追加した配列を取得する

```swift:Array.swift
public extension Array {
	
	public func appending(element: Element) -> Array<Element> {
		return self + [element]
	}
	
	public func appending(elements: [Element]) -> Array<Element> {
		return self + elements
	}
	
}
```

まあこれも要するに補完(ry

# `Dictionary`
## Tuple から `Dictionary` を作る

```swift:Dictionary.swift
public extension Dictionary {
	
	public init<S: SequenceType where S.Generator.Element == Element> (tuples seq: S) {
		self.init()
		for (k,v) in seq {
			self[k] = v
		}
	}
	
}
```

まあなぜこれを作ったのかというと、仮に `Dictionary` を `map` しても `Array` しか作れないから、例えば `Key` をそのままにして `Value` だけ2倍にしたい、とかいうときに一回 `map` で `(Key, Value)` の `Tuple` を作ってから `Dictionary` にする、といった感じしています。ちなみにこの書き方は確か [koher](http://qiita.com/koher) さんに教えてもらったはずですが、どの記事で教えてもらったのかは覚えてない…

## 特定の `Key` をなくした辞書が欲しい時

```swift:Dictionary.swift
public extension Dictionary {
	
	public func dropping(key: Key) -> Dictionary<Key, Value> {
		var dictionary = self
		dictionary.removeValueForKey(key)
		return dictionary
	}
	
}
```

なんかもっといい書き方ないのかなこれ… `var` 使いたくないでござる…

# `CGSize`
## 正方形サイズを作る

```swift:CGSize.swift
public extension CGSize {
	
	public init(length: CGFloat) {
		self.init(width: length, height: length)
	}
	
}
```

ご存知の通り正方形って横縦は同じ長さだから、引数一個で作りたい時もあるじゃない？と思ってこれ作った。

## 長いほう／短いほうの辺長を知りたい時

```swift:CGSize.swift
public extension CGSize {
	
	var maxLength: CGFloat {
		return max(self.width, self.height)
	}
	
	var minLength: CGFloat {
		return min(self.width, self.height)
	}
	
}
```

レイアウトを組む時に割と良く使ってるような気が…

# `CGRect`
## 上下左右の値が知りたい時

```swift:CGRect.swift
public extension CGRect {
	
	public var top: CGFloat {
		get {
			return self.origin.y
		}
		set {
			self.origin.y = newValue
		}
	}
	
	public var bottom: CGFloat {
		get {
			return self.origin.y + self.height
		}
		set {
			self.size.height = newValue - self.origin.y
		}
	}
	
	public var left: CGFloat {
		get {
			return self.origin.x
		}
		set {
			self.origin.x = newValue
		}
	}
	
	public var right: CGFloat {
		get {
			return self.origin.x + self.width
		}
		set {
			self.size.width = newValue - self.origin.x
		}
	}
	
}
```

これも良くレイアウトを組む時に使ってるような気がします。要するに `frame.origin.x` と `frame.size.width` がそれぞれ取得できても、一番右がどこにあるのかは一発でわかることができず、これらを一回足し算しないといけない、という微妙に面倒に思ってる心あらこんなの作った。そしてついでにこれらを設定する時に直接 `rect` 自体を設定できるようにセッターも組んでおいた。

# `UIColor`
## RGBA の十六進数から色を作る

```swift:UIColor.swift
public extension UIColor {
	
	public convenience init(hexRGBAValue: UInt) {
		let hexRed = (hexRGBAValue & 0xFF000000) >> 24
		let hexGreen = (hexRGBAValue & 0x00FF0000) >> 16
		let hexBlue = (hexRGBAValue & 0x0000FF00) >> 8
		let hexAlpha = (hexRGBAValue & 0x000000FF) >> 0
		
		let red = CGFloat(hexRed) / CGFloat(UInt8.max)
		let green = CGFloat(hexGreen) / CGFloat(UInt8.max)
		let blue = CGFloat(hexBlue) / CGFloat(UInt8.max)
		let alpha = CGFloat(hexAlpha) / CGFloat(UInt8.max)
		
		self.init(red: red, green: green, blue: blue, alpha: alpha)
	}
	
}
```

まあよくありますよね、特にデザイナーさんから多分よく十六進数で色指定をもらうことがあるんじゃないかと思います。ちなみにこれは `0xFFFFFFFF` の書き方にちなんで `UInt` で取得していますが、他にも[例えば CSS などでよく使う `#FFFFFF` の文字列とかから色を取得できる拡張](https://github.com/yeahdongcn/UIColor-Hex-Swift)もあります

# `UIImage`
## 画像から特定範囲内の内容を新たな画像として取得する

```swift:UIImage.swift
public extension UIImage {
	
	public func getCroppedImage(inRect rect: CGRect) -> UIImage {
		
		UIGraphicsBeginImageContextWithOptions(rect.size, false, self.scale)
		
		let drawPoint = rect.origin * -1
		self.drawAtPoint(drawPoint)
		let croppedImage = UIGraphicsGetImageFromCurrentImageContext()
		
		UIGraphicsEndImageContext()
		
		return croppedImage
		
	}
	
}
```

これも割とデザイナーさんから例えばボタン画像を一個ずつもらうんじゃなくて、複数の画像を一枚の絵にまとめて渡されることが多いのではないかと思いますが、そういった時手作業でいちいち画像を作るのが面倒でそのまま渡された素材を使いたい時に結構使ってます。

# `UIView`
## ビューの中心ポイントを取得したい時

```swift:UIView.swift
public extension UIView {
	
	public var midPoint: CGPoint {
		return CGPoint(x: self.bounds.midX, y: self.bounds.midY)
	}
	
```

これもレイアウト組む時、よくセンタリングにしたい時は `subview.center = CGPoint(parentview.bounds.midX, parentview.bounds.midY)` のように書いたりしていますがやはりそれが面倒(ry

ちなみにここでミソになっているのは中心を割り出す時に使っているのは `frame` ではなく `bounds` の方です。なぜなら `transform` が適用された時、`frame` で取った大きさは、実際自分からみた大きさとは必ずしも一致するとは限らないため。

## 全ての子ビューを一発で外したい

```swift:UIView.swift
public extension UIView {
	
	public func removeAllSubviews() {
		self.subviews.forEach { (subview) in
			subview.removeFromSuperview()
		}
	}
	
}
```

同じようにこれも書くのが面倒だから(ry

## 一発で複数のビューを子ビューとして追加したい

```swift:UIView.swift
public extension UIView {
	
	public func addSubviews(subviews: [UIView]) {
		subviews.forEach { (view) in
			self.addSubview(view)
		}
	}
	
}
```

同じようn(ry

# 便利そうな `class` や `struct`
## 標準出力とかを DEBUG 時だけにする `Console`

```swift:Console.swift
public struct Console {
	
	private init(){}
	
	public static let shared = Console()
	
	public func info(items: Any...) {
		#if DEBUG
			print(items)
		#endif
	}
	
	public func warning(items: Any...) {
		#if DEBUG
			print("---!!!", terminator: "")
			print(items, terminator: "")
			print("!!!---")
		#endif
	}
	
}
```

Xcode の Build Settings に、Other Swift Flags の Debug に `-D DEBUG` を設定しておけば、ここで作った `Console` でデバッグビルドのみ警告文を出力することができたりします。さらに要注意対象に目立つフォーマット（ここの `warning` みたいな）を組んでおけば自分にもわかりやすい。

ちなみに一昔の仕様は `print` は複数のスレッドが同時に呼び出すと、それぞれの出力内容が混ざってしまったりもしますので、その時はこれにさらに `Console` 専用の `dispatch_queue_t` も作って出力内容が混ざらないようにしました。今はもう大丈夫っぽいなのですが

## dispatch がもっと便利にかける `GCD`

```swift:GCD.swift
public struct GCD {
	
	public enum Thread {
		
		case Main
		case Global(priority: QueuePriority)
		case Static(queue: dispatch_queue_t)
		case Dynamic(name: String, attribute: QueueAttribute)
		
		public var queue: dispatch_queue_t {
			switch self {
			case .Main:
				return dispatch_get_main_queue()
				
			case .Global(priority: let priority):
				return dispatch_get_global_queue(priority.value, 0)
				
			case .Static(queue: let queue):
				return queue
				
			case .Dynamic(name: let name, attribute: let attribute):
				return dispatch_queue_create(name, attribute.value)
			}
		}
		
		public enum QueuePriority {
			case High
			case Default
			case Low
			case Background
			
			var value: dispatch_queue_priority_t {
				switch self {
				case .High:
					return DISPATCH_QUEUE_PRIORITY_HIGH
					
				case .Default:
					return DISPATCH_QUEUE_PRIORITY_DEFAULT
					
				case .Low:
					return DISPATCH_QUEUE_PRIORITY_LOW
					
				case .Background:
					return DISPATCH_QUEUE_PRIORITY_BACKGROUND
				}
				
			}
		}
		
		public enum QueueAttribute {
			case Serial
			case Concurrent
			
			var value: dispatch_queue_attr_t {
				switch self {
				case .Serial:
					return DISPATCH_QUEUE_SERIAL
					
				case .Concurrent:
					return DISPATCH_QUEUE_CONCURRENT
				}
			}
		}
		
	}
	
	private init() {
		
	}
	
}

extension GCD { // MARK: Semaphores
	
	public enum DispatchTime {
		case Forever
		case TimeAfter(delta: NSTimeInterval)
		
		public var dispatchTimeType: dispatch_time_t {
			switch self {
			case .Forever:
				return DISPATCH_TIME_FOREVER
				
			case .TimeAfter(delta: let delta):
				let nanoseconds = Int64(delta * NSTimeInterval(NSEC_PER_SEC))
				let time = dispatch_time(DISPATCH_TIME_NOW, nanoseconds)
				return time
			}
		}
	}
	
	public static func createSemaphore(value: Int) -> dispatch_semaphore_t {
		return dispatch_semaphore_create(value)
	}
	
	public static func fireSemaphore(semaphore: dispatch_semaphore_t) {
		dispatch_semaphore_signal(semaphore)
	}
	
	public static func waitForSemaphore(semaphore: dispatch_semaphore_t, until deadLine: DispatchTime = .Forever) {
		dispatch_semaphore_wait(semaphore, deadLine.dispatchTimeType)
	}
	
}

extension GCD { // MARK: Queues
	
	public static func runSynchronizedQueue(at thread: Thread = .Main, with action: (() -> Void)) {
		
		dispatch_sync(thread.queue) {
			action()
		}
		
	}
	
	public static func runAsynchronizedQueue(at thread: Thread = .Main, waitUntilStartForMax waitTime: NSTimeInterval? = nil, with action: (() -> Void)) {
		
		if let waitTime = waitTime {
			let semaphore = GCD.createSemaphore(thread.queue.hash)
			dispatch_async(thread.queue, {
				GCD.fireSemaphore(semaphore)
				action()
			})
			GCD.waitForSemaphore(semaphore, until: waitTime == 0 || waitTime == .infinity ? .Forever : .TimeAfter(delta: waitTime))
			
		} else {
			dispatch_async(thread.queue) {
				action()
			}
		}
		
	}
	
}

extension GCD { // MARK: Main Thread Actions
	
	public static func runMainThreadAction(action: (() -> Void)) {
		
		if NSThread.isMainThread() {
			action()
		} else {
			GCD.runAsynchronizedQueue(with: action)
		}
		
	}
	
}

extension GCD { // MARK: Check queue running status
	
	public static func isQueueRunning(queue: dispatch_queue_t) -> Bool {
		
		var isRunning = true
		
		let semaphore = GCD.createSemaphore(queue.hash)
		dispatch_async(queue) { 
			isRunning = false
			GCD.fireSemaphore(semaphore)
		}
		
		GCD.waitForSemaphore(semaphore, until: .TimeAfter(delta: 0.001))
		
		return isRunning
		
	}
	
}

extension GCD { // MARK: Once
	
	public static func runOnceAction(action: (() -> Void), inout withToken token: dispatch_once_t) {
		
		dispatch_once(&token) { 
			action()
		}
		
	}
	
}
```

内容がちょっと長いがまあ大体のものは[ここに記事](http://qiita.com/lovee/items/facfe77f6eab16651f08)に書いてました。まあ要するに `dispatch` 系の構文を最大限に補完が聞きやすいように作ったのがこれです。特に今の Xcode は途中補完も効くようになったのでこのままでもだいぶ便利になったが、それまでは前方完全一致しないと保管してくれないので、dispatch 系みたいな何でもかんで `dispatch_` で始まるやつらは本当面倒だった。

## コールバックで動くボタン `CallbackButton`

```swift:CallbackButton.swift
public class CallbackButton: UIButton {
	
	private var action: ((sender: CallbackButton) -> Void)?
	
	public var category: String?
	
	public init(image: UIImage, withAction action: ((sender: CallbackButton) -> Void)? = nil) {
		
		self.action = action
		
		super.init(frame: CGRect(origin: CGPointZero, size: image.size))
		
		self.setImage(image, forState: .Normal)
		self.addTarget(self, action: #selector(CallbackButton.tapped(_:)), forControlEvents: .TouchUpInside)
		
	}
	
	public init(frame: CGRect, withAction action: ((sender: CallbackButton) -> Void)? = nil) {
		
		self.action = action
		
		super.init(frame: frame)
		
		self.addTarget(self, action: #selector(CallbackButton.tapped(_:)), forControlEvents: .TouchUpInside)
		
	}
	
	public convenience init() {
		
		self.init(frame: CGRectZero)
		
	}
	
	required public init?(coder aDecoder: NSCoder) {
		fatalError("init(coder:) has not been implemented")
	}
	
	public func setAction(action: (sender: CallbackButton) -> Void) {
		
		self.action = action
		
	}
	
	func tapped(sender: CallbackButton) {
		
		self.action?(sender: sender)
		
	}
	
}
```

まあこれは要するに Obj-C タイプの `addTarget` 書くのが面倒だし、簡単なものならコールバックで作りたかったりもするのでこんなの作りました。ちなみに初期は `action` は `() -> Void` タイプだったが、複数ボタンを `for` 文で作る時どのボタンがどの動作かを分けるのが面倒いので、自分自身を返すように `(sender: CallbackButton) -> Void` 型に直した。そして `tag` は `UIButton` から流用できるとして、さらにボタン群を分けるために `category: String?` の変数も付け加えたから、こうすると `action` を `func buttonTapped(sender: CallbackButton)` で定義した時に中身がもっと書きやすいんじゃないかと思います。

## コールバックで動くスイッチ `CallbackSwitch`

```swift:CallbackSwitch.swift
public class CallbackSwitch: UISwitch {
	
	private var action: ((sender: CallbackSwitch) -> Void)?
	
	public init(frame: CGRect, action: ((sender: CallbackSwitch) -> Void)? = nil) {
		
		self.action = action
		
		super.init(frame: frame)
		
		self.addTarget(self, action: #selector(CallbackSwitch.switchValueChanged(_:)), forControlEvents: .ValueChanged)
		
	}
	
	required public init?(coder aDecoder: NSCoder) {
		fatalError("init(coder:) has not been implemented")
	}
	
	public func setAction(action: ((sender: CallbackSwitch) -> Void)) {
		
		self.action = action
		
	}
	
	func switchValueChanged(sender: CallbackSwitch) {
		
		self.action?(sender: sender)
		
	}
	
}
```

まあさっきのボタンと同じように値に変更があった時の動作をコールバックで定義するスイッチ

## 特定な数値にしか止まらないスライダー `IntervalSlider`

```swift:IntervalSlider.swift
public class IntervalSlider: UISlider {
	
	public var interval: Float?
	
	private var valueChangedAction: ((sender: IntervalSlider, newValue: Float) -> Void)?
	
	public init(frame: CGRect = .zero, interval: Float? = 1) {
		
		self.interval = interval
		
		super.init(frame: frame)
		
		self.addTarget(self, action: #selector(IntervalSlider.roundValue), forControlEvents: .ValueChanged)
		self.addTarget(self, action: #selector(IntervalSlider.additionalActionOnValueChanged(_:)), forControlEvents: .ValueChanged)
		
	}
	
	public required init?(coder aDecoder: NSCoder) {
		self.interval = 1
		super.init(coder: aDecoder)
	}
	
	@objc private func roundValue() {
		
		guard let interval = self.interval else {
			return
		}
		
		let newValue = round(self.value / interval) * interval
		self.setValue(newValue, animated: false)
		
	}
	
	@objc private func additionalActionOnValueChanged(sender: IntervalSlider) {
		self.valueChangedAction?(sender: sender, newValue: self.value)
	}
	
	public func setValueChangedAction(action: ((sender: IntervalSlider, newValue: Float) -> Void)?) {
		self.valueChangedAction = action
	}
	
}
```

通常のスライダーの値は `Float` 型なので連続で値が取れるわけですが、逆に例えば `1`、`2`、`3` などといった断続的な値だけを有効にしたい時に使うのがこれです。例えば `interval` を `1` にすると、上記みたいに `1`、`2`、`3` のような値になりますし、`2` とかにすれば `2`、`4`、`6` とかになります。ただこれには今の所特に（俺の）需要がないのでそんなに作りこんでいないが、`1`、`3`、`5` みたいな値の取り方が必要になるともう少し手間がかかります。

まあ基本は「俺得」で作った拡張ですのでそこまでの作り込みがあんまりありませんが、このままだとフレームワーク自体が結構でかくなってしまうのでそのうちサブモジュールも作って特定なものだけをインポートできたりしたらいいなとかも思ってます。

あと余談ですが「Eltaso」という名前は当然「えるたそ」から来てます（）