Giter VIP home page Giter VIP logo

cargo-snippet's Introduction

cargo-snippet

crates.io Build Status dependency status

A snippet extractor for competitive programmers.

This allows you to manage your code snippets with tests and benchmarks available !!

Installing

You need to install rustfmt to run cargo-snippet.

$ rustup component add rustfmt

Install cargo-snippet

$ cargo install cargo-snippet --features="binaries"

Usage

Create a project for snippet.

$ cargo new --lib mysnippet

Add dependencies to Cargo.toml.

[dependencies]
cargo-snippet = "0.6"

Note: cargo-snippet on dependencies is needed just for register #[snippet] attribute to prevent the error from the compiler. All logics that extract snippet is in the binary package which is installed by Installing section.

Then write some snippet codes and tests.

use cargo_snippet::snippet;

// Annotate snippet name
#[snippet("mymath")]
#[snippet("gcd")]
fn gcd(a: u64, b: u64) -> u64 {
    if b == 0 {
        a
    } else {
        gcd(b, a % b)
    }
}

// Also works
#[snippet(name = "mymath")]
// Equivalent to #[snippet("lcm")]
#[snippet]
fn lcm(a: u64, b: u64) -> u64 {
    a / gcd(a, b) * b
}

#[snippet]
// Include snippet
#[snippet(include = "gcd")]
fn gcd_list(list: &[u64]) -> u64 {
    list.iter().fold(list[0], |a, &b| gcd(a, b))
}

// You can set prefix string.
// Note: All codes will be formatted by rustfmt on output
#[snippet(prefix = "use std::io::{self,Read};")]
#[snippet(prefix = "use std::str::FromStr;")]
fn foo() {}

// By default, doc comments associated with items will be output with the snippet.
#[snippet]
/// This is a document!
fn documented() {
    //! Inner document also works.
}

// If you want doc comment to be hidden, append `doc_hidden` keyword.
#[snippet(doc_hidden, prefix = "use std::collections::HashMap;")]
/// This is a doc comment for `bar`.
/// Since `doc_hidden` is specified, it won't be present in the snippet.
fn bar() {
    //! And this is also a doc comment for `bar`, which will be removed.
}

#[test]
fn test_gcd() {
    assert_eq!(gcd(57, 3), 3);
}

#[test]
fn test_lcm() {
    assert_eq!(lcm(3, 19), 57);
}

You can test as always:

$ cargo test

Extract snippet !

$ cargo snippet
snippet foo
    use std::io::{self, Read};
    use std::str::FromStr;
    fn foo() {}

snippet documented
    /// This is a document!
    fn documented() {
        //! Inner document also works.
    }

snippet bar
    use std::collections::HashMap;
    fn bar() {}

snippet gcd
    fn gcd(a: u64, b: u64) -> u64 {
        if b == 0 {
            a
        } else {
            gcd(b, a % b)
        }
    }

snippet gcd_list
    fn gcd(a: u64, b: u64) -> u64 {
        if b == 0 {
            a
        } else {
            gcd(b, a % b)
        }
    }
    fn gcd_list(list: &[u64]) -> u64 {
        list.iter().fold(list[0], |a, &b| gcd(a, b))
    }

snippet lcm
    fn lcm(a: u64, b: u64) -> u64 {
        a / gcd(a, b) * b
    }

snippet mymath
    fn gcd(a: u64, b: u64) -> u64 {
        if b == 0 {
            a
        } else {
            gcd(b, a % b)
        }
    }
    fn lcm(a: u64, b: u64) -> u64 {
        a / gcd(a, b) * b
    }

Example

My snippets here.

Supported output format

  • Neosnippet
  • VScode
  • Ultisnips

You can specify output format via -t option. See cargo snippet -h.

cargo-snippet's People

Contributors

akiradeveloper avatar hatoo avatar magurotuna avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

cargo-snippet's Issues

Backslash on doc comment is wrongly escaped

This test fails.

    #[test]
    fn test_outer_line_doc_in_file_special_character() {
        let src = r#"
            #![snippet("file")]
            /// ///\\\ This is outer doc comment.
            fn foo() {}
        "#;

        let snip = snippets(&src);
        dbg!(&snip);
        assert_eq!(
            format_src(snip["file"].as_str()).unwrap(),
            format_src(
                r#"/// ///\\\ This is outer doc comment.
            fn foo() {}"#
            )
            .unwrap(),
        );
    }

This issue is critical for users who want to embed Ascii Art for a snippet 😄 .

Fix warning: use of deprecated item 'rustc_plugin': import this through rustc_driver::p lugin instead to make TLS work correctly

warning: use of deprecated item 'rustc_plugin': import this through rustc_driver::p lugin instead to make TLS work correctly. See https://github.com/rust-lang/rust/iss ues/62717
--> src/lib.rs:4:1 | 4 | extern crate rustc_plugin; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: #[warn(deprecated)] on by default
warning: use of deprecated item 'rustc_plugin': import this through rustc_driver::p lugin instead to make TLS work correctly. See https://github.com/rust-lang/rust/iss ues/62717
--> src/lib.rs:4:1 | 4 | extern crate rustc_plugin; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: #[warn(deprecated)] on by default

Snippetの依存ライブラリが指定できない

例えばlockを用いた高速なScannerをスニペットに登録する際に、structそのものの登録は行えても、
スニペット貼り付けのたびに依存するライブラリであるstd::io::Read, std::str::FromStrなどを記載する必要があり、少々手間がかかってしまいます。
アトリビュートにuse,libなどを追加してそのスニペットが依存しているライブラリ(もしくは単純に文字列でも)を登録可能にはできないでしょうか?

docアトリビュートとgrepの組み合わせで似たようなことができないか試しているのですが、rust-docのtest部分のuseと被って抽出が上手くいかないのです。

division by a dereferenced value causes rustfmt error

Consider the following example:

use cargo_snippet::snippet;

#[snippet]
fn foo(a: &i32, b: &i32) -> i32 {
    assert_ne!(*b, 0);
    *a / *b
}

This example has the correct syntax. Actually, the playground works well.
But when processed by cargo-snippet, it generates some error.

To look into the errors, I added log::error! calls in checking the result of rustfmt to writer.rs.

if !out.status.success() {
    log::error!("rustfmt returns non-zero status");
    log::error!("[stdout]\n{}", String::from_utf8_lossy(&out.stdout));
    log::error!("[stderr]\n{}", String::from_utf8_lossy(&out.stderr));
    return None;
}

The details of rustfmt error are:

[2020-05-31T10:28:10Z ERROR cargo_snippet::writer] rustfmt returns non-zero status
[2020-05-31T10:28:10Z ERROR cargo_snippet::writer] [stdout]

[2020-05-31T10:28:10Z ERROR cargo_snippet::writer] [stderr]
    error: unterminated block comment
     --> <stdin>:1:62
      |
    1 | fn foo (a :&i32 ,b :&i32 ) ->i32 {assert_ne !(*b ,0 ) ;*a /*b }
      |                                                          ^^^^

It looks like rustfmt receives /*b, and it is interpreted as the beginning of block comment.
To avoid this error, we need to make the dereferenced value wrapped by parentheses.

use cargo_snippet::snippet;

#[snippet]
fn foo(a: &i32, b: &i32) -> i32 {
    assert_ne!(*b, 0);
    *a / (*b) // wrap by parens
}

This way seems a kind of tricky, so I'm wondering we can solve it by fixing cargo-snippet.

Feature request: hidden doc comments

Currently, cargo-snippet's output includes doc comments in all cases.
This is surely a good feature for some users, but there may be other users who want doc comments to be removed from output because of verboseness.

Therefore, it would be nice if we introduce a new syntax like this:

/// many
/// doc
/// comments
#[snippet(doc_hidden)]
fn foo() {
    // omitted
}

and when doc_hidden is applied, cargo-snippet doesn't output doc comments.

What do you think about this @hatoo? If there's no problem, I'll implement it this weekend.

VSCodeのスニペットでマクロの変数がプレースホルダーとして扱われる

VSCodeでスニペットを呼び出す際,$aなどのマクロの変数がプレースホルダーとして扱われてしまい,$が消えてしまいます.
\\$aのように\\を前につけたところ,$aはそのまま出力されるようでした.
そのため,例えばVSCodeのスニペットを出力する際に,マクロの定義であれば$を\\$に変換するなどの修正を検討していただけないでしょうか.

All doc comment is converted to #[doc = " ..."]

#[snippet]
/// Some comment
fn foo() {}

run $cargo snippet

snippet foo
    #[doc = " Some comment"]
    fn foo() {}

Since almost always, we don't use #[doc = " ..."].
So it's justifiable that emit doc comment as /// instead #[doc] always.

I feel it's good even if this is implemented by text processing.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.