30 releases

0.3.5 Sep 4, 2022
0.3.4 Aug 30, 2022
0.2.31 Aug 11, 2022
0.2.28 May 30, 2022
0.1.4 Mar 13, 2022

#36 in #assignment

Download history 11/week @ 2024-02-25 11/week @ 2024-03-10 379/week @ 2024-03-31

390 downloads per month
Used in weblab

MIT license

48KB
1.5K SLoC

Weblab

Docs.rs Crates.io Github Workflows

Installation

Just add the following line to your Cargo.toml

weblab = "<replace with current version>"

Project structure

With weblab-rs you can make 3 kinds of assignments. Open-answer, multiple choice and programming exercises. The last needs the most explanation. A programming question is a single file with the following structure:

use weblab::weblab;

#[weblab(programming_assignment)]
/// This is an example assignment. This text will become the assignment text.
/// Note that the text in this comment starts with *three* slashes. That makes
/// it a special "doc comment".
/// # You can use markdown here. Most editors (like clion) even shows it.
/// The markdown will also show on weblab.
///
/// The assignment here is: return the word "main"!
#[weblab(title = "test")] // otherwise the module name is used
mod assignment {
    #[weblab(solution)]
    mod solution {
        // In this module, the solution of your assignment goes.
        // Parts of the solution may be marked with template_only!{}
        // or solution_only!{}. If this is the case, those parts
        // will be added or removed only for the template version.
        // Like that you can reuse part of the solution as the template
        // of the assignment

        // It is recommended to put a function here in which the student's
        // code goes. However, a solution may also contain only types, or
        // any other rust structure you like.

        // note that you may get unused import warnings on template_only.
        // template_only is removed from the source code by the ecnlosing
        // attribute macros (that's how it works). This means that technically
        // it's never used. You don't even need to import it! However, for
        // syntax highlighting it may be useful to import it anyway.
        #[allow(unused_imports)]
        use weblab::{solution_only, template_only};

        pub fn main() -> &'static str {
            solution_only!{
                "main"
            }
            template_only!{
                todo!()
            }
        }
    }

    #[weblab(test)]
    mod test {
        // in this section, tests can be put.
        // imports (any import for that matter, also from the library)
        // need to be prefixed with `super`. This works both for the
        // offline project, and in the generated weblab assignment.
        // NOTE: crate-relative imports may work offline, but will *not*
        // work when the assignment is generated on weblab, since each
        // assignment will be put in its own, sepsarate module structure.
        // In tests, `template_only!{}` and `solution_only!{}` also work.

        use super::solution;

        // Tests are marked with the standard rust test annotation.
        // To try out the spec tests locally, simply run `cargo test`.
        // The code will be automatically configured such that the
        // solution will be equal to the reference solution, and the tests
        // will verify the reference solution.
        #[test]
        fn test() {
            assert_eq!(solution::main(), "main");
        }
    }

    // The library is optional.
    #[weblab(library)]
    mod library {}

    // optionally, if the solution template and reference solution are
    // very different, you may choose to add another module:
    // ```
    // #[weblab(solution_template)]
    // mod solution_template {}
    // ```
    //
    // You can do the same for tests:
    //
    // ```
    // #[weblab(test_template)]
    // mod test_template {}
    // ```
}


To generate weblab assignments (in uploadable zip form) from this structure from this, make the root of the project a main.rs file similar to this:

use weblab::weblab_main;

weblab_folder! {
    // assignments
    ...
}

fn main() {
    // weblab_main takes one parameter, which is the root of the project. 
    // usually this module contains a weblab_folder!{} invocation. 
    weblab_main!(self);
}

assignment generation

This adds a command line interface to your project, which you can now use to interact with the generation code. The following commands are some of what's available:

cargo run -- generate folder
cargo run -- generate zip
cargo run -- generate zip output.zip
cargo run -- generate zip output.zip --name='some_assignment'
cargo run -- generate folder --name='some_assigment'
cargo run -- generate folder output --module='some::path::to::an::assignment'

# for all commands
cargo run -- --help 

# always available, simply runs the spectests
cargo test

Folders

To generate weblab folders, you can use the weblab_folder macro

use weblab::weblab_folder;

weblab_folder! {
    "test", // always a name first. Can be any string

    // then some module names in which the assignment can be found
    // note that the modules refer to the enclosing sope, in which
    // the label #[weblab(programming_assignment)] is put. Not the
    // module the annotation is put on. So the module `assignment`
    // contains something like this:
    // ```
    // #[weblab(programming_assignment)]
    // mod assignment {
    //  ... // contents
    // }
    // ```
    assignment, 
    assignment2,
}

Open questions

Examples

For an example module layout, look in example-project

Dependencies

~1.4–2MB
~47K SLoC