Xcodeを利用したツールを作りましたのでご紹介(仮)

# [Swift 愛好会](http://love-swift.connpass.com/event/39087/)
## 今日のアジェンダ
- 自己紹介
- 雑談
- 今日も何か作ってきたの？
- Xcodeでコマンドラインツールの作り方  

  
  
--- 
   
   

## 自己紹介
<img src="https://qiita-image-store.s3.amazonaws.com/0/84459/profile-images/1473703103" style="width: 60%; height: auto;">

name: 廣瀬 雄大
github: https://github.com/bannzai/
qiita: https://qiita.com/bannzai/

あだ名: star乞食
口ぐせ: starください

Swift愛好会ではOSSを自作して紹介しています。

star ください

---

## 前回紹介したOSS（雑談)
前回 **Kaeru** と言う自作OSSを紹介させていただきました。
qiita: [🍎が好きすぎてiPhoneで使われているあのUIを再現してみた](http://qiita.com/bannzai/items/ac429c829503bbe147d6)
github: [Kaeru](http://github.com/bannzai/Kaeru)


なんとこの発表をきっかけに順調にstarが伸びていき
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
**300** star超え達成しました！！<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
  
  
  
  
  
  
  
  
  
  
  
 　　
　　
　  　
　　
　　
　　
  
  
  
  
**star**をしてくださった皆様ありがとうございます<br><br><br><br><br><br><br><br><br><br><br>
　　
　　
  
  
  
  
  
  
  
  
  
  
 
いえーいぱふぱふ<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
  
  
  
  
  
  
  
  
  
  
 
  
  
  

　　
　　
　　
　　
　　
　　
　　
  
  
まだの人は**star**ください
  
  
  
  
  
  
  
  
## 今日も何か作ってきたの？
実はまだ作成途中なので今日はこんなものを作りたかった
と言う内容で発表させてもらおうかなと思います。  
  
  
  
  
   
なので、今日は
**PR**乞食になります　　
**PR**ください

  
  
作っている途中のリポジトリは[こちら](https://github.com/bannzai/xcp)

## 作りたかったもの
今回はコマンドラインから**Xcode**を使用せずにディレクトリ等を操作するツールを作ろうと思っていました。

名前は仮で**xcp**としています。

下記に一例(妄想)をあげます。

##### `project.pbxproj`で管理しているファイル一覧
```
$ xcp paths
/develop/swift/project/ProjectTests/Tests.swift
/develop/swift/project/ProjectTests/Info.plist
/develop/swift/project/Project/AppDelegate.swift
/develop/swift/project/Project/ViewController.swift
/develop/swift/project/Project/Info.plist
/develop/swift/project/ProjectUITests/Info.plist
/develop/swift/project/Project/Project-Bridging-Header.h
/develop/swift/project/Project/Assets.xcassets
...
```

##### ファイルを新規作成して`project.pbxproj`にもaddする
```
$ xcp add --create /develop/swift/project/SecondViewController.swift
...
```

##### ファイルを`rm`して`project.pbxproj`からも消す
```
$ xcp rm /develop/swift/project/SecondViewController.swift
...
```

##### `project.pbxproj`で管理しているstruct一覧
```
$ xcp find --struct "hogehoge"
/develop/swift/project/Project/hogehoge.swift struct hogehoge
```

##### struct の名前をreplaceする(難しそう)
```
$ xcp refactor --replace-name --struct --filename "hogehoge" "fugafuga"
/develop/swift/project/Project/fugafuga.swift struct fugafuga
/develop/swift/project/Project/ViewController.swift fugafuga()
```

と、コマンドから色々操作できたら
IDEに縛られず処理を書くことできそうだなと思っています。


## Xcodeでコマンドラインツールの作り方  
僕自身がIDEしかあまり知らずにプログラマとして育っていきました。
最近はCUI環境での開発も行っていますがやはりIDEだけを触っていたら
得られないものがあります。

コマンドラインツールに魅力を感じつつも
なかなか踏み切れない人の助力となればいいなと思います。

今回紹介するのは**Xcode**というIDEを使用した
コマンドラインツールとなります。
作ったツールはターミナル等から**shell**を介して実行できます。

`make`等を使用した開発もやったほうがいいでしょうが、
とっかかりとしていつも使っているツールから入れたら十分だと思います。

今回は標準入出力まで行えるところを確認しましょう。

作り方
1: Xcodeでコマンドラインツールを作成
Xcodeから新規でプロジェクト作成 

![image](https://qiita-image-store.s3.amazonaws.com/0/84459/0415cc58-17a8-b28e-dd2a-86f7f51db9b7.png)

macOSから`Command Line Tool`を選択し進む
例では`Demo`というプロジェクト名で作りました。

2: `main.swift` に`Hello world`が書かれているのでビルドして実行ファイルを作る

``` 

import Foundation

print("Hello, World!")

```

![image](https://qiita-image-store.s3.amazonaws.com/0/84459/74986687-661b-9a26-cde3-639bf77456ab.png)

ビルドしたら実行ファイルができておりターミナルで実行ファイルがある場所に`cd`しましょう

```
~/Library/Developer/Xcode/DerivedData/Demo-fgvorkhdvjwlgrgkalyitrwhkezn/Build/Products/Debug/

```

上記のようなディレクトリにあります。
そこで`./Demo`と入力し`Enter`を押せば
`Hello, world`と表示されます。

```
$ ./Demo
Hello, world
```


3: 標準入出力
標準出力は`main.swift`からも分かる通り
`print`で出力されます。

入力はコマンドの後にスペース区切りで渡すことができます。
例えば`paths`という入力を`Demo`に渡す場合は
`$ ./Demo　paths`
でいいでしょう。

入力をコードから利用する場合は

```
ProcessInfo.processInfo.argumets
```
から先ほどであれば`paths`という文字を取得することができます。
本当に受け取れているかどうかを出力してみましょう
`main.swift`を書き換えてビルドします。

```
let isExists = ProcessInfo
    .processInfo
    .arguments
    .contains{ $0 == "paths"}

print("is exists path? : \(isExists)")
```

ターミナルに戻り

```
$ ./Demo 
is exists path? : false
```
```
$ ./Demo paths 
is exists path? : true
```

これで入力が渡ったことが確認できました。
あとは渡ってきたパスによって処理を分岐させれば
自分の作りたいツールができます。やったね

他にもプロジェクトから`bash`コマンドを叩いてその標準出力を取得してどうこうといったこともできます。

`xcp`でもやっている場所があるので詳しくは[ここら辺](https://github.com/bannzai/xcp/blob/master/xcp/shell.swift#L17)とかを見てください。

注意点としてはまだ`swift 2.3`として書いています。


## ちなみに`xcp`は後どれくらいでできそう？
だいぶ時間かかりそうなのでのんびり開発していこうかなと思います。

一番の課題は実行時に`project.pbxproj`の情報をいちいち読んでいるからか
無駄な計算があるのか、コマンドラインツールとしては致命的に遅いです。

なので
`PR`や意見をお待ちしております。

## おしまい\\(^o^)/