Search Results

Blog


    cargo-generateを使ってrustプロジェクトを作る方法

    2023-08-28

    Rust開発者たちは新しいプロジェクトを作成するたびに、同じ設定を手動で何度も行う必要があるかもしてません。これは大変ですから、今日はcargo-generateでテンプレートレポジトリの作り方を紹介したいと思います。完成したテンプレートプロジェクトに興味がある方は、こちらをご覧ください。

    ☆では、始めましょう☆。

    まずcargoで新しいプロジェクトを作成します。

    mkdir rust_template
    cd rust_template
    cargo init
    

    テンプレートから新しいプロジェクトを作成する時に、リモートgitリポジトリを持っていると便利です。そのため、リモートリポジトリ(githubやgitlabなど)にプッシュすることをおすすめします。

    フォーマッター

    コッドフォーマッターとは、ホワイトスペースやインポット順序を自動的に修正するプログラムです。 Rustの場合はrustfmtを使用ます。

    rustfmt.tomlファイルでrustfmtを設定することができます。 自分のお好みに合わせて設定してください。全ての設定についてはこちらをご覧ください。

    私が使用した設定を説明します。group_importsとは同じクレートからのインポットをぐループ化するものことです。

    次はuse_field_init_shorthandをtrueに設定すると、ストラクトを初期化する時に、ストラクトのフィールドとバリアバル名が同じ場合、フィールド名を略します。

    group_imports = "StdExternalCrate"
    imports_layout = "Mixed"
    imports_granularity = "Crate"
    match_block_trailing_comma = true
    trailing_semicolon = true
    use_field_init_shorthand = true
    

    リンター

    次、リンターの機能についてを説明します。プログラムが問題なくコンパイルできても、バッグがなくても、コッドがより習慣的に記述されることがあります。この場合、リンターは通知だけではなく、コッドは自動的に修正することもできます。Rustエコシステムにはclippyというリンターを使用します。

    rustfmtと同じように、コンフィグファイルで設定することができます。個人的にはデフォルトのままにします。

    コマンドランナー justfile

    現在、開発者たちはmakefileがコマンドランナーとして使っています。たとえば

    
    .PHONY: debug check fmt lint
    
    debug:
        cargo run
    
    check:
        cargo check --workspace
    
    fmt:
        cargo +nightly fmt --all
    
    lint:
        cargo clippy -- -W clippy::unwrap_used -W clippy::cargo
    
    

    makefileは非常に複雑なビルドシステムです。そのため全く使わない機能やルールが数多く存在します。さらに、システムによってはmakefileのルールが異なるため、コマンドの実行が誤って行われることがあります(gmakemakeの違いについてははこちらをご覧ください)。これはかなり大変ですね。

    justfileを紹介したいと思います。justfileのシンタックスはmakefileに似てるけど、あくまでもjustfileはただのコマンドランナーです。 このまえのmakefileの内容をjustfileで書かれたらこうなります。

    
    debug:
        cargo run
    
    check:
        cargo check --workspace
    
    fmt:
        cargo +nightly fmt --all
    
    lint:
        cargo clippy -- -W clippy::unwrap_used -W clippy::cargo
    
    

    gitフック

    この前紹介したフォーマッターとリンターは便利ですが、通常、コマンドラインから手動で呼び出す必要があります。実際、フォーマッタとリンターを呼び出す一番適当なタイミングははコミットする際です。ファイルを保存するときにもそうですが、これが少し邪魔かもしれません。保存ときにコマンドを自動的に実行する方法は、使用しているテキストエディタによって変わりますから自分のエディタに合った方法を検索してみてください。

    それでは、gitフックについてご紹介しましょう。gitリポジトリでは、特定のエベントが発生した場合(例えば、コミットやプッシュときなど)、スクリプトを実行することの機能が提供されています。.git/hooksディレクトリには、利用可能なフックが格納されていますので、自分で確認してみてください。このディレクトリには.sampleという拡張子のついた実行可能ファイルが含まれていますが、現状では実行されません。ファイル拡張子を取り除いた場合に実行できるようになります。

    カスタムフックを作成する前に、プロジェクトのルートでdev/scriptsディレクトリを作成しましょう。これは.git/hookディレクトリがバージョン管理に含まらないため、他の開発者がフックを手動でコピーする必要があります。justfileにはこのコマンドを追加しましょう。

    devsetup:
        cp dev/hooks/* .git/hooks
    

    これで、プロジェクトをクローンしたあと、このコマンドを実行するこどでフックをインストールできます。

    さて、カスタムコミットフックを紹介します。

    #!/bin/sh
    
    BOLD='\033[1;36m'
    NC='\033[0m'
    
    # フォーマッター
    printf "${BOLD}[PRE-COMMIT]${NC} formatting code...\n"
    cargo +nightly fmt --all
    git add -u
    
    # リンター
    printf "${BOLD}[PRE-COMMIT]${NC} linting...\n"
    cargo clippy
    

    cargo fmtコマンドには+nightlyフラグが付けている理由は、この前rustfmt.tomlにベータフォーマッター機能が設定されたためです。また、フォーマッターコマンドの後に、git add -uが実行しない場合、現在のコミットにはフォーマッターによる変更が含まれないことに注意してください。

    cargo-generate

    まずcargo-generateをインストールします。おそらくすこし時間がかかります。

    cargo install cargo-generate
    

    cargo-generateはテクストテンプレート化の機能があります。プロジェクトがテンプレートから作成する時にプレースホルダは組み込みの変数の値で置き換えられます。以下はクレート名によってCargo.tomlで設定する例です。

    [package]
    name = "{{crate_name}}"
    version = "0.1.0"
    edition = "2021"
    license = "MIT OR Apache-2.0"
    authors = ["{{authors}}"]
    description = ""
    repository = ""
    

    Cargo.tomlに限らわず、どこでもこのプレースホルダ文法が使用できます。ぜひ自分に合わせる設定してみてください!

    新しいプロジェクトを作成したい場合、このコマンドを実行します。

    cargo generate --git <git-url> -f --name <プロジェクト名>
    

    <git-url>はテンプレートのリモートレポジトリのURLです。代わりに--gitフラグではなく--pathフラグでローカルファイルシステムからテンプレートレポジトリを使用できます(詳細についてcargo-generateのマニュアルを読んでみてください)。

    では、以上になります!読んでいただきありがとうございました!

    Switching back from Emacs to Neovim

    2023-03-13

    I started off as a vim cultist and used it for practically everything. At the time I was primarily doing C development on my own small codebases. However, after needing to do development on larger typescript codebases for work, my needs got to be more complex. The biggest thing missing for me was a LSP. For this reason, I started using neovim as my IDE and gradually shifted over for all software related tasks. I still occasionally used vim for simple text editing.

    At a certain point, I was just bored and decided to give emacs a shot. It has a lot of great defaults and feels pleasant to use after getting evil mode and my own vim bindings configured. I also really enjoyed some of the emacs plugins, especially org-tree-slide, it made giving presentations awesome and I used it for my rust workshop.

    However, I did not like a lot about my emacs experience:

    • Performance: felt very sluggish compared to vim/nvim
    • LSPs constant crashing: when working with rust projects, rust analyzer would constantly crash and ask to be restarted, making for a painful experience
    • Buffer switching keeps showing random buffers I did not open myself like *scratch*, *straight-process* and a billion others, tried a bunch of stuff to fix this
    • Clipboard pasting is slow and blocks
    • Emacs takes a while to start up
    • Haven't found nice way to reload init.el when I make a change, makes prototyping/experimenting with options more difficult
    • The last straw was when emacs started terminating for no reason whatsoever

    In general, my todo list of emacs improvements involves fixes with the editor rather than further advancements and features I could be adding to my workflow. In the end, it feels more like I was fighting the editor, this may just be perhaps that I come from vim and expect emacs to behave more like vim.

    Overall I'm really impressed by a lot of the things emacs is capable of but for now I just want a fast and productive IDE to write software with. I'm too lazy to keep fighting emacs - although I'm sure it's a great editor if I learned how to use it properly. I'll come back one day...

    Yet another blog rewrite

    2023-02-26

    fn main() {
        println!("hello world");
    }
    

    So somehow I have managed to rewrite my blog once again. This time we are using zola, which is a static site generator written in rust. It's pretty nice since you can do everything in markdown and it comes with a bunch of features like search index, syntax highlighting etc. I have finally caved in and decided to use modern technologies for once instead of the insanity of what I was working with before.

    First blog was a very long time ago when I wanted to learn django. This was unfinished so it doesn't really count.

    Next is this shell script that tacks on new blog posts to an existing file. It worked okay but got annoying when I wanted to change up the format of the blog pages or wanted to edit stuff. It was a reasonable project since I was learning shell scripting. I actually made a decent couple posts using this blog system.

    After this was when I became mentally ill. Here is a makefile based blog script that is more or less finished. It started off quite elegant with me using envsubst to do variable substitutions in md files as templating. It then spiraled into me trying to write a templating engine in makefile complete with a md to html generator written in sed. Honestly if I polished up this project and finished the sed script it could be a pretty decent and lightweight static blog generator.

    Needless to say, I got a bit tired of writing shell scripts for my blogs and just wanted something that works and has all the features I wanted. So that's why I'm using a prebuild tool for once. Perhaps if I get bored I'll write another blog script but we shall see 😋.