CLI-Todo-ToolをPythonで作る # 1
対象読者
- Pythonが好きな人.
- CLIツールに興味がある人.
ツールの詳細
- ツール名: 🐰 rabbit-todo 🐰
- 制作者: Mayuge 1名
- リポジトリ: rabbit-todo
ツールを作った背景と, 自分の現在の状況
僕はTodoをまとめるために, GithubのIssueを使っていました.
しかし, 個人開発の僕には使わない機能が多い.
なんなら, ブラウザに行くのも面倒.
そんな感じでした.
Github以外に自分のプロジェクトのTodoをまとめられるツールを探していたのですが,
基本的に出回っているツールは個人開発者向けではなく(当たり前),
共同開発をかなり意識したツールばかり.
ボッチの僕とは縁がない(´;ω;`)
ということで, エンジニアとしての魂が僕にこう言いました.
自分でつくりなさい
ということで, 作ることになりました.
僕は, 何回かツールを作ったことがあるものの, 作り上げたことがない人です.
初期バージョンでは, 動くものを作って世の中に公開する事を目標にしました.
なので機能は充実していません.
Pythonのバージョン + ライブラリ
-
Python 3.11
-
colorama ( 0.4.6 ): 文字に色を付けるため.
-
click ( 8.1.7 ): CLI用のフレームワーク.
最終的なディレクトリ構成
rabbit-todo/
├── .gitignore
├── LICENSE
├── README.md
├── poetry.lock
├── pyproject.toml
├── rabbit_todo/
│ ├── __init__.py
│ ├── entry_point.py
│ ├── cmd/
│ │ ├── __init__.py
│ │ └── cli.py
│ ├── common/
│ │ ├── __init__.py
│ │ ├── messages.py
│ │ └── result.py
│ ├── core/
│ │ ├── __init__.py
│ │ ├── i_task_repository.py
│ │ ├── task.py
│ │ └── task_id_generator.py
│ └── io/
│ ├── __init__.py
│ └── json_task_repository.py
└── tests/
├── __init__.py
├── test_cli.py
├── test_json_repository.py
├── test_result.py
├── test_task.py
└── test_task_id_generator.py
工夫した点
圧倒的に依存性の方向です.
こんなイメージです.
coreにあるクラスはioもcliも知りません.
rabbit-todoのUI表示に, CLI以外の選択肢を作りたいなぁと思っているので,
coreとcliの分離は妥当ですかね.
ioに関しては, json以外の方法は正直取らない気がするのですが,
cliが分離されていますし, コストがかからない今のうちに分離しておきました.
感じた恩恵としては, core内で, repositoryのインターフェイスを定義しているので,
coreのテストが楽だったことですかね.
これからもどんどん恩恵を感じることができるようになっていくんじゃないかなぁと思っています.
現在は, cli.py にTaskを追加するロジックなどを書いてしまっていますが, 最終的にはその辺も分離する予定です.
意図的な先送りで選択肢を増やす戦略です.
エラーハンドリング
エラーハンドリングは, RustLikeな方法にしました.
Repository系で起きたエラーを上の層に伝えるには最善だと判断.
Result型の定義はこんな感じです.
T = TypeVar('T')
B = TypeVar('B')
class Result(Generic[T]):
def __init__(self, value: T | None, is_success: bool, error_message: str | None = None) -> None:
self._value = value
self._is_success = is_success
self._message = error_message
@classmethod
def ok(cls, value: T) -> Result[T]:
return cls(value=value, is_success=True)
@classmethod
def error(cls, error_message: str) -> Result[T]:
return cls(value=None, is_success=False, error_message=error_message)
@classmethod
def from_result(cls, result: Result[B]) -> Result[T]:
if result.is_success():
return cls.ok(result.unwrap())
return cls.error(result.message)
@property
def message(self) -> str | None:
return self._message
def is_success(self) -> bool:
return self._is_success
def unwrap(self) -> T:
if not self._is_success:
raise RuntimeError("Result is not a success")
return self._value
Genericは, 見たことはありますが, 書いたことはなかったので少し心配ですが, 特に支障がなさそうなので, いったんはこのコードで進めようと思ってます.
今後追加したいもの
正直, 初回のこのバージョンは, 成果物を完成させたことがなかったため,
完成させること第一で考えました.
ですが, 拡張性をかなり意識したので,
簡単にいろいろな機能を追加できるようになってるはず...
僕は欲張りなので, かなり追加したいものがあります.
ですが, ほとんどのものをプラグインといいますか,
オプショナルなものにしたいと思ってます.
タスクに機能をもう少し追加
タスクは最小単位ですので, 最小限の機能のみにして,
使いたい人はオプショナルなプラグインをonにする感じをイメージしてます.
とはいえ, タスクの名前と達成したかどうかだけを管理するだけでは
要素が少ないと思うので, 何かしらオプショナルでない機能を付けたいとは思ってます.
どっちにしろオプショナルな機能が多めなツールになりそうですね.
構造化機能
-
Featureクラス
- gitのfeatureブランチみたいな感じでTaskをグループ化.
- listなどで見たときに進捗をグラフィカルに表示したい.
-
Milestoneクラス
- 自分のプロジェクトの中長期的な目標を表す.
- TaskとFeatureをグループ化.
- Featureと同じく, グラフィカルに進捗を表示したい.
Gitとの連携
- Featureクラスを作成すると, gitでfeatureブランチが作成される機能
- このツールからgitへのpushが行えるようにする.
などなど.
タスクの順番を決める
タスクを立ててもどれからやっていいかわからない.みたいな人のために,
タスクを立てる順番を決めるコマンドと機能を作ってもいいかなぁと思ってます.
ポモドーロタイマー機能の追加
タスクに予想ポモドーロ数みたいな属性を追加 + タイマー機能を実装.
タイマーは最初はtkinterとかで実装して, 合間を見て, ブラウザとかを試してみたいですね.
コマンドの充実
さすがに現在の, add
, remove
, done
, list
だけではきついと思うので,
新しいコマンドも実装したいですね! ( Issueなどで, アイデアください! )
GUIの追加
ブラウザを使って, ブラウザをスクリーン, CLIをコマンドを打ち込む場所として使う.
そんな感じのことができたらいいなぁと思ってます.
ボタンを押す代わりにコマンドをCLIで使う.
ちょっとあこがれませんか?
まとめ
rabbit-todoの初期バージョンの簡単な紹介でした.
今後も自分の理想になるように改良を続けていきます!
気になった方はぜひGithubのリポジトリを見に来てください!
また, 僕と同じような悩みを持った方で, 一緒に進化させていきたい!と思っていただけた方は,
ぜひフィードバックや機能のリクエストお願いします!
各種リンク
Github
Twitter
メール: mayuge.studio.public@gmail.com
メールに来てくだされば, 反応できると思います!
Discussion