TIL

Today I Learned. 知ったこと、学んだことを書いていく

文字列からクラスのインスタンスを生成 - VB.NET

例) ProjectName.Personインスタンスを生成したい

生成対象のクラス(ProjectName.Person)

Public Class Person
    Public name As String

    Public Sub New()
        Me.name = "hoge"
    End Sub

    Public Sub New(ByVal name As String)
        Me.name = name
    End Sub
End Class

生成するメインモジュール

Module Module1

    Sub Main()
        Dim personType As Type = Type.GetType("ProjectName.Person")
        ' 引数なしのコンストラクタ
        Dim personConstructor As ConstructorInfo = personType.GetConstructor(Type.EmptyTypes)
        ' Stringの引数を持つコンストラクタ
        Dim personConstructor2 As ConstructorInfo = personType.GetConstructor(New Type() {GetType(String)})

        Dim personClassObject As Object = personConstructor.Invoke(New Object() {})
        Dim personClassObject2 As Object = personConstructor2.Invoke(New Object() {"太郎"})

        Debug.Print(personClassObject.name)
        Debug.Print(personClassObject2.name)
    End Sub

End Module

出力結果

hoge
太郎

ポイント

  • Type.GetType()でクラスの生成
  • {Type}.GetConstructor()でコンストラクタの生成
    • 引数なしの場合、Type.EmptyTypes
    • 引数ありの場合、Typeインスタンスを生成し、渡す
  • {ConstructorInfo}.Invoke()インスタンスの生成

参考文献

頭に来てもアホとは戦うな! を読んで

読み終わったから、アウトプットする

Before

  1. 他人にどう思われるかを気にして、行動していた
  2. 自分はできる人だと思いこんでいた

気づき

1. 他人にどう思われるかは気にせずに行動してみる

他人からどう見られるかは、人生の最後から逆算すればどうでもいい途中経過

人生の終りがあると考えると、やりたいことは今すぐにすべき。

他人にどう思われようと構わずにやりたいことをやるべき。

つまらない意地とかプライドは人生で全く意味のないこと

2. 等身大の自分を知るために、行動する。そして、等身大にあった目標を立てる

等身大の自分を知ること(自分を見失わないこと)

常に等身大の自分を見つめて、それに基づいた正しい目標を設定し、成長していく

自分の力を過信しない。たまたま、なにか成功したからと言って、調子に乗らない。それはただの途中経過で、目標はその先にある

3. 気まずいときこそ、コミュニケーションを取る

これがこの本を読んで一番の収穫

もし、気まずいときにコミュニケーションをしないと、事態は悪化するしかなくなってしまう。
お互いに最悪のシナリオで深読みし合うしかなくなる

コミュニケーションを取らないと、この深読みの負のループに入ってしまい、相手の何気ない行為にも、悪気のある行為であると思いこんでしまい、最終的には衝突してしまう。

最低限のコミュニケーションを取り、相手に敵意はないことを伝えて、これ以上関係を悪化させないようにする

Neovim内で使うpythonをpyenvのアクティブなものにする - Neovim

g:python3_host_progに値をセットする(Python3の場合)

g:python3_host_progに値をセットすると、neovim内で実行するpython3を指定できる

pyenvのアクティブなPythonを使うようにするには、以下のように~/.config/nvim/.init.vimに書く

let g:python3_host_prog = system('type pyenv &>/dev/null && echo -n "$(pyenv root)/versions/$(cat $(pyenv root)/version | head -n 1)/bin/python" || echo -n $(which python)')



メモ書き

:checkhealthしたときのメッセージ

## Python 3 provider (optional)
  - INFO: `g:python3_host_prog` is not set.  Searching for python3 in the environment.

:help g:python3_host_progしてみた

PYTHON PROVIDER CONFIGURATION ~
                        *g:python_host_prog*
                        *g:python3_host_prog*
Program to use for evaluating Python code. Setting this makes startup faster.
Also useful for working with virtualenvs.  >
    let g:python_host_prog  = '/path/to/python'
    let g:python3_host_prog = '/path/to/python3'

Pythonコードを評価するためのプログラム。 これを設定すると起動が速くなります。

virtualenvsでの作業にも便利です。

.vimrcに以下の記述を追加する

参考文献

prompt-toolkitで検索ツールバーの実装と、インクリメンタル検索の実装した - Python

いろいろやって、できたから、まとめてみる

ソースはGistにあげた

https://gist.github.com/tamago324/806aac08455412d06b48b7022f5b660f

2018-11-16 00:21:49 編集:カレントバッファで検索結果の移動をするように変更

単純な検索機能を実装する

まずは、単純な検索を実装する

  • /で検索の文字入力開始
  • ?で検索の文字入力開始(逆順に検索)
  • Enterで検索実行
  • c-cで検索入力中止
  • 検索文字が0文字になったら、検索入力中止
  • nで次の検索位置
  • Nで逆順に次の検索位置

今は、ReadOnlyの想定で作ったから、nとかNとか入力できないのは気にしない

from prompt_toolkit.application import Application
from prompt_toolkit.application.current import get_app
from prompt_toolkit.buffer import Buffer
from prompt_toolkit.document import Document
from prompt_toolkit.filters import Condition, is_searching
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.key_binding.bindings import search
from prompt_toolkit.layout.containers import HSplit, Window
from prompt_toolkit.layout.controls import BufferControl
from prompt_toolkit.layout.layout import Layout
from prompt_toolkit.widgets.toolbars import SearchToolbar


text = "\n".join([str(i) for i in range(100)])

# vi_mode=Trueとすると`/`と`?`で表示されるようになる
search_toolbar = SearchToolbar(vi_mode=True)
control = BufferControl(
    Buffer(document=Document(text), read_only=True),
    search_buffer_control=search_toolbar.control,
)


# ウィンドウ
body = HSplit([Window(control), search_toolbar])

# キーバインディング
kb = KeyBindings()


@kb.add("q")
def _(event):
    event.app.exit()


# 検索ツールバーの文字が空になったかどうか
@Condition
def search_buffer_is_empty():
    " Returns True when the search buffer is empty. "
    return get_app().current_buffer.text == ""


kb.add("/")(search.start_forward_incremental_search)
kb.add("?")(search.start_reverse_incremental_search)
kb.add("enter", filter=is_searching)(search.accept_search)
kb.add("c-c")(search.abort_search)
kb.add("backspace", filter=search_buffer_is_empty)(search.abort_search)


@kb.add("n", filter=~is_searching)
def _(event):
    search_state = get_app().current_search_state
    current_buffer = get_app().current_buffer

    cursor_position = current_buffer.get_search_position(
        search_state, include_current_position=False
    )
    current_buffer.cursor_position = cursor_position

@kb.add("N", filter=~is_searching)
def _(event):
    search_state = get_app().current_search_state
    current_buffer = get_app().current_buffer

    cursor_position = current_buffer.get_search_position(
        ~search_state, include_current_position=False
    )
    current_buffer.cursor_position = cursor_position


app = Application(layout=Layout(body), key_bindings=kb, full_screen=True)

app.run()

ptkのソースのprompt_toolkit.key_binging.key_bingings.vi.load_vi_search_bindingsとか、サンプルとかがすごい参考になった

https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/prompt_toolkit/key_binding/bindings/vi.py#L1815-L1853

https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/examples/full-screen/text-editor.py#L250-L255

実装手順

SearchToolBarインスタンスつくって、BufferControlsearch_buffer_controlに作ったインスタンスcontrolを渡す。(検索ツールバーの紐付け?)

search_toolbar = SearchToolbar(vi_mode=True)
control = BufferControl(
    Buffer(document=Document(text), read_only=True),
    search_buffer_control=search_toolbar.control,
)

/で前方検索の開始

kb.add("/")(search.start_forward_incremental_search)

enterで検索実行

kb.add("enter", filter=is_searching)(search.accept_search)

nNで次の検索結果に移動

@kb.add("n", filter=~is_searching)
def _(event):
    search_state = get_app().current_search_state
    current_buffer = get_app().current_buffer

    cursor_position = current_buffer.get_search_position(
        search_state, include_current_position=False
    )
    current_buffer.cursor_position = cursor_position

@kb.add("N", filter=~is_searching)
def _(event):
    search_state = get_app().current_search_state
    current_buffer = get_app().current_buffer

    cursor_position = current_buffer.get_search_position(
        ~search_state, include_current_position=False
    )
    current_buffer.cursor_position = cursor_position

2018-11-16 00:21:49 編集

current_buffer = get_app().current_bufferにすることで、カレントバッファで検索結果の移動ができるようになる

これで一通りの検索ができるようになった!

実装するときにつまづいたこと

次の検索結果への移動の実装方法がわからなかった

これは、サンプルのtext_editorを見たら書いてあったから、参考にした

https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/examples/full-screen/text-editor.py#L250-L255

def do_find_next():
    search_state = get_app().current_search_state

    cursor_position = text_field.buffer.get_search_position(
        search_state, include_current_position=False)
    text_field.buffer.cursor_position = cursor_position

search_stateを反転させれば、逆に検索もできることをどこかで知って、それも使った。

filters.is_searchingがなんなのかよくわからなかった

いろいろ調べた結果、検索中で、検索対象のコントロールがカレントコントロールの場合、Trueになるってことがわかった

prompt_toolkit.filters.app.is_searchingに以下のように書いてあった

@Condition
def is_searching():
    " When we are searching. "
    app = get_app()
    return app.layout.is_searching

prompt_toolkit.layout.layout.Layout.is_searchingを見てみる

    @property
    def is_searching(self):
        " True if we are searching right now. "
        return self.current_control in self.search_links

prompt_toolkit.layout.layout.Layout.search_linksとは

class Layout(object):
    def __init__(self, container, focused_element=None):
        ...
        # Map search BufferControl back to the original BufferControl.
        # This is used to keep track of when exactly we are searching, and for
        # applying the search.
        # When a link exists in this dictionary, that means the search is
        # currently active.
        self.search_links = {}  # search_buffer_control -> original buffer control.

Map Search BufferControlを元のBufferControlに戻します。 これは、正確にいつ検索しているかを追跡し、検索を適用するために使用されます。 この辞書にリンクが存在する場合、検索が現在アクティブであることを意味します。

検索している時には、get_app().layout.search_linksに検索対象のBufferControlが格納されるから、is_searchingではinで調べる

search_linksを調べてみた

こんな感じのdictになっている

  • Key: SearchBufferControlで、検索文字入力用のSearchBufferControl
  • Value: BufferControlで、検索対象のBufferControl

検索文字列入力中は、current_controlSearchBufferControlになる。search_links[current_control]とすると、それに紐づく検索対象のBufferControlが返される

そのため、is_searchingは、検索文字列を入力しているかどうかということ。(検索ツールバーが表示されているかどうか)

nNが検索文字列入力中に打てなくなってしまった

@kb.add('n')みたいに書いちゃうと、検索するときに、nが打てなくなってしまった。。。そのため、以下のようにする

@kb.add('n', filter=~is_searching)
@kb.add('N', filter=~is_searching)

こうすることで、検索文字を入力していないときのみ、nNのKeyBindingが有効になる

インクリメンタル検索を実装する

検索文字入力中にもハイライト(インクリメンタル検索, incremental search)したかったから、やってみた

from prompt_toolkit.application import Application
from prompt_toolkit.application.current import get_app
from prompt_toolkit.buffer import Buffer
from prompt_toolkit.document import Document
from prompt_toolkit.filters import Condition, is_searching
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.key_binding.bindings import search
from prompt_toolkit.layout.containers import HSplit, Window
from prompt_toolkit.layout.controls import BufferControl
from prompt_toolkit.layout.layout import Layout
from prompt_toolkit.styles import Style
from prompt_toolkit.widgets.toolbars import SearchToolbar
from prompt_toolkit.layout.processors import (
    ConditionalProcessor,
    DisplayMultipleCursors,
    HighlightIncrementalSearchProcessor,
    HighlightSearchProcessor,
    HighlightSelectionProcessor,
)

text = "\n".join([str(i) for i in range(100)])

all_input_processors = [
    # 検索モードではないときだけハイライト
    ConditionalProcessor(HighlightSearchProcessor(), ~is_searching),
    HighlightIncrementalSearchProcessor(),
    HighlightSelectionProcessor(),
    DisplayMultipleCursors(),
]

# vi_mode=Trueとすると`/`と`?`で表示される様になる
search_toolbar = SearchToolbar(vi_mode=True)
control = BufferControl(
    Buffer(document=Document(text), read_only=True),
    search_buffer_control=search_toolbar.control,
    preview_search=True,
    include_default_input_processors=False,
    input_processors=all_input_processors,
)


# ウィンドウ
body = HSplit([Window(control), search_toolbar])

# キーバインディング
kb = KeyBindings()


@kb.add("q")
def _(event):
    event.app.exit()


@Condition
def search_buffer_is_empty():
    " Returns True when the search buffer is empty. "
    return get_app().current_buffer.text == ""


kb.add("/")(search.start_forward_incremental_search)
kb.add("?")(search.start_reverse_incremental_search)
kb.add("enter", filter=is_searching)(search.accept_search)
kb.add("c-c")(search.abort_search)
kb.add("backspace", filter=search_buffer_is_empty)(search.abort_search)


@kb.add("n", filter=~is_searching)
def _(event):
    search_state = get_app().current_search_state
    current_buffer = get_app().current_buffer

    cursor_position = current_buffer.get_search_position(
        search_state, include_current_position=False
    )
    current_buffer.cursor_position = cursor_position

@kb.add("N", filter=~is_searching)
def _(event):
    search_state = get_app().current_search_state
    current_buffer = get_app().current_buffer

    cursor_position = current_buffer.get_search_position(
        ~search_state, include_current_position=False
    )
    current_buffer.cursor_position = cursor_position


style = Style([("incsearch", "fg:ansibrightyellow reverse")])

app = Application(layout=Layout(body), key_bindings=kb, full_screen=True, style=style)

app.run()

シンプルな検索との違いは

  • Processorのリストを作っている
  • BufferControlのコンストラクタへの引数を追加
  • IncSearch用のスタイルを用意

Processorのリストを作る

all_input_processors = [
    # 検索モードではないときだけハイライト
    ConditionalProcessor(HighlightSearchProcessor(), ~is_searching),
    HighlightIncrementalSearchProcessor(),
    HighlightSelectionProcessor(),
    DisplayMultipleCursors(),
]

何も指定しなくても、デフォルトでこの4つは生成されるが、HighlightSearchProcessorが、デフォルトのままだと検索文字列入力中にもハイライトされてしまうため、(1回目の検索結果が2回目のIncSearchのハイライトの邪魔になる)ConditionalProcessorで検索中はハイライトしないようにした

BufferControlのコンストラクタへの引数を追加

以下の3つを追加した

  • preview_search=True
    • IncSearchの有効化
  • include_default_input_processors=False
    • input_proecssorsで渡したPrcessorのみを有効にしたいため、False
  • input_processors=all_input_processors
    • 適用するProcessorのリストを渡す

IncSearch用のスタイルを用意

style = Style([("incsearch", "fg:ansibrightyellow reverse")])

IncSearch中には、styleincsearchというclassがつくため、それ用のスタイルを定義して、Applicationに渡しておく。

ドキュメントに書いてあった

https://python-prompt-toolkit.readthedocs.io/en/stable/pages/reference.html#prompt_toolkit.layout.processors.HighlightIncrementalSearchProcessor

増分検索を強調表示するために使用される検索条件を強調表示します。 スタイルクラス 'incsearch'がコンテンツに適用されます。

重要:これは、BufferControlにpreview_search = Trueフラグを設定する必要があります。 そうしないと、検索中にカーソル位置が検索一致に設定されず、何も起こりません。

実装してみて

ドキュメントとソースをたくさん読んでて、少しずつわかっていくのがなんか楽しかった。あと、動いたときの嬉しさ半端ない

ディレクトリパスをエイリアスで登録して簡単に移動できるgotoコマンドを使ってみる

ディレクトリのパスをエイリアスとして登録して簡単に移動できるgotoっていうコマンドを見つけたから使い方のメモ

github.com

インストール

$ mkdir -p ~/.bash
$ wget https://raw.githubusercontent.com/iridakos/goto/master/goto.sh -O ~/.bash/goto.sh

.bashrcに以下を追記する

source ~/.bash/goto.sh

読み込んで

$ source ~/.bashrc

使ってみる

$ goto

usage: goto [<option>] <alias> [<directory>]

default usage:
  goto <alias> - changes to the directory registered for the given alias

  OPTIONS:
    -r, --register: registers an alias
      goto -r|--register <alias> <directory>
    -u, --unregister: unregisters an alias
      goto -u|--unregister <alias>
    -p, --push: pushes the current directory onto the stack, then performs goto
      goto -p|--push <alias>
    -o, --pop: pops the top directory from the stack, then changes to that directory
      goto -o|--pop
    -l, --list: lists aliases
      goto -l|--list
    -x, --expand: expands an alias
      goto -x|--expand <alias>
    -c, --cleanup: cleans up non existent directory aliases
      goto -c|--cleanup
    -h, --help: prints this help
      goto -h|--help
    -v, --version: displays the version of the goto script
      goto -v|--version

使い方

移動

goto <alias>

また、Tabで補完できる

エイリアス登録(-r)

-r --register

goto -r <alias> <directory>

例)~/src/pythonpythonとしてエイリアス登録

$ goto -r python ~/src/python

エイリアス登録を解除(-u)

-u --unregisters

goto -u <alias>

例)エイリアスpythonの登録を解除

$ goto -u python

カレントディレクトリをスタックにpushし、goto(-p)

-p --push

goto -p <alias>

カレントディレクトリに戻ってきたいときとか使えそう

例)カレントディレクトリをスタックに追加してから、pythonに移動

$ pwd
/Users/tamago324/dotfiles/

$ goto -p python

スタックからpopし、移動(-o)

-o --pop

goto -o

-pでpushされたスタックからpopし、移動

例)/Users/tamago324/dotfiles/goto -p xxxとしていた場合

$ goto -o

$ pwd
/Users/tamago324/dotfiles/

スタックに追加していたため、戻れる

エイリアスの一覧(-l)

-l --list

goto -l

エイリアスの完全パスを取得(-x)

-x --expand

goto -x <alias>

存在しないパスのエイリアスを削除(-c)

-c --cleanup

goto -c

なくなったディレクトリパスのエイリアスを削除してくれる

参考文献

指定フォルダ以下のファイルをコピーする - Python

指定のフォルダの下にあるファイルをコピー

再帰的に見ていく

再帰的にファイルを見るのにpathlib.Path.glob()を使い、ファイルをコピーするのにshutil.copy()を使う

例)C:\sample以下のファイルで、ファイル名に"a"が含まれているファイルをカレントディレクトリにコピーする

>>> from pathlib import Path
>>> p = Path(r"C:\sample")
WindowsPath('C:/sample')
>>> for f in p.glob("**/*a*):
...     shutil.copy(f.absolute(), "./")

参考文献

nonlocal ネストした関数から変数にアクセスする - Python

ネストした関数で、上で定義された変数を使うにはnonlocalキーワードを使う

def main():
    a = 1

    def child():
        nonlocal a
        a += 1
        print(a)

    print(a)
    child()
    print(a)

main()

出力結果

1
2
2

ネストした関数から、アクセスできた!!

これは、メモ化のための実装方法らしい。クロージャというやつ
メモ化ってどっかで聞いたことある。
たしか、同じ引数だったら、前回の結果をそのまま返すやつだっけ

クロージャについてはこんどちゃんとやる。こんど。うん。

参考文献