Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PyQt5で自分のためのIDEを作っちゃおう!

fukatani
September 17, 2019

 PyQt5で自分のためのIDEを作っちゃおう!

PyQt5でIDEをフルスクラッチで自作しようという発表です。
本資料はPycon JP 2019でスピーチさせていただきましたものです。

概要
- なぜIDEを自作したのか?
- PyQt5製IDEのアーキテクチャ
- PyQt5でまずはメモ帳を作る
- メモ帳をプログラミング用エディタに進化させる
- デバッガなどと連携させてIDEを仕上げる

IDEの全貌はhttps://github.com/fukatani/rujaion にあります。

ご来場いただいた皆様、スタッフの皆様、スポンサーの皆様誠にありがとうございました。

fukatani

September 17, 2019
Tweet

Other Decks in Programming

Transcript

  1. PyQt5で自分のためのIDEを 作っちゃおう! Pycon JP 2019 深谷亮祐

  2. 自己紹介   @fukafukatani 所属: トヨタ自動車株式会社 仕事: 自動運転/物体認識(3D点群/画像) 趣味: 競技プログラミング(AtCoder青)、ボドゲ

  3. あらすじ あるIDEで競技プログラミングに参加していたが、いくつかの問題が、、

  4. 右クリックメニュー縦 に長すぎ問題 項目やたら多い

  5. AsMut問題 行末で改行したいだけ なのに補完候補が出ちゃう

  6. IDEを自作したモチベーション - どのIDEも「こんな機能がほしい」「この挙動はちょっと気に入らない」がある - やりたいことをやるのにPythonで実現したい - 開発しやすい - ライブラリの充実 Pythonで、自分だけのためのIDEを実現するぞ!

  7. ちょっとだけ競プロの話 与えられた問題文の仕様を満たす プログラムを書く 問題文だけでなく入力例と出力例が与え られる 例が複数あるので確認が手間

  8. できたもの IDEにブラウザ(PersephoneP)を埋め込み 問題の閲覧をしながら、プログラミングできる 閲覧された問題の入出力例は、バックグラウ ンドでonline-judge-toolsによってダウンロード Testボタンで書いたコードをテストできる!

  9. というわけで、本日のコンテンツ - PyQtを使った統合開発環境のアーキテクチャ - QPlainTextEditでメモ帳を作ろう - QPlainTextEditを強化して、プログラミング用エディタにしよう - テキストエディタとデバッガを通信させてIDEに仕上げよう ところどころ、コードが入りますが、

    雰囲気を感じていただければ、... 全体はhttps://github.com/fukatani/rujaion
  10. というわけで、本日のコンテンツ - PyQtを使った統合開発環境のアーキテクチャ - QPlainTextEditでメモ帳を作ろう - QPlainTextEditを強化して、プログラミング用エディタにしよう - テキストエディタとデバッガを通信させてIDEに仕上げよう

  11. Python製IDEってあまり聞かないけどできる の? Integrated Development Environment: 統合開発環境のこと - テキストエディタ(補完、シンタックスハイライト、定義ジャンプ、...) - コンパイル(ビルド)、デバッグ

    が統合されたソフトウェア 実はPythonはIDEを作れるだけの十分なポテンシャルを有する
  12. デバッガ IDEを図にしてみると エディタ 文字キーの入力受付 表示 補完ライブラリ

  13. デバッガ 図にしてみると エディタ 補完ライブラリ 既存のライブラリを使用 PDB 既存のライブラリを使用

  14. デバッガ 図にしてみると エディタ 補完ライブラリ PyQt+カスタマイズしていく 本発表のメイン

  15. PyQtとは PythonのGUIキット、割と人気 IDE向けの機能も充実 - QPlainTextEdit (テキストエディタ) - QCompleter (テキスト補完) -

    QSyntaxHighlighter (シンタックスハイライト) 既存ライブラリ+PyQtを組み合わせればIDEが作れる!
  16. 本日のコンテンツ - PyQtを使った統合開発環境のアーキテクチャ - QPlainTextEditでメモ帳を作ろう - QPlainTextEditを強化して、プログラミング用エディタにしよう - テキストエディタとデバッガを通信させてIDEに仕上げよう

  17. 6行で作るテキストエディタ(QPlainTextEdit) コピペ、アンドゥが可能なエディタが出現 ただし、セーブ/ロードはできない

  18. キーバインドの追加 QPlainTextEditを継承し、 keyPressEventをオーバーライド 継承元のキーバインド を有効に キーバインド指定

  19. セーブ(名前をつけて保存)の実装 File I/Oでテキスト形式で保存 ウインドウが出現 →選択したファイル名を返す

  20. ロードの実装 File I/Oでロードしてテキストをセット ウインドウが出現 →選択したファイル名を返す

  21. 本日のコンテンツ - PyQtを使った統合開発環境のアーキテクチャ - QPlainTextEditでメモ帳を作ろう - QPlainTextEditを強化して、プログラミング用エディタにしよう - テキストエディタとデバッガを通信させてIDEに仕上げよう ここまででメモ帳レベルのエディタはできた

    次はオートインデント、シンタックスハイライトを実装
  22. やるべきことは3つ 入力済テキストの取得 テキストの自動挿入 ハイライト (一部箇所のフォントの色変更、波 線、...)

  23. やるべきことは3つ オートインデント、補完、スニペット挿入 シンタックスハイライト、対応するカッコ の強調、文法エラー箇所の強調 多くのプログラミング向け機能はこの3つの要素から成立 この辺を実装すると「使えるじゃん!」という感覚になってくる 入力済テキストの取得 テキストの自動挿入 ハイライト (一部箇所のフォントの色変更、波

    線、...)
  24. オートインデントの動作 def function: “:”で終わる行で改行する と、 (keyPressEventで判定) def function: スペースを四個いれてほしい (正確にはネストを一段下げる)

  25. オートインデントの実装 テキスト挿入 カーソル行の テキスト取得 Enterキーのショートカットキーに割当

  26. 現在行ハイライトの動作 ステップ 1. テキストカーソル位置が”変わる度”に現在行をチェック 2. 現在行の背景色を変える(ハイライト) テキストカーソルが存在する 行の背景色を変更

  27. あるイベントが起こる度に カーソルが移動する度に Editorのテキストが変化する度に キーが押される度に マウスホイールが回る度に 現在行の色を変更 文法エラーをチェック 「XXX の度に YYY

    を行う」という類の実装は、 Qtではシグナルとスロットという概念で扱う
  28. 現在行ハイライトの実装 (1) カーソルが移動する度に Editorのテキストが変化する度に キーが押される度に 現在行の色を変更 文法エラーをチェック シグナル スロット シグナル

    今回はQPlainTextEditのメンバなので実装不要 スロット 今回は自分で実装 接続
  29. 現在行ハイライトの実装 (2) 背景色の変更: ボリューミーなので、詳しい説明は省略 写経して使ってください 行全体 特定箇所の背景・フォントの 変更、 下線の追加

  30. シンタックスハイライトの動作と実装方針 ハイライト自体は現在行のハイライトと同様 テキスト全体を走査し、正規表現にマッチする場所をハイライト ex. - def, class, importなどの予約語との一致 - #

    の後ろはコメント - 定数(2018, 3.14, None, True) - 文字列リテラル(“Hello World”) QSyntaxHighlighterを使って実装すると楽 シンタックスハイライト実行例
  31. 本日のコンテンツ - PyQtを使った統合開発環境のアーキテクチャ - QPlainTextEditでメモ帳を作ろう - QPlainTextEditを強化して、プログラミング用エディタにしよう - テキストエディタとデバッガを通信させてIDEに仕上げよう ここまででプログラミング用エディタはできた

    補完ライブラリやデバッガと通信して、IDEにしよう
  32. 補完機能の概要 エディタ 補完ライブラリ import json json.lo load loads ユーザー 候補の選択

    選ばれたテキストの挿入 insertPlainText
  33. 補完ライブラリの叩き方 >>> import jedi >>> source = """import json ...

    json.lo""" >>> jedi.Script(source, 2, len("json.lo")).completions() [<Completion: load>, <Completion: loads>] Pythonの補完なら、jediを使うのが楽 (pip install jedi) その行の 何文字目? 何行目? テキスト全体
  34. ポップアップ周りの実装概要 (QPlainTextEdit) ポップアップ表示時 のEnter判定 QCompleter(ポップアップ内容の 制御を行うクラス)を継承

  35. GUIデバッガを作る前に、、CUIデバッグの流れ 4行目でブレークポイントをしかけて実行 その時点でのaの内容を表示 ユーザー入力文字は水色 “(Pdb)”という文字列が出力されると、入力を受付可能な状態 $ python3 -m pdb myscript.py

    (Pdb) breakpoint 4 (Pdb) run hello hello >/script.py(4)<module>() (Pdb) print a 40 デバッグしたいプログラム
  36. デバッガとの通信 実行中のプログラムから特定の文字列が出力されるのを待つ場合、 対話自動化ライブラリpexpectで実現できる pip install pexpect (Pdb)という文字列が見つかるまでブロックされ、見つかると続行

  37. pexpectを使った対話型デバッガ機能の概要 エディタ デバッガ(Pdb) >hello >hello >/script.py(3) (Pdb) run ユーザー 次の指示

    Step in / Print a / … (Pdb)という文字列 が現れるまで待機
  38. まとめ - PyQtを使ったIDEのアーキテクチャ - QPlainTextEditでメモ帳を作った - プログラミング用エディタ向け機能の実装 - オートインデント(insertPlainText) -

    現在行ハイライト - IDE機能の実装 - JediやQCompleterを使った補完 - pexpectを使った対話型デバッガの実装
  39. 今日話せなかったこと - QThreadを使った重い処理の非同期化 - ブレークポイントの管理 - QtWebEngine - コンソールの実装 https://github.com/fukatani/rujaion

    PyQt5を使ったRust/C++ IDE (Pythonサポート計画中)
  40. ご清聴の皆様、スタッフの皆様、ありがとうございました!  @fukafukatani

  41. 補足スライド

  42. 質問1、デバッガの出力はどうやって使うの か? A. パースします。 print aをして、 a = 40という出力が出たなら、” =

    ”の後ろを取得すればよいです。
  43. 質問2、PyQt5の動作は遅くないか? A. (実感として)遅くないです。不要な機能がないせいか、有名IDEより速いです。 Visual Studio CodeなどもJavaScriptでできていますし、フロントエンドの速度はあま り問題にならず、補完やデバッグなどのバックエンド側の速度が問題になることが多 いです。 C++の補完をやろうとしたとき、真面目に保管しようとすると標準ライブラリ全部読み 込まないといけないので遅くなりました。(cqueryみたいな解決策はあり)