--- Title: Scintilla2 11 Author: yamasyuh68 Web: https://mimemo.io/m/3kyw8o3Ondo6Lrg --- 190924 # ツリーのアウトラインを書き出す機能を実装 - アウトラインデータをエディタ内に新規文書として書き出す - 秀丸でGREPしたときに結果が新規文書で表示されるイメージ - データ取得は無限階層のスキャンになりモデルのスキャンとほぼ同じロジックになる これは再帰関数で実装したが、何とか再帰しないで書きたいと考えてたルーチンを使ったらすんなりいけた( ´∀`) ``` def treeoutput(self): current=self.ui.tabWidget.currentIndex() self.makenewtab( None ) new=self.ui.tabWidget.currentIndex() , self.currentSci self.ui.tabWidget.setCurrentIndex(current) tree=[] for ii in range(self.ui.treeView.model().rowCount( )) : root = self.ui.treeView.model().index( ii,0) # start 0,0 new[1].append(root.data() +' , '+ root.sibling(root.row(),1).data() +'\r\n') tree.clear() tree.append( [ 0 , self.ui.treeView.model().rowCount(root) ,root ] ) # [ index , count , parent ] n=0 while 1 : flag=1 for i in range( tree[n][0] , tree[n][1] ): # 子供が見つかれば異常で抜ける child= tree[n][2].child( i , 0 ) # 見つからなければ普通に抜ける new[1].append( child.data()+' , '+ child.sibling(child.row(),1).data() + '\r\n') if self.ui.treeView.model().rowCount( child) : if len( tree ) <= n +1: tree.append(None) tree[n+1] = [ 0 ,self.ui.treeView.model().rowCount( child), child] tree[n][0] = i+1 # 戻ったときのためにインデクスを更新しておく flag = 0 break if flag: # 通常で抜けた場合 上に戻る if n==0 : # 全部終わったらwhile を抜ける break else : n -= 1 continue else : # 異常で抜けた場合 潜る n += 1 continue def columnShow(self): self.ui.treeView.setColumnHidden(1, not self.ui.treeView.isColumnHidden(1) ) ``` ## 再帰しない大まかなロジック 1. root を取得 2. while 1 のループを回し、root に子供がいれば取得してさらにループに戻ってその子供を探し続ける 3. 子供がいなければ階層を戻して兄弟で同じ事を続ける 4. 階層を進めたり戻したりするのでそれぞれの階層のデータを保持しておく、これはlist を使う list = [ [ 行のインデクス、行の数、親のオブジェクト] , [,,] , [,,]/, ] リストのインデクスが階層に相当する 5. while のループ処理が階層0で正常に終了したらループをbreakする - 一応しっかり動いてるけど可読性は極端に低い そもそもリストで次元が増えていくとほぼ理解できなくなる(私だけか??) 一週間位したら自分でも何を書いたかわからなくなっている可能性高い( ̄― ̄?) - **もっとエレガントに書きたい** # アウトラインツリーにメニューをつけた - とりあえず書き出しと隠しカラムの表示切り替え機能をつけた - 表示切替はいわゆるトグル、直球で行けばフラグを立ててその逆を指定する フラグをifで分岐させるのが素直だが最近は三項演算子を使ったりしてた しかしフラグがboolであれば、単純に not flag で良いことに気づいた treeView.setColumnHidden( column , not treeView.isColumnHidden() ) この1行でいけた。切り替わります 短くて可読性も高い、エレガントですよね~ --- 190926 # 解析ルーチンの書換実験 - 行頭の見出し文字「.」の個数をカウントするロジックだが、インデントの増減とか注釈付加の仕組みを考えてると結構汎用的に使う機能だと思うようになったので、早く単純なコードを考え直してみた ``` ① for i2 , l in enumerate( line ) : if l == '.' : continue else : break ② for i2 , l in enumerate( line ) : if l != '.' : break ③ for i2 in range(line.__len__()): if linet[i2] != '.' : break ``` - 現在①にしてるが、単純に②の方がシンプルだと気づいた でも一番長い文書で比較したけどほとんど時間は変わらず - ①②は文字列をイテレータにするので新たにオブジェクトを作る分時間がかかるかなと思って③を考えた 文字列がリストだってことを利用した点では同じだけど少し早いかなと思ったら、逆に遅かった なぜだろう・・・(・_・?) - でとりあえずコードは②に書き換えたが、これをクラス内の別関数にして呼ぶようにしたらそれだけで結構遅くなった やはり**関数を呼び出すと遅くなる**んだな このロジックは他でも使うので関数化して効率化したかったけど遅くなるようだと却下だ、重複して書くことにする - そもそものロジックの見直し自体は続けたい この部分はロジカルな部分以上にpythonの内部処理の問題になるからあんまり意味ないかもしれないけど、**こういうのも楽しいからよし!** # インデント増減 - VSCodeにある機能、python には必須ですよね 私は基本半角スペース4つにしてるので、まずは該当行の先頭スペースの数の取得から始まる この仕組みは注釈付加の際にも使う予定なので関数化した ``` def countToken(self,line,token): for i , l in enumerate( line ) : if l != token : return i # return i def indentincrease(self): line = self.getCursorPosition() i = self.countToken( self.text(line[0]) , ' ' ) token=[' ',' ',' ',' '] self.insertAt( token[ i % 4] ,line[0] , 0 ) ``` - インデント増は半角スペース挿入で簡単だが減の方が難しいことに気づいた 範囲指定にも対応する必要あり、まだこれから # アウトラインの書き出し関係、ラムダの利用 - シンチラに文字列をアペンドする箇所はルートと子供で二箇所ある 変数をたてないで1行で長いコードにしたので、ラムダで関数化してみた - 変更があったときにラムダを直せば二箇所とも直るから楽 書き出す項目を選択したくなったらラムダを複数書いて切り替えれば良いから楽だ - ラムダ化した方が良い場所では極力使うようにしよう --- 190930 # インデント増減機能を実装 - 減にも対応 - 選択範囲から行のfrom toを取得してイテレータにして回す そのあとで選択範囲を元に戻す - 実装はしたけどpythonプログラミングでしか使いそうに無い 必要なかったかも ( ̄― ̄?) # 現在ファイルをお気に入りに追加 - ①現在のファイル名を取得 ②お気に入りファイルを読み込み ③ファイル名をappend ④最終行を表示 こんな感じで実装した - フォルダ設定したければ自分で引き続き編集する想定です - お気に入りファイルを保存した場合は自動でビューを更新する仕様にするか?? --- 191001 # 行頭連番挿入機能実装 - 簡単だった (・∀・)ノ ①選択範囲あり~その範囲のみ、なし~全文 ②行数取得、挿入連番の桁数取得 ③行頭にその桁数で連番挿入をforで回す - 桁数は行数に応じて可変となる format文で0詰めの文字列は作成できるけど、この桁数を変数に出来るのだろうか?? strオブジェクトの解説を読んでて覚えた **str.zfill( n )** メソッドで実装した、問題なし ---- └──> [scieditor2](https://mimemo.io/m/zeXgworpjz4K0Ek)