├── .git-blame-ignore-revs ├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ ├── mean_bean_ci.yml │ ├── mean_bean_deploy.yml │ ├── publish_image.yaml │ └── release-plz.yaml ├── .gitignore ├── .mailmap ├── .tokeignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── Earthfile ├── LICENCE-APACHE ├── LICENCE-MIT ├── README.md ├── benchmark.sh ├── build.rs ├── ci ├── build.bash ├── common.bash ├── set_rust_version.bash └── test.bash ├── fuzz ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md └── fuzz_targets │ ├── parse_from_slice.rs │ ├── parse_from_slice_panic.rs │ └── parse_from_slice_total.rs ├── languages.json ├── src ├── cli.rs ├── cli_utils.rs ├── config.rs ├── consts.rs ├── input.rs ├── language │ ├── embedding.rs │ ├── language_type.rs │ ├── language_type.tera.rs │ ├── languages.rs │ ├── mod.rs │ └── syntax.rs ├── lib.rs ├── main.rs ├── sort.rs ├── stats.rs └── utils │ ├── ext.rs │ ├── fs.rs │ ├── macros.rs │ └── mod.rs ├── tests ├── accuracy.rs ├── data │ ├── Daml.daml │ ├── Dockerfile │ ├── MSBuild.csproj │ ├── Makefile │ ├── Modelica.mo │ ├── NuGet.Config │ ├── PKGBUILD │ ├── Rakefile │ ├── SConstruct │ ├── Snakefile │ ├── Tera.tera │ ├── abnf.abnf │ ├── alloy.als │ ├── apl.apl │ ├── arduino.ino │ ├── arturo.art │ ├── asciidoc.adoc │ ├── asn1.asn1 │ ├── ats.dats │ ├── awk.awk │ ├── ballerina.bal │ ├── bazel.bzl │ ├── bean.bean │ ├── bicep.bicep │ ├── bitbake.bb │ ├── bqn.bqn │ ├── brightscript.brs │ ├── c.c │ ├── cairo.cairo │ ├── cangjie.cj │ ├── chapel.chpl │ ├── cil.cil │ ├── circom.circom │ ├── clojure.clj │ ├── clojurec.cljc │ ├── clojurescript.cljs │ ├── cmake.cmake │ ├── codeql.ql │ ├── cogent.cogent │ ├── cpp.cpp │ ├── crystal.cr │ ├── csharp.cs │ ├── cuda.cu │ ├── cue.cue │ ├── cython.pyx │ ├── d.d │ ├── d2.d2 │ ├── dhall.dhall │ ├── dreammaker.dm │ ├── dust.dust │ ├── ebuild.ebuild │ ├── edgeql.edgeql │ ├── edn.edn │ ├── eight.8th │ ├── elvish.elv │ ├── emacs_dev_env.ede │ ├── emacs_lisp.el │ ├── emojicode.🍇 │ ├── esdl.esdl │ ├── example.umpl │ ├── factor.factor │ ├── fennel.fnl │ ├── flatbuffers.fbs │ ├── forgecfg.cfg │ ├── fsharp.fs │ ├── fstar.fst │ ├── ftl.ftl │ ├── futhark.fut │ ├── gas.S │ ├── gdb.gdb │ ├── gdshader.gdshader │ ├── gherkin.feature │ ├── gleam.gleam │ ├── glimmer_js.gjs │ ├── glimmer_ts.gts │ ├── gml.gml │ ├── go.go │ ├── gohtml.gohtml │ ├── graphql.gql │ ├── gwion.gw │ ├── haml.haml │ ├── hcl.tf │ ├── headache.ha │ ├── hicad.mac │ ├── hledger.hledger │ ├── hpp.hpp │ ├── html.html │ ├── janet.janet │ ├── java.java │ ├── javascript.js │ ├── jinja2.j2 │ ├── jq.jq │ ├── jslt.jslt │ ├── jsonnet.jsonnet │ ├── jupyter.ipynb │ ├── justfile │ ├── k.k │ ├── kakoune_script.kak │ ├── ksh.ksh │ ├── kvlanguage.kv │ ├── lalrpop.lalrpop │ ├── linguafranca.lf │ ├── liquid.liquid │ ├── livescript.ls │ ├── llvm.ll │ ├── logtalk.lgt │ ├── lolcode.lol │ ├── m4.m4 │ ├── menhir.mly │ ├── meson.build │ ├── metal.metal │ ├── mlatu.mlt │ ├── moduledef.def │ ├── mojo.mojo │ ├── monkeyc.mc │ ├── nextflow.nf │ ├── nqp.nqp │ ├── odin.odin │ ├── open_policy_agent.rego │ ├── openscad.scad │ ├── opentype.fea │ ├── org_mode.org │ ├── pan.pan │ ├── pcss.pcss │ ├── pest.pest │ ├── phix.e │ ├── plantuml.puml │ ├── pofile.po │ ├── pofile_pot.pot │ ├── poke.pk │ ├── pony.pony │ ├── postcss.sss │ ├── powershell.ps1 │ ├── pug.pug │ ├── puppet.pp │ ├── pyret.arr │ ├── python.py │ ├── q.q │ ├── qml.qml │ ├── racket.rkt │ ├── raku.raku │ ├── razor.cshtml │ ├── razorcomponent.razor │ ├── redscript.reds │ ├── renpy.rpy │ ├── roc.roc │ ├── ron.ron │ ├── rpmspec.spec │ ├── ruby.rb │ ├── ruby_env │ ├── ruby_html.erb │ ├── rust.rs │ ├── scheme.scm │ ├── shaderlab.shader │ ├── slang.slang │ ├── slint.slint │ ├── solidity.sol │ ├── sql.sql │ ├── srecode.srt │ ├── stan.stan │ ├── stata.do │ ├── stratego.str │ ├── stylus.styl │ ├── svelte.svelte │ ├── swift.swift │ ├── swig.i │ ├── tact.tact │ ├── templ.templ │ ├── thrift.thrift │ ├── tsx.tsx │ ├── ttcn.ttcn3 │ ├── twig.twig │ ├── typescript.ts │ ├── typst.typ │ ├── uiua.ua │ ├── unison.u │ ├── urweb.ur │ ├── urweb_urp.urp │ ├── urweb_urs.urs │ ├── vb6_bas.bas │ ├── vb6_cls.cls │ ├── vb6_frm.frm │ ├── vbscript.vbs │ ├── velocity.vm │ ├── vhdl.vhd │ ├── visualbasic.vb │ ├── vqe.qasm │ ├── vue.vue │ ├── webassembly.wat │ ├── wenyan.wy │ ├── wgsl.wgsl │ ├── xsl.xsl │ ├── xtend.xtend │ ├── yaml.yaml │ ├── zencode.zs │ ├── zig.zig │ └── zokrates.zok └── embedding │ └── file_triggeringprincipal_frame_1.html └── tokei.example.toml /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Format JSON 2 | d7c548537cd5828b2d58e09f3207ddacc517b227 3 | f356d27ab21e0f93839da90393c0edf9225740c2 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | tests/data/* linguist-documentation 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: XAMPPRocky 4 | -------------------------------------------------------------------------------- /.github/workflows/publish_image.yaml: -------------------------------------------------------------------------------- 1 | name: Publish Docker Images 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | tags: 8 | - v* 9 | 10 | jobs: 11 | image: 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.ref }} 14 | cancel-in-progress: true 15 | runs-on: ubuntu-latest 16 | permissions: 17 | packages: write 18 | contents: read 19 | attestations: write 20 | steps: 21 | - uses: earthly/actions-setup@v1 22 | with: 23 | github-token: ${{ secrets.GITHUB_TOKEN }} 24 | - name: Check out the repo 25 | uses: actions/checkout@v4 26 | - name: Extract metadata (tags, labels) for Docker 27 | id: meta 28 | uses: docker/metadata-action@v5 29 | with: 30 | images: ghcr.io/${{ github.repository }} 31 | tags: | 32 | type=semver,pattern={{raw}} 33 | type=raw,value=latest,enable={{is_default_branch}} 34 | - name: Log in to the Container registry 35 | uses: docker/login-action@v3 36 | with: 37 | registry: ghcr.io 38 | username: ${{ github.actor }} 39 | password: ${{ secrets.GITHUB_TOKEN }} 40 | - name: Build and Push Docker Image 41 | run: echo "${{ steps.meta.outputs.tags }}" | xargs -I {} earthly --ci --push +docker --image_name="{}" 42 | -------------------------------------------------------------------------------- /.github/workflows/release-plz.yaml: -------------------------------------------------------------------------------- 1 | name: Release-plz 2 | 3 | permissions: 4 | pull-requests: write 5 | contents: write 6 | 7 | on: 8 | push: 9 | branches: 10 | - master 11 | 12 | jobs: 13 | 14 | release-plz: 15 | name: Release-plz 16 | runs-on: ubuntu-22.04 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v3 20 | with: 21 | fetch-depth: 0 22 | - name: Install Rust toolchain 23 | uses: dtolnay/rust-toolchain@stable 24 | - name: Run release-plz 25 | uses: MarcoIeni/release-plz-action@v0.5 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/rust 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=rust 3 | 4 | ### Rust ### 5 | # Generated by Cargo 6 | # will have compiled files and executables 7 | debug/ 8 | target/ 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | 16 | # End of https://www.toptal.com/developers/gitignore/api/rust 17 | 18 | 19 | ### IDE ### 20 | .vscode 21 | .idea/ 22 | *.iml 23 | 24 | ### Other ### 25 | 26 | # macOS 27 | .DS_Store 28 | 29 | # settings 30 | .settings 31 | .tokeirc 32 | 33 | # benchmark 34 | results.csv 35 | 36 | node_modules 37 | *.code-workspace 38 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Erin Power 2 | Erin Power 3 | Erin Power <4464295+XAMPPRocky@users.noreply.github.com> 4 | Erin Power 5 | -------------------------------------------------------------------------------- /.tokeignore: -------------------------------------------------------------------------------- 1 | tests/data 2 | resources 3 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at xampprocky+coc@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Erin Power "] 3 | build = "build.rs" 4 | categories = ["command-line-utilities", "development-tools", "visualization"] 5 | description = "Count your code, quickly." 6 | homepage = "https://tokei.rs" 7 | include = [ 8 | "Cargo.lock", 9 | "Cargo.toml", 10 | "LICENCE-APACHE", 11 | "LICENCE-MIT", 12 | "build.rs", 13 | "languages.json", 14 | "src/**/*", 15 | ] 16 | keywords = ["utility", "cli", "cloc", "lines", "statistics"] 17 | license = "MIT OR Apache-2.0" 18 | name = "tokei" 19 | readme = "README.md" 20 | repository = "https://github.com/XAMPPRocky/tokei.git" 21 | version = "13.0.0-alpha.8" 22 | rust-version = "1.71" 23 | edition = "2021" 24 | 25 | [features] 26 | all = ["cbor", "yaml"] 27 | cbor = ["dep:hex", "dep:serde_cbor"] 28 | default = [] 29 | yaml = ["dep:serde_yaml"] 30 | 31 | [profile.release] 32 | lto = "thin" 33 | panic = "abort" 34 | 35 | [build-dependencies] 36 | tera = "1.20.0" 37 | ignore = "0.4.22" 38 | serde_json = "1.0.125" 39 | json5 = "0.4.1" 40 | 41 | [dependencies] 42 | aho-corasick = "1.1.3" 43 | arbitrary = { version = "1.3.2", features = ["derive"] } 44 | clap = { version = "4", features = ["cargo", "string", "wrap_help"] } 45 | colored = "2.1.0" 46 | crossbeam-channel = "0.5.13" 47 | encoding_rs_io = "0.1.7" 48 | grep-searcher = "0.1.13" 49 | ignore = "0.4.22" 50 | log = "0.4.22" 51 | rayon = "1.10.0" 52 | serde = { version = "1.0.208", features = ["derive", "rc"] } 53 | term_size = "0.3.2" 54 | toml = "0.8.19" 55 | parking_lot = "0.12.3" 56 | dashmap = { version = "6.0.1", features = ["serde"] } 57 | num-format = "0.4.4" 58 | once_cell = "1.19.0" 59 | regex = "1.10.6" 60 | serde_json = "1.0.125" 61 | etcetera = "0.8.0" 62 | table_formatter = "0.6.1" 63 | 64 | [dependencies.env_logger] 65 | features = [] 66 | version = "0.11.5" 67 | 68 | [dependencies.hex] 69 | optional = true 70 | version = "0.4.3" 71 | 72 | [dependencies.serde_cbor] 73 | optional = true 74 | version = "0.11.2" 75 | 76 | [dependencies.serde_yaml] 77 | optional = true 78 | version = "0.9.34" 79 | 80 | [dev-dependencies] 81 | proptest = "1.5.0" 82 | strum = "0.26.3" 83 | strum_macros = "0.26.4" 84 | tempfile = "3.12.0" 85 | git2 = { version = "0.19.0", default-features = false, features = [] } 86 | -------------------------------------------------------------------------------- /Earthfile: -------------------------------------------------------------------------------- 1 | VERSION 0.6 2 | FROM alpine:3.19 3 | WORKDIR /src 4 | 5 | build: 6 | FROM rust:alpine3.19 7 | RUN apk update \ 8 | && apk add \ 9 | git \ 10 | gcc \ 11 | g++ \ 12 | pkgconfig 13 | 14 | COPY . /src 15 | WORKDIR /src 16 | RUN cargo build --release 17 | SAVE ARTIFACT /src/target/release/tokei AS LOCAL ./tokei 18 | 19 | docker: 20 | COPY +build/tokei /usr/local/bin/ 21 | WORKDIR /src 22 | ENTRYPOINT [ "tokei" ] 23 | CMD [ "--help" ] 24 | ARG image_name=tokei:latest 25 | SAVE IMAGE --push $image_name 26 | -------------------------------------------------------------------------------- /LICENCE-APACHE: -------------------------------------------------------------------------------- 1 | Copyright 2016 Erin Power 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /LICENCE-MIT: -------------------------------------------------------------------------------- 1 | MIT License (MIT) 2 | 3 | Copyright (c) 2016 Erin Power 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /benchmark.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | if [ "$1" = "--full" ]; then 5 | FILE=$2 6 | FULL=true 7 | else 8 | FILE=$1 9 | FULL=false 10 | fi 11 | 12 | echo 'Tokei Benchmarking Tool' 13 | 14 | if [ $FULL = true ]; then 15 | REQUIRED='cloc, tokei, loc, hyperfine, and scc' 16 | else 17 | REQUIRED='tokei, and hyperfine' 18 | fi 19 | 20 | echo "The use of this tool requires $REQUIRED to be installed and available in your PATH variable." 21 | 22 | echo 'Please enter the path you would like to benchmark:' 23 | 24 | if [ -z ${FILE+x} ]; then 25 | read -r input 26 | else 27 | input=$FILE 28 | fi 29 | 30 | hyperfine --version 31 | echo "old tokei: $(tokei --version)" 32 | 33 | if [ $FULL = true ]; then 34 | scc --version 35 | loc --version 36 | echo "cloc: $(cloc --version)" 37 | fi 38 | 39 | cargo build --release 40 | 41 | if [ $FULL = true ]; then 42 | hyperfine -w 10 --export-csv './results.csv' "target/release/tokei $input" \ 43 | "tokei $input" \ 44 | "scc $input" \ 45 | "loc $input" # \ "cloc $input" 46 | else 47 | hyperfine -w 5 "target/release/tokei $input" \ 48 | "tokei $input" 49 | fi 50 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | extern crate ignore; 2 | extern crate json5; 3 | extern crate serde_json; 4 | 5 | use std::ffi::OsStr; 6 | use std::fs; 7 | use std::path::Path; 8 | use std::{cmp, env, error}; 9 | 10 | use ignore::Walk; 11 | use serde_json::Value; 12 | 13 | fn main() -> Result<(), Box> { 14 | let out_dir = env::var_os("OUT_DIR").expect("No OUT_DIR variable."); 15 | generate_languages(&out_dir)?; 16 | generate_tests(&out_dir)?; 17 | 18 | Ok(()) 19 | } 20 | 21 | fn generate_languages(out_dir: &OsStr) -> Result<(), Box> { 22 | let mut tera = tera::Tera::default(); 23 | 24 | let json_string: String = fs::read_to_string("languages.json")?.parse()?; 25 | let mut json: Value = json5::from_str(&json_string)?; 26 | 27 | for (_key, ref mut item) in json 28 | .get_mut("languages") 29 | .unwrap() 30 | .as_object_mut() 31 | .unwrap() 32 | .iter_mut() 33 | { 34 | macro_rules! sort_prop { 35 | ($prop:expr) => {{ 36 | if let Some(ref mut prop) = item.get_mut($prop) { 37 | prop.as_array_mut() 38 | .unwrap() 39 | .sort_unstable_by(compare_json_str_len) 40 | } 41 | }}; 42 | } 43 | 44 | sort_prop!("quotes"); 45 | sort_prop!("verbatim_quotes"); 46 | sort_prop!("multi_line"); 47 | } 48 | 49 | let output_path = Path::new(&out_dir).join("language_type.rs"); 50 | let rust_code = tera.render_str( 51 | &std::fs::read_to_string("src/language/language_type.tera.rs")?, 52 | &tera::Context::from_value(json)?, 53 | )?; 54 | std::fs::write(output_path, rust_code)?; 55 | 56 | Ok(()) 57 | } 58 | 59 | fn compare_json_str_len(a: &Value, b: &Value) -> cmp::Ordering { 60 | let a = a.as_array().expect("a as array"); 61 | let b = b.as_array().expect("b as array"); 62 | 63 | let max_a_size = a.iter().map(|e| e.as_str().unwrap().len()).max().unwrap(); 64 | let max_b_size = b.iter().map(|e| e.as_str().unwrap().len()).max().unwrap(); 65 | 66 | max_b_size.cmp(&max_a_size) 67 | } 68 | 69 | fn generate_tests(out_dir: &OsStr) -> Result<(), Box> { 70 | // Length of string literal below by number of languages 71 | const INITIAL_BUFFER_SIZE: usize = 989 * 130; 72 | let mut string = String::with_capacity(INITIAL_BUFFER_SIZE); 73 | 74 | generate_tests_batch("./tests/data", None, &mut string)?; 75 | generate_tests_batch("./tests/embedding", Some("embedding"), &mut string)?; 76 | 77 | Ok(fs::write(Path::new(&out_dir).join("tests.rs"), string)?) 78 | } 79 | 80 | fn generate_tests_batch( 81 | src_dir: &str, 82 | test_module: Option<&str>, 83 | string: &mut String, 84 | ) -> Result<(), Box> { 85 | let walker = Walk::new(src_dir).filter(|p| match p { 86 | Ok(ref p) => { 87 | if let Ok(ref p) = p.metadata() { 88 | p.is_file() 89 | } else { 90 | false 91 | } 92 | } 93 | _ => false, 94 | }); 95 | 96 | if let Some(test_module) = test_module { 97 | string.push_str(&format!( 98 | r####" 99 | #[cfg(test)] 100 | mod {0} {{ 101 | use super::*; 102 | "####, 103 | test_module 104 | )); 105 | } 106 | 107 | for path in walker { 108 | let path = path?; 109 | let path = path.path(); 110 | let root = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); 111 | 112 | let name = path.file_stem().unwrap().to_str().unwrap().to_lowercase(); 113 | 114 | if name == "jupyter" { 115 | continue; 116 | } 117 | 118 | string.push_str(&format!( 119 | r####" 120 | #[test] 121 | fn {0}() {{ 122 | const _: &str = include_str!(r###"{2}"###); 123 | let mut languages = Languages::new(); 124 | languages.get_statistics(&["{1}"], &[], &Config::default()); 125 | 126 | if languages.len() != 1 {{ 127 | panic!("wrong languages detected: expected just {0}, found {{:?}}", 128 | languages.into_iter().collect::>()); 129 | }} 130 | 131 | let (name, language) = languages.into_iter().next().unwrap(); 132 | let mut language = language.summarise(); 133 | 134 | let contents = fs::read_to_string("{1}").unwrap(); 135 | 136 | println!("{{}} {1}", name); 137 | assert_eq!(get_digit!(LINES, contents), language.lines()); 138 | println!("{{}} LINES MATCH", name); 139 | assert_eq!(get_digit!(CODE, contents), language.code); 140 | println!("{{}} CODE MATCH", name); 141 | assert_eq!(get_digit!(COMMENTS, contents), language.comments); 142 | println!("{{}} COMMENTS MATCH", name); 143 | assert_eq!(get_digit!(BLANKS, contents), language.blanks); 144 | println!("{{}} BLANKS MATCH", name); 145 | 146 | let report = language.reports.pop().unwrap(); 147 | let stats = report.stats.summarise(); 148 | 149 | assert_eq!(language.lines(), stats.lines()); 150 | assert_eq!(language.code, stats.code); 151 | assert_eq!(language.comments, stats.comments); 152 | assert_eq!(language.blanks, stats.blanks); 153 | }} 154 | "####, 155 | name, 156 | path.to_string_lossy().replace('\\', "/"), 157 | std::fs::canonicalize(root.join(path)).unwrap().display(), 158 | )); 159 | } 160 | 161 | if test_module.is_some() { 162 | string.push_str("\n}"); 163 | } 164 | 165 | Ok(()) 166 | } 167 | -------------------------------------------------------------------------------- /ci/build.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Script for building your rust projects. 3 | set -e 4 | 5 | source ci/common.bash 6 | 7 | # $1 {path} = Path to cross/cargo executable 8 | CROSS=$1 9 | # $1 {string} = 10 | TARGET_TRIPLE=$2 11 | # $3 {boolean} = Whether or not building for release or not. 12 | RELEASE_BUILD=$3 13 | 14 | required_arg "$CROSS" 'CROSS' 15 | required_arg "$TARGET_TRIPLE" '' 16 | 17 | if [ -z "$RELEASE_BUILD" ]; then 18 | $CROSS build --target "$TARGET_TRIPLE" 19 | $CROSS build --target "$TARGET_TRIPLE" --all-features 20 | else 21 | $CROSS build --target "$TARGET_TRIPLE" --all-features --release 22 | fi 23 | -------------------------------------------------------------------------------- /ci/common.bash: -------------------------------------------------------------------------------- 1 | required_arg() { 2 | if [ -z "$1" ]; then 3 | echo "Required argument $2 missing" 4 | exit 1 5 | fi 6 | } 7 | -------------------------------------------------------------------------------- /ci/set_rust_version.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | rustup default "$1" 4 | rustup target add "$2" 5 | -------------------------------------------------------------------------------- /ci/test.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Script for building your rust projects. 3 | set -e 4 | 5 | source ci/common.bash 6 | 7 | # $1 {path} = Path to cross/cargo executable 8 | CROSS=$1 9 | # $1 {string} = 10 | TARGET_TRIPLE=$2 11 | 12 | required_arg "$CROSS" 'CROSS' 13 | required_arg "$TARGET_TRIPLE" '' 14 | 15 | $CROSS test --target "$TARGET_TRIPLE" 16 | $CROSS build --target "$TARGET_TRIPLE" --all-features 17 | -------------------------------------------------------------------------------- /fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | target 3 | corpus 4 | artifacts 5 | -------------------------------------------------------------------------------- /fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | 2 | [package] 3 | name = "tokei-fuzz" 4 | version = "0.0.1" 5 | authors = ["Michael Macnair"] 6 | publish = false 7 | edition = "2018" 8 | 9 | [package.metadata] 10 | cargo-fuzz = true 11 | 12 | [dependencies] 13 | libfuzzer-sys = "0.4" 14 | arbitrary = { version = "1.0.0", features = ["derive"] } 15 | 16 | [dependencies.tokei] 17 | path = ".." 18 | 19 | # Prevent this from interfering with workspaces 20 | [workspace] 21 | members = ["."] 22 | 23 | [[bin]] 24 | name = "parse_from_slice_total" 25 | path = "fuzz_targets/parse_from_slice_total.rs" 26 | test = false 27 | doc = false 28 | 29 | [[bin]] 30 | name = "parse_from_slice_panic" 31 | path = "fuzz_targets/parse_from_slice_panic.rs" 32 | test = false 33 | doc = false 34 | -------------------------------------------------------------------------------- /fuzz/README.md: -------------------------------------------------------------------------------- 1 | ## Fuzzing Tokei 2 | 3 | Tokei can be fuzzed using libFuzzer, via [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz/). 4 | 5 | First install cargo-fuzz: `cargo install cargo-fuzz`. 6 | 7 | To launch a fuzzing job: `cargo +nightly fuzz run ` - it will run until you kill it with ctrl-c. 8 | 9 | To use multiple cores: `cargo +nightly fuzz run --jobs=6` 10 | 11 | To speed things up (at the expensive of missing bugs that only manifest in larger files): 12 | `cargo +nightly fuzz run -- -max_len=200` 13 | 14 | Available fuzz targets: 15 | 16 | - `parse_from_slice_panic` - checks that all of the LanguageType instances' `parse_from_slice` function doesn't panic. 17 | - `parse_from_slice_total` - checks that the language stats pass a basic test of reporting no more total lines than 18 | there are new lines in the file. At the time of writing there are low-hanging bugs here. 19 | 20 | With the two `parse_from_slice` fuzz targets, it makes sense to share a common corpus directory as they have identical 21 | input formats, e.g.: `cargo +nightly fuzz run parse_from_slice_{panic,total} fuzz/corpus/common` 22 | 23 | Potential improvements: 24 | 25 | - Build the fuzz harnesses in CI, so they don't rot. 26 | - Do some coverage analysis to check if we're missing any code we would benefit from fuzzing (once it's 27 | [integrated into cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz/pull/248)) 28 | - Tighten the `parse_from_slice_total` fuzz target to check the total lines exactly matches the number of lines in the 29 | file. Only once any bugs found with the current fuzzer are fixed. 30 | - Check in a minimized corpus, and run regression over it in CI. 31 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/parse_from_slice.rs: -------------------------------------------------------------------------------- 1 | use arbitrary::Arbitrary; 2 | use std::str; 3 | 4 | use tokei::{Config, LanguageType}; 5 | 6 | #[derive(Arbitrary, Debug)] 7 | pub struct FuzzInput<'a> { 8 | lang: LanguageType, 9 | treat_doc_strings_as_comments: bool, 10 | data: &'a [u8], 11 | } 12 | 13 | // The first byte of data is used to select a language; remaining input is parsed 14 | // If check_total is true, asserts that the parsed stats pass a basic sanity test 15 | pub fn parse_from_slice(input: FuzzInput, check_total: bool) { 16 | let config = &Config { 17 | treat_doc_strings_as_comments: Some(input.treat_doc_strings_as_comments), 18 | 19 | // these options don't impact the behaviour of parse_from_slice: 20 | columns: None, 21 | hidden: None, 22 | no_ignore: None, 23 | no_ignore_parent: None, 24 | no_ignore_dot: None, 25 | no_ignore_vcs: None, 26 | sort: None, 27 | types: None, 28 | for_each_fn: None, 29 | }; 30 | 31 | // check that parsing doesn't panic 32 | let stats = input.lang.parse_from_slice(input.data, config); 33 | 34 | if check_total { 35 | // verify that the parsed total lines is not more than the total occurrences of \n and \r\n. 36 | // if/when all of the current discrepancies are fixed, we could make this stronger by checking it is equal. 37 | if let Ok(s) = str::from_utf8(input.data) { 38 | assert!( 39 | stats.lines() <= s.lines().count(), 40 | "{} got more total lines ({}) than str::lines ({}). Code: {}, Comments: {}, Blanks: {}. treat_doc_strings_as_comments: {}. File contents (as UTF-8):\n{}", 41 | input.lang.name(), 42 | stats.lines(), 43 | s.lines().count(), 44 | stats.code, 45 | stats.comments, 46 | input.treat_doc_strings_as_comments, 47 | stats.blanks, 48 | s 49 | ) 50 | }; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/parse_from_slice_panic.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | 4 | mod parse_from_slice; 5 | use parse_from_slice::{parse_from_slice, FuzzInput}; 6 | 7 | fuzz_target!(|data: FuzzInput| { 8 | parse_from_slice(data, false); 9 | }); 10 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/parse_from_slice_total.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | 4 | mod parse_from_slice; 5 | use parse_from_slice::{parse_from_slice, FuzzInput}; 6 | 7 | fuzz_target!(|data: FuzzInput| { 8 | parse_from_slice(data, true); 9 | }); 10 | -------------------------------------------------------------------------------- /src/consts.rs: -------------------------------------------------------------------------------- 1 | // Set of common pub consts. 2 | 3 | /// Fallback row length 4 | pub const FALLBACK_ROW_LEN: usize = 81; 5 | 6 | // Column widths used for console printing. 7 | 8 | /// Language column width 9 | pub const LANGUAGE_COLUMN_WIDTH: usize = 10; 10 | 11 | /// Path column width 12 | pub const PATH_COLUMN_WIDTH: usize = 80; 13 | 14 | /// Files column width 15 | pub const FILES_COLUMN_WIDTH: usize = 8; 16 | 17 | /// Lines column width 18 | pub const LINES_COLUMN_WIDTH: usize = 12; 19 | 20 | /// Code column width 21 | pub const CODE_COLUMN_WIDTH: usize = 12; 22 | 23 | /// Comments column width 24 | pub const COMMENTS_COLUMN_WIDTH: usize = 12; 25 | 26 | /// Blanks column width 27 | pub const BLANKS_COLUMN_WIDTH: usize = 12; 28 | -------------------------------------------------------------------------------- /src/language/languages.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | collections::{btree_map, BTreeMap}, 3 | iter::IntoIterator, 4 | ops::{AddAssign, Deref, DerefMut}, 5 | path::Path, 6 | }; 7 | 8 | use rayon::prelude::*; 9 | 10 | use crate::{ 11 | config::Config, 12 | language::{Language, LanguageType}, 13 | utils, 14 | }; 15 | 16 | /// A newtype representing a list of languages counted in the provided 17 | /// directory. 18 | /// ([_List of 19 | /// Languages_](https://github.com/XAMPPRocky/tokei#supported-languages)) 20 | #[derive(Debug, Default, PartialEq)] 21 | pub struct Languages { 22 | inner: BTreeMap, 23 | } 24 | 25 | impl serde::Serialize for Languages { 26 | fn serialize(&self, serializer: S) -> Result 27 | where 28 | S: serde::Serializer, 29 | { 30 | self.inner.serialize(serializer) 31 | } 32 | } 33 | 34 | impl<'de> serde::Deserialize<'de> for Languages { 35 | fn deserialize(deserializer: D) -> Result 36 | where 37 | D: serde::Deserializer<'de>, 38 | { 39 | let map = <_>::deserialize(deserializer)?; 40 | 41 | Ok(Self::from_previous(map)) 42 | } 43 | } 44 | 45 | impl Languages { 46 | fn from_previous(map: BTreeMap) -> Self { 47 | use std::collections::btree_map::Entry; 48 | let mut me = Self::new(); 49 | 50 | for (name, input_language) in map { 51 | match me.entry(name) { 52 | Entry::Occupied(mut entry) => { 53 | *entry.get_mut() += input_language; 54 | } 55 | Entry::Vacant(entry) => { 56 | entry.insert(input_language); 57 | } 58 | } 59 | } 60 | me 61 | } 62 | 63 | /// Populates the `Languages` struct with statistics about languages 64 | /// provided by [`Language`]. 65 | /// 66 | /// Takes a `&[&str]` of paths to recursively traverse, paths can be 67 | /// relative, absolute or glob paths. a second `&[&str]` of paths to ignore, 68 | /// these strings use the `.gitignore` syntax, such as `target` 69 | /// or `**/*.bk`. 70 | /// 71 | /// ```no_run 72 | /// use tokei::{Config, Languages}; 73 | /// 74 | /// let mut languages = Languages::new(); 75 | /// languages.get_statistics(&["."], &[".git", "target"], &Config::default()); 76 | /// ``` 77 | /// 78 | /// [`Language`]: struct.Language.html 79 | pub fn get_statistics>( 80 | &mut self, 81 | paths: &[A], 82 | ignored: &[&str], 83 | config: &Config, 84 | ) { 85 | utils::fs::get_all_files(paths, ignored, &mut self.inner, config); 86 | self.inner.par_iter_mut().for_each(|(_, l)| l.total()); 87 | } 88 | 89 | /// Constructs a new, Languages struct. Languages is always empty and does 90 | /// not allocate. 91 | /// 92 | /// ```rust 93 | /// # use tokei::*; 94 | /// let languages = Languages::new(); 95 | /// ``` 96 | #[must_use] 97 | pub fn new() -> Self { 98 | Languages::default() 99 | } 100 | 101 | /// Summary of the Languages struct. 102 | #[must_use] 103 | pub fn total(self: &Languages) -> Language { 104 | let mut total = Language::new(); 105 | for (ty, l) in self { 106 | let language = l.summarise(); 107 | total.comments += language.comments; 108 | total.blanks += language.blanks; 109 | total.code += language.code; 110 | total.inaccurate |= language.inaccurate; 111 | total.children.insert(*ty, language.reports.clone()); 112 | } 113 | total 114 | } 115 | } 116 | 117 | impl IntoIterator for Languages { 118 | type Item = as IntoIterator>::Item; 119 | type IntoIter = as IntoIterator>::IntoIter; 120 | 121 | fn into_iter(self) -> Self::IntoIter { 122 | self.inner.into_iter() 123 | } 124 | } 125 | 126 | impl<'a> IntoIterator for &'a Languages { 127 | type Item = (&'a LanguageType, &'a Language); 128 | type IntoIter = btree_map::Iter<'a, LanguageType, Language>; 129 | 130 | fn into_iter(self) -> Self::IntoIter { 131 | self.inner.iter() 132 | } 133 | } 134 | 135 | impl<'a> IntoIterator for &'a mut Languages { 136 | type Item = (&'a LanguageType, &'a mut Language); 137 | type IntoIter = btree_map::IterMut<'a, LanguageType, Language>; 138 | 139 | fn into_iter(self) -> Self::IntoIter { 140 | self.inner.iter_mut() 141 | } 142 | } 143 | 144 | impl AddAssign> for Languages { 145 | fn add_assign(&mut self, rhs: BTreeMap) { 146 | for (name, language) in rhs { 147 | if let Some(result) = self.inner.get_mut(&name) { 148 | *result += language; 149 | } 150 | } 151 | } 152 | } 153 | 154 | impl Deref for Languages { 155 | type Target = BTreeMap; 156 | 157 | fn deref(&self) -> &Self::Target { 158 | &self.inner 159 | } 160 | } 161 | 162 | impl DerefMut for Languages { 163 | fn deref_mut(&mut self) -> &mut BTreeMap { 164 | &mut self.inner 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # Tokei: Count your code quickly. 2 | //! 3 | //! A simple, efficient library for counting code in directories. This 4 | //! functionality is also provided as a 5 | //! [CLI utility](//github.com/XAMPPRocky/tokei). Tokei uses a small state 6 | //! machine rather than regular expressions found in other code counters. Tokei 7 | //! can accurately count a lot more edge cases such as nested comments, or 8 | //! comment syntax inside string literals. 9 | //! 10 | //! # Examples 11 | //! 12 | //! Gets the total lines of code from all rust files in current directory, 13 | //! and all subdirectories. 14 | //! 15 | //! ```no_run 16 | //! use std::collections::BTreeMap; 17 | //! use std::fs::File; 18 | //! use std::io::Read; 19 | //! 20 | //! use tokei::{Config, Languages, LanguageType}; 21 | //! 22 | //! // The paths to search. Accepts absolute, relative, and glob paths. 23 | //! let paths = &["src", "tests"]; 24 | //! // Exclude any path that contains any of these strings. 25 | //! let excluded = &["target"]; 26 | //! // `Config` allows you to configure what is searched and counted. 27 | //! let config = Config::default(); 28 | //! 29 | //! let mut languages = Languages::new(); 30 | //! languages.get_statistics(paths, excluded, &config); 31 | //! let rust = &languages[&LanguageType::Rust]; 32 | //! 33 | //! println!("Lines of code: {}", rust.code); 34 | //! ``` 35 | 36 | #![deny( 37 | trivial_casts, 38 | trivial_numeric_casts, 39 | unused_variables, 40 | unstable_features, 41 | unused_import_braces, 42 | missing_docs 43 | )] 44 | 45 | #[macro_use] 46 | extern crate log; 47 | #[macro_use] 48 | extern crate serde; 49 | 50 | #[macro_use] 51 | mod utils; 52 | mod config; 53 | mod consts; 54 | mod language; 55 | mod sort; 56 | mod stats; 57 | 58 | pub use self::{ 59 | config::Config, 60 | consts::*, 61 | language::{Language, LanguageType, Languages}, 62 | sort::Sort, 63 | stats::{find_char_boundary, CodeStats, Report}, 64 | }; 65 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate log; 3 | 4 | mod cli; 5 | mod cli_utils; 6 | mod consts; 7 | mod input; 8 | 9 | use std::{error::Error, io, process}; 10 | 11 | use tokei::{Config, Languages, Sort}; 12 | 13 | use crate::{ 14 | cli::Cli, 15 | cli_utils::Printer, 16 | consts::{ 17 | BLANKS_COLUMN_WIDTH, CODE_COLUMN_WIDTH, COMMENTS_COLUMN_WIDTH, FALLBACK_ROW_LEN, 18 | LANGUAGE_COLUMN_WIDTH, LINES_COLUMN_WIDTH, PATH_COLUMN_WIDTH, 19 | }, 20 | input::add_input, 21 | }; 22 | 23 | fn main() -> Result<(), Box> { 24 | let mut cli = Cli::from_args(); 25 | 26 | if cli.print_languages { 27 | Cli::print_supported_languages()?; 28 | process::exit(0); 29 | } 30 | let config = cli.override_config(Config::from_config_files()); 31 | let mut languages = Languages::new(); 32 | 33 | if let Some(input) = cli.file_input() { 34 | if !add_input(input, &mut languages) { 35 | Cli::print_input_parse_failure(input); 36 | process::exit(1); 37 | } 38 | } 39 | 40 | let input = cli.input(); 41 | 42 | for path in &input { 43 | if ::std::fs::metadata(path).is_err() { 44 | eprintln!("Error: '{}' not found.", path); 45 | process::exit(1); 46 | } 47 | } 48 | 49 | let columns = cli 50 | .columns 51 | .or(config.columns) 52 | .or_else(|| { 53 | if cli.files { 54 | term_size::dimensions().map(|(w, _)| w) 55 | } else { 56 | None 57 | } 58 | }) 59 | .unwrap_or(FALLBACK_ROW_LEN) 60 | .max(FALLBACK_ROW_LEN); 61 | 62 | if cli.streaming == Some(crate::cli::Streaming::Simple) { 63 | println!( 64 | "#{:^LANGUAGE_COLUMN_WIDTH$} {:^PATH_COLUMN_WIDTH$} {:^LINES_COLUMN_WIDTH$} {:^CODE_COLUMN_WIDTH$} {:^COMMENTS_COLUMN_WIDTH$} {:^BLANKS_COLUMN_WIDTH$}", 65 | "language", "path", "lines", "code", "comments", "blanks" 66 | ); 67 | println!( 68 | "{:>LANGUAGE_COLUMN_WIDTH$} {:LINES_COLUMN_WIDTH$} {:>CODE_COLUMN_WIDTH$} {:>COMMENTS_COLUMN_WIDTH$} {:>BLANKS_COLUMN_WIDTH$}", 69 | (0..10).map(|_| "#").collect::(), 70 | (0..80).map(|_| "#").collect::(), 71 | (0..12).map(|_| "#").collect::(), 72 | (0..12).map(|_| "#").collect::(), 73 | (0..12).map(|_| "#").collect::(), 74 | (0..12).map(|_| "#").collect::() 75 | ); 76 | } 77 | 78 | languages.get_statistics(&input, &cli.ignored_directories(), &config); 79 | if config.for_each_fn.is_some() { 80 | process::exit(0); 81 | } 82 | 83 | if let Some(format) = cli.output { 84 | print!("{}", format.print(&languages).unwrap()); 85 | process::exit(0); 86 | } 87 | 88 | let mut printer = Printer::new( 89 | columns, 90 | cli.files, 91 | io::BufWriter::new(io::stdout()), 92 | cli.number_format, 93 | ); 94 | 95 | if languages.iter().any(|(_, lang)| lang.inaccurate) { 96 | printer.print_inaccuracy_warning()?; 97 | } 98 | 99 | printer.print_header()?; 100 | 101 | let mut is_sorted = false; 102 | if let Some(sort_category) = cli.sort.or(config.sort) { 103 | for (_, ref mut language) in &mut languages { 104 | language.sort_by(sort_category); 105 | } 106 | 107 | let mut languages: Vec<_> = languages.iter().collect(); 108 | match sort_category { 109 | Sort::Blanks => languages.sort_by(|a, b| b.1.blanks.cmp(&a.1.blanks)), 110 | Sort::Comments => languages.sort_by(|a, b| b.1.comments.cmp(&a.1.comments)), 111 | Sort::Code => languages.sort_by(|a, b| b.1.code.cmp(&a.1.code)), 112 | Sort::Files => languages.sort_by(|a, b| b.1.reports.len().cmp(&a.1.reports.len())), 113 | Sort::Lines => languages.sort_by(|a, b| b.1.lines().cmp(&a.1.lines())), 114 | } 115 | is_sorted = true; 116 | if cli.sort_reverse { 117 | printer.print_results(languages.into_iter().rev(), cli.compact, is_sorted)?; 118 | } else { 119 | printer.print_results(languages.into_iter(), cli.compact, is_sorted)?; 120 | } 121 | } else { 122 | printer.print_results(languages.iter(), cli.compact, is_sorted)?; 123 | } 124 | 125 | printer.print_total(&languages)?; 126 | 127 | Ok(()) 128 | } 129 | -------------------------------------------------------------------------------- /src/sort.rs: -------------------------------------------------------------------------------- 1 | use std::{borrow::Cow, str::FromStr}; 2 | 3 | use serde::de::{self, Deserialize, Deserializer}; 4 | 5 | /// Used for sorting languages. 6 | #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] 7 | pub enum Sort { 8 | /// Sort by number blank lines. 9 | Blanks, 10 | /// Sort by number comments lines. 11 | Comments, 12 | /// Sort by number code lines. 13 | Code, 14 | /// Sort by number files lines. 15 | Files, 16 | /// Sort by number of lines. 17 | Lines, 18 | } 19 | 20 | impl FromStr for Sort { 21 | type Err = String; 22 | 23 | fn from_str(s: &str) -> Result { 24 | Ok(if s.eq_ignore_ascii_case("blanks") { 25 | Sort::Blanks 26 | } else if s.eq_ignore_ascii_case("comments") { 27 | Sort::Comments 28 | } else if s.eq_ignore_ascii_case("code") { 29 | Sort::Code 30 | } else if s.eq_ignore_ascii_case("files") { 31 | Sort::Files 32 | } else if s.eq_ignore_ascii_case("lines") { 33 | Sort::Lines 34 | } else { 35 | return Err(format!("Unsupported sorting option: {}", s)); 36 | }) 37 | } 38 | } 39 | 40 | impl<'de> Deserialize<'de> for Sort { 41 | fn deserialize(deserializer: D) -> Result 42 | where 43 | D: Deserializer<'de>, 44 | { 45 | String::deserialize(deserializer)? 46 | .parse() 47 | .map_err(de::Error::custom) 48 | } 49 | } 50 | 51 | impl<'a> From for Cow<'a, Sort> { 52 | fn from(from: Sort) -> Self { 53 | Cow::Owned(from) 54 | } 55 | } 56 | 57 | impl<'a> From<&'a Sort> for Cow<'a, Sort> { 58 | fn from(from: &'a Sort) -> Self { 59 | Cow::Borrowed(from) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/stats.rs: -------------------------------------------------------------------------------- 1 | use crate::consts::{ 2 | BLANKS_COLUMN_WIDTH, CODE_COLUMN_WIDTH, COMMENTS_COLUMN_WIDTH, LINES_COLUMN_WIDTH, 3 | }; 4 | use crate::LanguageType; 5 | use std::{collections::BTreeMap, fmt, ops, path::PathBuf}; 6 | 7 | /// A struct representing stats about a single blob of code. 8 | #[derive(Clone, Debug, Default, PartialEq, serde::Deserialize, serde::Serialize)] 9 | #[non_exhaustive] 10 | pub struct CodeStats { 11 | /// The blank lines in the blob. 12 | pub blanks: usize, 13 | /// The lines of code in the blob. 14 | pub code: usize, 15 | /// The lines of comments in the blob. 16 | pub comments: usize, 17 | /// Language blobs that were contained inside this blob. 18 | pub blobs: BTreeMap, 19 | } 20 | 21 | impl CodeStats { 22 | /// Creates a new blank `CodeStats`. 23 | #[must_use] 24 | pub fn new() -> Self { 25 | Self::default() 26 | } 27 | 28 | /// Get the total lines in a blob of code. 29 | #[must_use] 30 | pub fn lines(&self) -> usize { 31 | self.blanks + self.code + self.comments 32 | } 33 | 34 | /// Creates a new `CodeStats` from an existing one with all of the child 35 | /// blobs merged. 36 | #[must_use] 37 | pub fn summarise(&self) -> Self { 38 | let mut summary = self.clone(); 39 | 40 | for (_, stats) in std::mem::take(&mut summary.blobs) { 41 | let child_summary = stats.summarise(); 42 | 43 | summary.blanks += child_summary.blanks; 44 | summary.comments += child_summary.comments; 45 | summary.code += child_summary.code; 46 | } 47 | 48 | summary 49 | } 50 | } 51 | 52 | impl ops::AddAssign for CodeStats { 53 | fn add_assign(&mut self, rhs: Self) { 54 | self.add_assign(&rhs); 55 | } 56 | } 57 | 58 | impl ops::AddAssign<&'_ CodeStats> for CodeStats { 59 | fn add_assign(&mut self, rhs: &'_ CodeStats) { 60 | self.blanks += rhs.blanks; 61 | self.code += rhs.code; 62 | self.comments += rhs.comments; 63 | 64 | for (language, stats) in &rhs.blobs { 65 | *self.blobs.entry(*language).or_default() += stats; 66 | } 67 | } 68 | } 69 | 70 | /// A struct representing the statistics of a file. 71 | #[derive(Deserialize, Serialize, Clone, Debug, Default, PartialEq)] 72 | #[non_exhaustive] 73 | pub struct Report { 74 | /// The code statistics found in the file. 75 | pub stats: CodeStats, 76 | /// File name. 77 | pub name: PathBuf, 78 | } 79 | 80 | impl Report { 81 | /// Create a new `Report` from a [`PathBuf`]. 82 | /// 83 | /// [`PathBuf`]: //doc.rust-lang.org/std/path/struct.PathBuf.html 84 | #[must_use] 85 | pub fn new(name: PathBuf) -> Self { 86 | Self { 87 | name, 88 | ..Self::default() 89 | } 90 | } 91 | } 92 | 93 | impl ops::AddAssign for Report { 94 | fn add_assign(&mut self, rhs: CodeStats) { 95 | self.stats += rhs; 96 | } 97 | } 98 | 99 | #[doc(hidden)] 100 | #[must_use] 101 | pub fn find_char_boundary(s: &str, index: usize) -> usize { 102 | for i in 0..4 { 103 | if s.is_char_boundary(index + i) { 104 | return index + i; 105 | } 106 | } 107 | unreachable!(); 108 | } 109 | 110 | macro_rules! display_stats { 111 | ($f:expr, $this:expr, $name:expr, $max:expr) => { 112 | write!( 113 | $f, 114 | " {: LINES_COLUMN_WIDTH$} {:>CODE_COLUMN_WIDTH$} {:>COMMENTS_COLUMN_WIDTH$} {:>BLANKS_COLUMN_WIDTH$}", 115 | $name, 116 | $this.stats.lines(), 117 | $this.stats.code, 118 | $this.stats.comments, 119 | $this.stats.blanks, 120 | max = $max 121 | ) 122 | }; 123 | } 124 | 125 | impl fmt::Display for Report { 126 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 127 | let name = self.name.to_string_lossy(); 128 | let name_length = name.len(); 129 | 130 | // Added 2 to max length to cover wider Files column (see https://github.com/XAMPPRocky/tokei/issues/891). 131 | let max_len = f.width().unwrap_or(27) + 2; 132 | 133 | if name_length <= max_len { 134 | display_stats!(f, self, name, max_len) 135 | } else { 136 | let mut formatted = String::from("|"); 137 | // Add 1 to the index to account for the '|' we add to the output string 138 | let from = find_char_boundary(&name, name_length + 1 - max_len); 139 | formatted.push_str(&name[from..]); 140 | display_stats!(f, self, formatted, max_len) 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/utils/ext.rs: -------------------------------------------------------------------------------- 1 | //! Various extensions to Rust std types. 2 | 3 | pub(crate) trait AsciiExt { 4 | fn is_whitespace(&self) -> bool; 5 | fn is_line_ending_whitespace(&self) -> bool; 6 | } 7 | 8 | impl AsciiExt for u8 { 9 | fn is_whitespace(&self) -> bool { 10 | *self == b' ' || (b'\x09'..=b'\x0d').contains(self) 11 | } 12 | 13 | fn is_line_ending_whitespace(&self) -> bool { 14 | *self == b'\n' 15 | } 16 | } 17 | 18 | pub(crate) trait SliceExt { 19 | fn trim_first_and_last_line_of_whitespace(&self) -> &Self; 20 | fn trim_start(&self) -> &Self; 21 | fn trim(&self) -> &Self; 22 | fn contains_slice(&self, needle: &Self) -> bool; 23 | } 24 | 25 | impl SliceExt for [u8] { 26 | fn trim_first_and_last_line_of_whitespace(&self) -> &Self { 27 | let start = self 28 | .iter() 29 | .position(|c| c.is_line_ending_whitespace() || !c.is_whitespace()) 30 | .map_or(0, |i| (i + 1).min(self.len().saturating_sub(1))); 31 | 32 | let end = self 33 | .iter() 34 | .rposition(|c| c.is_line_ending_whitespace() || !c.is_whitespace()) 35 | .map_or_else( 36 | || self.len().saturating_sub(1), 37 | |i| { 38 | // Remove the entire `\r\n` in the case that it was the line ending whitespace 39 | if self[i.saturating_sub(1)] == b'\r' && self[i] == b'\n' { 40 | i - 1 41 | } else { 42 | i 43 | } 44 | }, 45 | ); 46 | 47 | if self[start..].is_empty() { 48 | return &[]; 49 | } 50 | 51 | &self[start..=end] 52 | } 53 | 54 | fn trim_start(&self) -> &Self { 55 | let length = self.len(); 56 | 57 | if length == 0 { 58 | return self; 59 | } 60 | 61 | let start = match self.iter().position(|c| !c.is_whitespace()) { 62 | Some(start) => start, 63 | None => return &[], 64 | }; 65 | 66 | &self[start..] 67 | } 68 | 69 | fn trim(&self) -> &Self { 70 | let length = self.len(); 71 | 72 | if length == 0 { 73 | return self; 74 | } 75 | 76 | let start = match self.iter().position(|c| !c.is_whitespace()) { 77 | Some(start) => start, 78 | None => return &[], 79 | }; 80 | 81 | let end = match self.iter().rposition(|c| !c.is_whitespace()) { 82 | Some(end) => end.max(start), 83 | _ => length, 84 | }; 85 | 86 | &self[start..=end] 87 | } 88 | 89 | fn contains_slice(&self, needle: &Self) -> bool { 90 | let self_length = self.len(); 91 | let needle_length = needle.len(); 92 | 93 | if needle_length == 0 || needle_length > self_length { 94 | return false; 95 | } else if needle_length == self_length { 96 | return self == needle; 97 | } 98 | 99 | for window in self.windows(needle_length) { 100 | if needle == window { 101 | return true; 102 | } 103 | } 104 | 105 | false 106 | } 107 | } 108 | 109 | #[cfg(test)] 110 | mod tests { 111 | use super::*; 112 | 113 | use proptest::prelude::*; 114 | 115 | #[test] 116 | fn is_whitespace() { 117 | assert!(b' '.is_whitespace()); 118 | assert!(b'\r'.is_whitespace()); 119 | assert!(b'\n'.is_whitespace()); 120 | } 121 | 122 | #[test] 123 | fn trim() { 124 | assert!([b' ', b' ', b' '].trim().is_empty()); 125 | assert!([b' ', b'\r', b'\n'].trim().is_empty()); 126 | assert!([b'\n'].trim().is_empty()); 127 | assert!([].trim().is_empty()); 128 | 129 | assert_eq!([b'a', b'b'], [b'a', b'b'].trim()); 130 | assert_eq!([b'h', b'i'], [b' ', b'h', b'i'].trim()); 131 | assert_eq!([b'h', b'i'], [b'h', b'i', b' '].trim()); 132 | assert_eq!([b'h', b'i'], [b' ', b'h', b'i', b' '].trim()); 133 | } 134 | 135 | #[test] 136 | fn contains() { 137 | assert!([1, 2, 3, 4, 5].contains_slice(&[1, 2, 3, 4, 5])); 138 | assert!([1, 2, 3, 4, 5].contains_slice(&[1, 2, 3])); 139 | assert!([1, 2, 3, 4, 5].contains_slice(&[3, 4, 5])); 140 | assert!([1, 2, 3, 4, 5].contains_slice(&[2, 3, 4])); 141 | assert!(![1, 2, 3, 4, 5].contains_slice(&[])); 142 | } 143 | 144 | #[test] 145 | fn trim_first_and_last_line_of_whitespace_edge_cases() { 146 | assert_eq!(b"", b"\ra ".trim_first_and_last_line_of_whitespace()); 147 | assert_eq!(b"a", b"\r\na ".trim_first_and_last_line_of_whitespace()); 148 | 149 | assert_eq!(b" ", b" ".trim_first_and_last_line_of_whitespace()); 150 | } 151 | 152 | proptest! { 153 | #[test] 154 | fn trim_first_and_last_line_of_whitespace_doesnt_panic(input: Vec) { 155 | let _ = &input.trim_first_and_last_line_of_whitespace(); 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/utils/macros.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_macros)] 2 | 3 | macro_rules! opt_warn { 4 | ($option:expr, $message:expr) => { 5 | match $option { 6 | Some(result) => result, 7 | None => { 8 | warn!($message); 9 | continue; 10 | } 11 | } 12 | }; 13 | } 14 | 15 | macro_rules! rs_warn { 16 | ($result:expr, $message: expr) => { 17 | match $result { 18 | Ok(result) => result, 19 | Err(error) => { 20 | warn!("{}", error); 21 | continue; 22 | } 23 | } 24 | }; 25 | } 26 | 27 | macro_rules! opt_error { 28 | ($option:expr, $message:expr) => { 29 | match $option { 30 | Some(result) => result, 31 | None => { 32 | error!($message); 33 | continue; 34 | } 35 | } 36 | }; 37 | } 38 | 39 | macro_rules! rs_error { 40 | ($result:expr) => { 41 | match $result { 42 | Ok(result) => result, 43 | Err(error) => { 44 | error!("{}", error); 45 | continue; 46 | } 47 | } 48 | }; 49 | } 50 | 51 | macro_rules! opt_ret_warn { 52 | ($option:expr, $message:expr) => { 53 | match $option { 54 | Some(result) => result, 55 | None => { 56 | warn!($message); 57 | return None; 58 | } 59 | } 60 | }; 61 | } 62 | 63 | macro_rules! rs_ret_warn { 64 | ($result:expr, $message: expr) => { 65 | match $result { 66 | Ok(result) => result, 67 | Err(error) => { 68 | warn!("{}", error); 69 | return None; 70 | } 71 | } 72 | }; 73 | } 74 | 75 | macro_rules! opt_ret_error { 76 | ($option:expr, $message:expr) => { 77 | match $option { 78 | Some(result) => result, 79 | None => { 80 | error!($message); 81 | return None; 82 | } 83 | } 84 | }; 85 | } 86 | 87 | macro_rules! rs_ret_error { 88 | ($result:expr) => { 89 | match $result { 90 | Ok(result) => result, 91 | Err(error) => { 92 | error!("{}", error); 93 | return None; 94 | } 95 | } 96 | }; 97 | } 98 | 99 | macro_rules! debug { 100 | ($fmt:expr) => (if cfg!(debug_assertions) {println!($fmt)}); 101 | ($fmt:expr, $($arg:tt)*) => (if cfg!(debug_assertions) {println!($fmt, $($arg)*)}); 102 | } 103 | -------------------------------------------------------------------------------- /src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | mod macros; 3 | pub(crate) mod ext; 4 | pub mod fs; 5 | -------------------------------------------------------------------------------- /tests/accuracy.rs: -------------------------------------------------------------------------------- 1 | extern crate ignore; 2 | extern crate regex; 3 | extern crate tokei; 4 | 5 | use std::fs; 6 | 7 | use once_cell::sync::Lazy; 8 | use regex::Regex; 9 | use tokei::{Config, Languages}; 10 | 11 | static LINES: Lazy = Lazy::new(|| Regex::new(r"\d+ lines").unwrap()); 12 | static CODE: Lazy = Lazy::new(|| Regex::new(r"\d+ code").unwrap()); 13 | static COMMENTS: Lazy = Lazy::new(|| Regex::new(r"\d+ comments").unwrap()); 14 | static BLANKS: Lazy = Lazy::new(|| Regex::new(r"\d+ blanks").unwrap()); 15 | 16 | macro_rules! get_digit { 17 | ($regex:expr, $text:expr) => {{ 18 | let matched = $regex.find(&$text).expect("Couldn't find category"); 19 | matched 20 | .as_str() 21 | .split_whitespace() 22 | .next() 23 | .unwrap() 24 | .parse::() 25 | .unwrap() 26 | }}; 27 | } 28 | 29 | mod config { 30 | use tokei::*; 31 | 32 | /* 33 | #[test] 34 | fn extension_change() { 35 | use std::collections::HashMap; 36 | let mut languages = Languages::new(); 37 | let config = Config { 38 | languages: { 39 | let mut map = HashMap::new(); 40 | let mut config = LanguageConfig::new(); 41 | config.extensions(vec![String::from("cpp")]); 42 | map.insert(LanguageType::C, config); 43 | 44 | Some(map) 45 | }, 46 | ..Config::default() 47 | }; 48 | 49 | languages.get_statistics(&["tests/data/cpp.cpp"], &[], &config); 50 | 51 | if languages.len() != 1 { 52 | panic!("wrong languages detected: expected just C, found {:?}", 53 | languages.into_iter().collect::>()); 54 | } 55 | 56 | let (name, _) = languages.into_iter().next().unwrap(); 57 | 58 | assert_eq!(LanguageType::C, name); 59 | } 60 | */ 61 | 62 | #[test] 63 | fn treating_comments_as_code() { 64 | let mut languages = Languages::new(); 65 | let config = Config { 66 | treat_doc_strings_as_comments: Some(true), 67 | ..Config::default() 68 | }; 69 | 70 | languages.get_statistics(&["tests/data/python.py"], &[], &config); 71 | 72 | if languages.len() != 1 { 73 | panic!( 74 | "wrong languages detected: expected just Python, found {:?}", 75 | languages.into_iter().collect::>() 76 | ); 77 | } 78 | 79 | let (_, language) = languages.into_iter().next().unwrap(); 80 | 81 | assert_eq!(language.lines(), 15); 82 | assert_eq!(language.blanks, 3); 83 | assert_eq!(language.comments, 7); 84 | assert_eq!(language.code, 5); 85 | } 86 | } 87 | 88 | include!(concat!(env!("OUT_DIR"), "/tests.rs")); 89 | -------------------------------------------------------------------------------- /tests/data/Daml.daml: -------------------------------------------------------------------------------- 1 | -- ! 42 lines 24 code 9 comments 9 blanks 2 | 3 | {- 4 | This code is derived from https://github.com/digital-asset/ex-secure-daml-infra/blob/master/daml/BobTrigger.daml 5 | -- Haskell/DAML support nested comments 6 | {- including nested 7 | block comments 8 | -} 9 | -} 10 | 11 | 12 | module BobTrigger where 13 | 14 | -- import DA.Action 15 | import DA.Foldable 16 | import DA.Next.Map (Map) 17 | import Daml.Trigger 18 | import Main 19 | 20 | (--$) :: a -> b -> String 21 | a --$ b = "Not a comment" 22 | 23 | rejectTrigger : Trigger () = Trigger with 24 | initialize = \_ -> () 25 | updateState = \_ _ () -> () 26 | rule = rejectRule 27 | registeredTemplates = AllInDar 28 | heartbeat = None 29 | testNotAComment = 1 30 | --$ 2 == "Not a comment" 31 | 32 | 33 | rejectRule : Party -> ACS -> Time -> Map CommandId [Command] -> () -> TriggerA () 34 | rejectRule p acs _ _ _ = do 35 | let assets = getContracts @Asset acs 36 | let bobAssets = filter (\(_,a) -> a.owner == p) assets 37 | let configs = getContracts @DonorConfig acs 38 | let Some (_,bobConfig) = find (\(_,c) -> c.owner == p) configs 39 | 40 | forA_ bobAssets $ \(_cid, c) -> do 41 | debug "Ran rejectRule" 42 | emitCommands [exerciseCmd _cid Give with newOwner = bobConfig.donateTo] [toAnyContractId _cid] 43 | -------------------------------------------------------------------------------- /tests/data/Dockerfile: -------------------------------------------------------------------------------- 1 | # 17 lines 7 code 3 comments 7 blanks 2 | 3 | FROM netbsd:7.0.2 4 | 5 | MAINTAINER Somebody version: 2.2 6 | 7 | RUN curl -sSf https://static.rust-lang.org/rustup.sh | sh -s -- -y 8 | 9 | # this part is important 10 | VOLUME ["/project"] 11 | WORKDIR "/project" 12 | 13 | RUN sh -c 'echo "Hello World" > /dev/null' 14 | RUN cargo install tokei # not counted 15 | 16 | # now you do your part 17 | 18 | -------------------------------------------------------------------------------- /tests/data/MSBuild.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | Latest 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/data/Makefile: -------------------------------------------------------------------------------- 1 | # 24 lines 11 code 5 comments 8 blanks 2 | 3 | ## ## 4 | ## IMPORTANT COMMENT ## 5 | ## ## 6 | 7 | all: hello 8 | 9 | hello: main.o factorial.o hello.o 10 | g++ main.o factorial.o hello.o -o hello 11 | 12 | # main.o is my favorite 13 | main.o: main.cpp 14 | g++ -c main.cpp 15 | 16 | factorial.o: factorial.cpp 17 | g++ -c factorial.cpp 18 | 19 | hello.o: hello.cpp 20 | g++ -c hello.cpp 21 | 22 | clean: 23 | rm *o hello #not counted 24 | 25 | -------------------------------------------------------------------------------- /tests/data/Modelica.mo: -------------------------------------------------------------------------------- 1 | // 21 lines 13 code 5 comments 3 blanks 2 | block Add "Output the sum of the two inputs" 3 | extends Interfaces.SI2SO; 4 | 5 | /* 6 | parameter section 7 | */ 8 | parameter Real k1=+1 "Gain of input signal 1"; 9 | parameter Real k2=+1 "Gain of input signal 2"; 10 | 11 | // equation section 12 | equation 13 | y = k1*u1 + k2*u2; 14 | annotation ( 15 | Documentation(info=" 16 |

17 | Some documentation. 18 |

19 | ")); 20 | 21 | end Add; 22 | -------------------------------------------------------------------------------- /tests/data/NuGet.Config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/data/PKGBUILD: -------------------------------------------------------------------------------- 1 | # 24 lines 19 code 3 comments 2 blanks 2 | # Maintainer: Andy 'Blocktronics' Herbert 3 | # Aur Maintainer: Wanesty 4 | 5 | pkgname=moebius-bin 6 | pkgver=1.0.29 7 | pkgrel=1 8 | epoch=1 9 | pkgdesc="Modern ANSI & ASCII Art Editor" 10 | arch=('x86_64') 11 | url="https://github.com/blocktronics/moebius" 12 | license=('Apache') 13 | depends=('gtk3' 'libnotify' 'libxss' 'libxtst' 'xdg-utils' 'libappindicator-gtk3') 14 | makedepends=('libarchive') 15 | conflicts=('moebius') 16 | source=("https://github.com/blocktronics/moebius/releases/download/$pkgver/Moebius.rpm") 17 | sha256sums=(69aaa1e42e287ed78c8e73971dae3df23ae4fa00e3416ea0fc262b7d147fefec) 18 | noextract=("Moebius.rpm") 19 | 20 | package() { 21 | bsdtar -C "${pkgdir}" -xvf "$srcdir/Moebius.rpm" 22 | mkdir "$pkgdir/usr/bin" 23 | ln -s "/opt/Moebius/moebius" "$pkgdir/usr/bin/moebius" 24 | } -------------------------------------------------------------------------------- /tests/data/Rakefile: -------------------------------------------------------------------------------- 1 | # 10 lines 4 code 2 comments 4 blanks 2 | 3 | # this is a rakefile 4 | 5 | task default: %w[test] 6 | 7 | task :test do # not counted 8 | ruby "test/unittest.rb" 9 | end 10 | 11 | -------------------------------------------------------------------------------- /tests/data/SConstruct: -------------------------------------------------------------------------------- 1 | #!python 2 | # 10 lines 3 code 3 comments 4 blanks 3 | 4 | # this is a comment 5 | 6 | Program('cpp.cpp') # this is a line-ending comment 7 | 8 | env = Environment(CCFLAGS='-O3') 9 | env.Append(CCFLAGS='-O3') 10 | 11 | -------------------------------------------------------------------------------- /tests/data/Snakefile: -------------------------------------------------------------------------------- 1 | # 67 lines 50 code 4 comments 13 blanks 2 | """ 3 | A sample Snakefile for testing line counting 4 | """ 5 | 6 | SAMPLES = ["A", "B"] 7 | 8 | 9 | # This is a 10 | # multiline 11 | # comment 12 | rule all: 13 | input: 14 | "plots/quals.svg" 15 | 16 | 17 | '''Sometimes even some 18 | comments in single quote 19 | fences.''' 20 | rule bwa_map: 21 | input: 22 | "data/genome.fa", # Inline comments are also supported 23 | "data/samples/{sample}.fastq" 24 | output: 25 | "mapped_reads/{sample}.bam" 26 | shell: 27 | "bwa mem {input} | samtools view -Sb - > {output}" 28 | 29 | 30 | rule samtools_sort: 31 | input: 32 | "mapped_reads/{sample}.bam" 33 | output: 34 | "sorted_reads/{sample}.bam" 35 | shell: 36 | "samtools sort -T sorted_reads/{wildcards.sample} " 37 | "-O bam {input} > {output}" 38 | 39 | 40 | rule samtools_index: 41 | input: 42 | "sorted_reads/{sample}.bam" 43 | output: 44 | "sorted_reads/{sample}.bam.bai" 45 | shell: 46 | "samtools index {input}" 47 | 48 | 49 | rule bcftools_call: 50 | input: 51 | fa="data/genome.fa", 52 | bam=expand("sorted_reads/{sample}.bam", sample=SAMPLES), 53 | bai=expand("sorted_reads/{sample}.bam.bai", sample=SAMPLES) 54 | output: 55 | "calls/all.vcf" 56 | shell: 57 | "bcftools mpileup -f {input.fa} {input.bam} | " 58 | "bcftools call -mv - > {output}" 59 | 60 | 61 | rule plot_quals: 62 | input: 63 | "calls/all.vcf" 64 | output: 65 | "plots/quals.svg" 66 | script: 67 | "scripts/plot-quals.py" 68 | -------------------------------------------------------------------------------- /tests/data/Tera.tera: -------------------------------------------------------------------------------- 1 | {# 42 lines 26 code 11 comments 5 blanks #} 2 | 3 | 4 | 5 | 6 | 7 | 8 | link 9 | {# #} 14 | {# comment #} 15 | 16 | 17 | body 18 | 19 | 20 | 21 | 24 | 25 | 28 | 29 | 32 | 35 | {# 36 | multi-line-comment #} 37 | 38 | {% if error %} 39 |
{{ error.content }}
{# comment #} 40 | {% endif %} 41 | 42 | 43 | -------------------------------------------------------------------------------- /tests/data/abnf.abnf: -------------------------------------------------------------------------------- 1 | ; 11 lines 3 code 5 comments 3 blanks 2 | ; comment line 0 3 | ; comment line 1 4 | 5 | ALPHA = %x41-5A / %x61-7A ; A-Z / a-z 6 | 7 | BIT = "0" / "1" 8 | 9 | CHAR = %x01-7F 10 | ; any 7-bit US-ASCII character, 11 | ; excluding NUL 12 | -------------------------------------------------------------------------------- /tests/data/alloy.als: -------------------------------------------------------------------------------- 1 | // 18 lines 10 code 3 comments 5 blanks 2 | 3 | sig Node { 4 | edge: set Node 5 | } 6 | 7 | ------------------------------------------------------------------------ 8 | 9 | pred self_loop[n: Node] { 10 | n in n.edge 11 | } 12 | 13 | pred all_self_loop { 14 | all n: Node | self_loop[n] 15 | } 16 | 17 | /* Comments started by /* don't nest */ 18 | run all_self_loop 19 | -------------------------------------------------------------------------------- /tests/data/apl.apl: -------------------------------------------------------------------------------- 1 | ⍝ 10 lines 3 code 3 comments 4 blanks 2 | 3 | 4 | 256=2*8 5 | 6 | ⍝ Comment 7 | ⊃¨ ' '(≠⊆⊢) 'A Programming Language' 8 | 9 | ⍝ A magic square of length ⊢ 10 | MS ← (⍳-∘⌈÷∘2)(⊣⊖⌽),⍨⍴∘⍳×⍨ 11 | -------------------------------------------------------------------------------- /tests/data/arduino.ino: -------------------------------------------------------------------------------- 1 | // 23 lines 13 code 6 comments 4 blanks 2 | 3 | int led = 13; 4 | 5 | void setup() { 6 | // setup println() 7 | Serial.begin(155200); 8 | // Init LED pin 9 | pinMode(led, OUTPUT); 10 | } 11 | 12 | /** 13 | * Blink the LED 14 | */ 15 | void loop() { 16 | Serial.println("LED ON!"); 17 | digitalWrite(led, HIGH); 18 | delay(1000); 19 | 20 | Serial.println("LED OFF!"); 21 | digitalWrite(led, LOW); 22 | delay(1000); 23 | } 24 | -------------------------------------------------------------------------------- /tests/data/arturo.art: -------------------------------------------------------------------------------- 1 | ; 8 lines 3 code 3 comments 2 blanks 2 | ; this is a comment 3 | ; this is another comment 4 | 5 | a1: 2 6 | a2: 3.14 ; pi 7 | 8 | a3: 213213 ; another number 9 | -------------------------------------------------------------------------------- /tests/data/asciidoc.adoc: -------------------------------------------------------------------------------- 1 | // 20 lines 5 code 8 comments 7 blanks 2 | 3 | = AsciiDoc title 4 | 5 | A simple paragraph. 6 | 7 | // single line comment 8 | 9 | That should end before a paragraph. 10 | 11 | //// 12 | multi 13 | = Line 14 | 15 | comment 16 | //// 17 | 18 | == Nested title 19 | 20 | Nested titles and paragraphs are fine, too. 21 | -------------------------------------------------------------------------------- /tests/data/asn1.asn1: -------------------------------------------------------------------------------- 1 | -- 34 lines 16 code 11 comments 7 blanks 2 | PKCS-12 { 3 | iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-12(12) 4 | modules(0) pkcs-12(1) } 5 | 6 | -- PKCS #12 v1.1 ASN.1 Module 7 | -- Revised October 27, 2012 8 | 9 | -- This module has been checked for conformance with the ASN.1 standard 10 | -- by the OSS ASN.1 Tools 11 | 12 | DEFINITIONS IMPLICIT TAGS ::= 13 | 14 | BEGIN 15 | 16 | PFX ::= SEQUENCE { 17 | version INTEGER {v3(3)}(v3,...), 18 | authSafe OCTET STRING, 19 | macData MacData /* " " */ OPTIONAL 20 | } 21 | 22 | /* 23 | * Multi line 24 | * 25 | */ 26 | 27 | MacData ::= SEQUENCE { 28 | mac OBJECT IDENTIFIER, 29 | macSalt OCTET STRING, 30 | iterations INTEGER DEFAULT 1 31 | -- Note: The default is for historical reasons and its use is 32 | -- deprecated. 33 | } 34 | END 35 | -------------------------------------------------------------------------------- /tests/data/ats.dats: -------------------------------------------------------------------------------- 1 | //! 42 lines 25 code 9 comments 8 blanks 2 | 3 | (************* 4 | Reference: 5 | https://github.com/ats-lang/ats-lang.github.io/blob/master/DOCUMENT/ATS2TUTORIAL/CODE/chap_stream_vt.dats 6 | **************) 7 | #include "share/atspre_staload.hats" 8 | 9 | /* Lazy-evaluated integer iterator */ 10 | fun from 11 | (n: int): stream_vt(int) = 12 | $ldelay(stream_vt_cons(n, from(n + 1))) 13 | 14 | // Lazy-evaluated prime finder 15 | fun sieve 16 | (ns: stream_vt(int)) 17 | : stream_vt(int) = $ldelay( 18 | let 19 | val ns_con = !ns 20 | val- @stream_vt_cons(n0, ns1) = ns_con 21 | val n0_val = n0 22 | val ns1_val = ns1 23 | 24 | val () = 25 | (ns1 := sieve(stream_vt_filter_cloptr(ns1_val, lam x => x mod n0_val > 0))) 26 | 27 | prval () = fold@(ns_con) 28 | in 29 | ns_con 30 | end 31 | , 32 | ~ns 33 | ) 34 | 35 | // Test run for finding the 1000-th prime number 36 | val thePrimes = sieve(from(2)) 37 | val p1000 = (steam_vt_drop_exn(thePrimes, 1000)).head() 38 | val () = println!("p1000 = ", p1000) 39 | 40 | implement main0 () = {} 41 | 42 | (* End of file *) 43 | -------------------------------------------------------------------------------- /tests/data/awk.awk: -------------------------------------------------------------------------------- 1 | #!/bin/awk -f 2 | # 5 lines 1 code 3 comments 1 blanks 3 | 4 | # This is a comment 5 | { print $0 } 6 | -------------------------------------------------------------------------------- /tests/data/ballerina.bal: -------------------------------------------------------------------------------- 1 | // 40 lines 29 code 6 comments 5 blanks 2 | 3 | # Returns Bob's response to someone talking to him. 4 | # 5 | # + input - whatever is said to Bob 6 | # + return - Bob's response 7 | public function hey(string input) returns string { 8 | string trimmed = input.trim(); 9 | boolean silent = isSilence(trimmed); 10 | boolean asking = isQuestion(trimmed); 11 | boolean yelling = isYelling(trimmed); 12 | 13 | match [silent, yelling, asking] { 14 | [true, _, _] => { 15 | return "Fine. Be that way!"; 16 | } 17 | [_, true, true] => { 18 | return "Calm down, I know what I'm doing!"; 19 | } 20 | [_, true, false] => { 21 | return "Whoa, chill out!"; 22 | } 23 | [_, false, true] => { 24 | return "Sure."; 25 | } 26 | _ => { 27 | return "Whatever."; 28 | } 29 | } 30 | } 31 | 32 | isolated function isSilence(string input) returns boolean => input.length() == 0; 33 | 34 | isolated function isQuestion(string input) returns boolean => input.endsWith("?"); 35 | 36 | function isYelling(string input) returns boolean { 37 | // contains an uppercase letter and does not contain a lowercase letter 38 | return input.includesMatch(re `\p{Lu}`) 39 | && !input.includesMatch(re `\p{Ll}`); 40 | } 41 | -------------------------------------------------------------------------------- /tests/data/bazel.bzl: -------------------------------------------------------------------------------- 1 | # 18 lines 13 code 3 comments 2 blanks 2 | 3 | # build hello-greet 4 | cc_library( 5 | name = "hello-greet", 6 | srcs = ["hello-greet.cc"], 7 | hdrs = ["hello-greet.h"], 8 | ) 9 | 10 | # build hello-world 11 | cc_binary( 12 | name = "hello-world", 13 | srcs = ["hello-world.cc"], 14 | deps = [ 15 | ":hello-greet", 16 | "//lib:hello-time", 17 | ], 18 | ) -------------------------------------------------------------------------------- /tests/data/bean.bean: -------------------------------------------------------------------------------- 1 | ; 27 lines 13 code 6 comments 8 blanks 2 | 3 | option "operating_currency" "EUR" 4 | 5 | 2002-01-01 commodity EUR 6 | name: "Euro" 7 | asset-class: "cash" 8 | 9 | 10 | ; open accounts initially 11 | 2020-09-01 open Equity:Opening-Balances 12 | 2020-09-01 open Assets:Cash EUR 13 | 2020-09-01 open Expenses:Food EUR 14 | 15 | ; put initial money on account 16 | 2020-09-01 pad Assets:Cash Equity:Opening-Balances 17 | 18 | ; verifying starting balance 19 | 2020-09-02 balance Assets:Cash 81.7 EUR 20 | 21 | ; transferring money 22 | 2020-09-03 * "transfer of money" 23 | Assets:Cash -17.7 EUR 24 | Expenses:Food 25 | 26 | ; validating changed balance 27 | 2020-09-04 balance Assets:Cash 64 EUR 28 | -------------------------------------------------------------------------------- /tests/data/bicep.bicep: -------------------------------------------------------------------------------- 1 | //! 50 lines 35 code 8 comments 7 blanks 2 | /* 3 | Bicep is a declarative language, which means the elements can appear in any order. Unlike imperative languages, the order of elements doesn't affect how deployment is processed. 4 | This means you can define resources, variables, and parameters in any order you like. 5 | */ 6 | 7 | metadata description = 'Creates a storage account and a web app' 8 | 9 | @description('The prefix to use for the storage account name.') 10 | @minLength(3) 11 | @maxLength(11) 12 | param storagePrefix string 13 | 14 | param storageSKU string = 'Standard_LRS' 15 | param location string = resourceGroup().location 16 | 17 | var uniqueStorageName = '${storagePrefix}${uniqueString(resourceGroup().id)}' 18 | 19 | var objectExmaple = { 20 | name: 'John' 21 | age: 30 22 | address: ''' 23 | 1 Microsoft Way 24 | Redmond, WA 98052 25 | ''' 26 | } 27 | 28 | // Create a storage account 29 | resource stg 'Microsoft.Storage/storageAccounts@2022-09-01' = { 30 | name: uniqueStorageName 31 | location: location 32 | sku: { 33 | name: storageSKU 34 | } 35 | kind: 'StorageV2' 36 | properties: { 37 | supportsHttpsTrafficOnly: true 38 | } 39 | } 40 | 41 | // Use a module to deploy a web app 42 | // Modules are a way to encapsulate and reuse resources in Bicep 43 | module webModule './webApp.bicep' = { 44 | name: 'webDeploy' 45 | params: { 46 | skuName: 'S1' 47 | location: location 48 | personalInfo: objectExmaple 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/data/bitbake.bb: -------------------------------------------------------------------------------- 1 | # 23 lines 13 code 5 comments 5 blanks 2 | # 3 | # This file was derived from the 'Hello World!' example recipe in the 4 | # Yocto Project Development Manual. 5 | # 6 | 7 | SUMMARY = "Simple helloworld application" 8 | SECTION = "examples" 9 | LICENSE = "MIT" 10 | LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" 11 | 12 | SRC_URI = "file://helloworld.c" 13 | 14 | S = "${WORKDIR}" 15 | 16 | do_compile() { 17 | ${CC} helloworld.c -o helloworld 18 | } 19 | 20 | do_install() { 21 | install -d ${D}${bindir} 22 | install -m 0755 helloworld ${D}${bindir} 23 | } 24 | -------------------------------------------------------------------------------- /tests/data/bqn.bqn: -------------------------------------------------------------------------------- 1 | # 10 lines 3 code 3 comments 4 blanks 2 | 3 | 4 | 256=2⋆8 5 | 6 | # Comment 7 | <⟜'a'⊸/"Big Questions Notation" 8 | 9 | # A magic square of length ⊢ 10 | MS ← (↕-⌈∘÷⟜2)(⊣⌽˘⌾⍉⌽˘)⋈˜⥊⟜↕ט 11 | -------------------------------------------------------------------------------- /tests/data/brightscript.brs: -------------------------------------------------------------------------------- 1 | ' 26 lines 10 code 13 comments 3 blanks 2 | ' /** 3 | ' * @member difference 4 | ' * @memberof module:rodash 5 | ' * @instance 6 | ' * @description Return a new array of items from the first which are not in the second. 7 | ' * @param {Array} first 8 | ' * @param {Array} second 9 | ' * @example 10 | 11 | REM * difference = _.difference([1,2], [2]) 12 | REM * ' => [1] 13 | REM * 14 | REM */ 15 | 16 | Function rodash_difference_(first, second) 17 | result = [] 18 | for each f in first 19 | result.push(f) 'Push array 20 | for each s in second 21 | if m.equal(s,f) then result.pop() 22 | end for 23 | end for 24 | 25 | return result 26 | End Function -------------------------------------------------------------------------------- /tests/data/c.c: -------------------------------------------------------------------------------- 1 | // 50 lines 33 code 8 comments 9 blanks 2 | 3 | /* /* we can't nest block comments in c, but we can start one */ 4 | int main(void) { 5 | char *start = "/*"; 6 | 7 | int x = 1; 8 | x += 2; // end of line comment */ 9 | } 10 | 11 | void foo() { 12 | char *esc = "\"/*escaped quotes in a string and block comment*/\""; 13 | func1(); 14 | func2(); 15 | char *next_line = 16 | "*/ /*string on new line\ 17 | continued to another line\ 18 | bar();\ 19 | */"; 20 | 21 | char *next_line2 = "line1\ 22 | // not a real comment\ 23 | line3*/"; 24 | 25 | /* Block comment 26 | // line comment in a block comment 27 | end block comment*/ 28 | 29 | char *late_start = // " 30 | "wow\ 31 | that's pretty neat"; 32 | 33 | char *late_start2 = /* " */ 34 | "*/ still just a string"; // but this is a line comment 35 | } 36 | 37 | void foobar() { 38 | int a = 4; // /* 39 | int b = 5; 40 | int c = 6; // */ 41 | } 42 | 43 | /*\ 44 | / comment 45 | \*/ 46 | struct Point { 47 | int x; 48 | int y; 49 | int z; 50 | }; 51 | -------------------------------------------------------------------------------- /tests/data/cairo.cairo: -------------------------------------------------------------------------------- 1 | //! 51 lines 32 code 13 comments 6 blanks 2 | //! ```rust 3 | //! fn main () { 4 | //! // Comment 5 | //! 6 | //! println!("Hello World!"); 7 | //! } 8 | //! ``` 9 | 10 | /// The main function 11 | fn main() { 12 | let x: ByteArray = "\"/*##\"\"##\'\'"; 13 | // comment 14 | loop { 15 | if x.len() >= 2 && x[0] == '*' && x[1] == '/' { // found the */ 16 | break; 17 | } 18 | } 19 | } 20 | 21 | fn foo>(name: T) { 22 | let this_ends = 'a "\'test/"*.'; 23 | call1(); 24 | call2(); 25 | let this_does_not = // a // nested // comment " // 26 | ///"*/another /*test 27 | call3(); 28 | //*/"; 29 | } 30 | 31 | fn call1() {} 32 | fn call2() {} 33 | fn call3() {} 34 | 35 | fn foobar() { 36 | let does_not_start: ByteArray = // " 37 | "until here, 38 | test/* 39 | test"; // a quote: " 40 | let also_doesnt_start = 41 | /// " */ 42 | 'until here, 43 | test,'; // another quote: " 44 | } 45 | 46 | fn foo2() { 47 | let a = 4; // /// 48 | let b = '5'; 49 | let c = 6; // /// 50 | } 51 | 52 | -------------------------------------------------------------------------------- /tests/data/cangjie.cj: -------------------------------------------------------------------------------- 1 | /* 50 lines 34 code 8 comments 8 blanks */ 2 | 3 | /* /* we can nest block*/ comments in cangjie */ 4 | main(): Unit { 5 | let start: String = "/*" 6 | 7 | var x: Int64 = 1 8 | x += 2 // end of line comment */ 9 | } 10 | 11 | func foo(): Unit { 12 | let esc: String = "\"/*escaped quotes in a string and block comment*/\""; 13 | let next_line: String = """ 14 | */ /*string on new line 15 | continued to another line 16 | bar(); 17 | */" 18 | """ 19 | 20 | /* Block comment 21 | // line comment in a block comment 22 | end block comment*/ 23 | let late_start: String = // " 24 | ##"wow\ 25 | that's pretty neat"## 26 | 27 | let late_start2: String = /* " */ 28 | "*/ still just a string" // but this is a line comment 29 | } 30 | 31 | func foobar(): Unit { 32 | let a: Int64 = 4 // /* 33 | let b: Int64 = 5 34 | let c: Int64 = 6 // */ 35 | } 36 | 37 | /* \ 38 | / comment 39 | \*/ 40 | struct Point { 41 | let x: Int64 42 | let y: Int64 43 | let z: Int64 44 | 45 | public init(x: Int64, y: Int64, z: Int64) { 46 | this.x = x 47 | this.y = y 48 | this.z = z 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/data/chapel.chpl: -------------------------------------------------------------------------------- 1 | // chapel 24 lines 9 code 9 comments 6 blanks 2 | 3 | // Tidy line comment 4 | 5 | /* Tidy block 6 | comment. 7 | */ 8 | 9 | // Cheeky line comments /* 10 | // */ 11 | 12 | /* Cheeky // block comments */ 13 | 14 | // Caculate a factorial 15 | proc factorial(n: int): int { 16 | var x = 1; // this will eventually be returned 17 | for i in 1..n { 18 | x *= i; 19 | } 20 | return x; 21 | } 22 | 23 | writeln("// this isn't a comment"); 24 | writeln('/* this is also not a comment */'); 25 | -------------------------------------------------------------------------------- /tests/data/cil.cil: -------------------------------------------------------------------------------- 1 | ; 20 lines 15 code 3 comments 2 blanks 2 | ;============= etcd_t ============== 3 | (allow etcd_t proc_sysctl_t (dir (search))) 4 | (allow etcd_t proc_sysctl_t (file (read open))) 5 | (allow etcd_t procfs_t (dir (search getattr))) 6 | (allow etcd_t procfs_t (lnk_file (read))) 7 | (allow etcd_t self (dir (read open search))) 8 | (allow etcd_t self (fifo_file (write read))) 9 | 10 | ;============= kernel_t ============== 11 | (allow kernel_t bin_t (dir (search))) 12 | (allow kernel_t bin_t (file (read execute_no_trans open map execute))) 13 | (allow kernel_t debugfs_t (dir (search))) 14 | (allow kernel_t device_t (blk_file (create setattr))) 15 | (allow kernel_t device_t (chr_file (write create setattr))) 16 | (allow kernel_t self (capability (dac_override mknod))) 17 | (allow kernel_t self (dir (write add_name search))) 18 | (allow kernel_t self (file (write create open))) 19 | 20 | (filecon "/.extra(/.*)?" any (system_u object_r extra_t (systemLow systemLow))) 21 | -------------------------------------------------------------------------------- /tests/data/circom.circom: -------------------------------------------------------------------------------- 1 | // 34 lines 23 code 7 comments 4 blanks 2 | pragma circom 2.0.8; 3 | 4 | /* 5 | * Sum an array of non-zero values. 6 | */ 7 | function sum(values, size) { 8 | var sum = 0; 9 | for (var i = 0; i < size; i++) { 10 | assert(values[i] != 0); 11 | sum += values[i]; 12 | } 13 | log("sum = ", sum); 14 | return sum; 15 | } 16 | 17 | /* 18 | * Ensure x is a solution to x^5 - 2x^4 + 5x - 4 = 0. 19 | */ 20 | template Polynomial() { 21 | signal input x; 22 | signal x2; 23 | signal x4; 24 | signal x5; 25 | signal output y; 26 | 27 | x2 <== x * x; 28 | x4 <== x2 * x2; 29 | x5 <== x4 * x; 30 | y <== x5 - 2 * x4 + 5 * x - 4; // y = x^5 - 2 * x^4 + 5x - 4. 31 | y === 0; // Ensure that y = 0. 32 | } 33 | 34 | component main = Polynomial(); 35 | -------------------------------------------------------------------------------- /tests/data/clojure.clj: -------------------------------------------------------------------------------- 1 | ; 19 lines 13 code 3 comments 3 blanks 2 | 3 | (ns clojure) 4 | 5 | ; Below is a function 6 | (defn a-fn 7 | "Docstring with a column ;" 8 | [a b] 9 | (+ 1 1)) 10 | 11 | (defn a-fn2 12 | ;"Not a doc" 13 | "Doc doc again" 14 | [a b] ; a and b right? 15 | (let [multiline "I'm 16 | a multline 17 | ; string 18 | "] 19 | (str multline a b))) 20 | -------------------------------------------------------------------------------- /tests/data/clojurec.cljc: -------------------------------------------------------------------------------- 1 | ; 19 lines 13 code 3 comments 3 blanks 2 | 3 | (ns clojure) 4 | 5 | ; Below is a function 6 | (defn a-fn 7 | "Docstring with a column ;" 8 | [a b] 9 | (+ 1 1)) 10 | 11 | (defn a-fn2 12 | ;"Not a doc" 13 | "Doc doc again" 14 | [a b] ; a and b right? 15 | (let [multiline "I'm 16 | a multline 17 | ; string 18 | "] 19 | (str multline a b))) 20 | -------------------------------------------------------------------------------- /tests/data/clojurescript.cljs: -------------------------------------------------------------------------------- 1 | ; 19 lines 13 code 3 comments 3 blanks 2 | 3 | (ns clojure) 4 | 5 | ; Below is a function 6 | (defn a-fn 7 | "Docstring with a column ;" 8 | [a b] 9 | (+ 1 1)) 10 | 11 | (defn a-fn2 12 | ;"Not a doc" 13 | "Doc doc again" 14 | [a b] ; a and b right? 15 | (let [multiline "I'm 16 | a multline 17 | ; string 18 | "] 19 | (str multline a b))) 20 | -------------------------------------------------------------------------------- /tests/data/cmake.cmake: -------------------------------------------------------------------------------- 1 | # 25 lines 16 code 3 comments 6 blanks 2 | 3 | SET(_POSSIBLE_XYZ_INCLUDE include include/xyz) 4 | SET(_POSSIBLE_XYZ_EXECUTABLE xyz) 5 | SET(_POSSIBLE_XYZ_LIBRARY XYZ) 6 | 7 | # this is a comment 8 | IF(XYZ_FIND_VERSION_MAJOR AND XYZ_FIND_VERSION_MINOR) 9 | SET(_POSSIBLE_SUFFIXES "${XYZ_FIND_VERSION_MAJOR}${XYZ_FIND_VERSION_MINOR}" "${XYZ_FIND_VERSION_MAJOR}.${XYZ_FIND_VERSION_MINOR}" "-${XYZ_FIND_VERSION_MAJOR}.${XYZ_FIND_VERSION_MINOR}") # not counted 10 | ELSE(XYZ_FIND_VERSION_MAJOR AND XYZ_FIND_VERSION_MINOR) 11 | SET(_POSSIBLE_SUFFIXES "67" "92" "352.9" "0.0.8z") 12 | ENDIF(XYZ_FIND_VERSION_MAJOR AND XYZ_FIND_VERSION_MINOR) 13 | 14 | FOREACH(_SUFFIX ${_POSSIBLE_SUFFIXES}) 15 | LIST(APPEND _POSSIBLE_XYZ_INCLUDE "include/XYZ${_SUFFIX}") 16 | LIST(APPEND _POSSIBLE_XYZ_EXECUTABLE "XYZ${_SUFFIX}") 17 | LIST(APPEND _POSSIBLE_XYZ_LIBRARY "XYZ${_SUFFIX}") 18 | ENDFOREACH(_SUFFIX) # not counted 19 | 20 | FIND_PROGRAM(XYZ_EXECUTABLE 21 | NAMES ${_POSSIBLE_XYZ_EXECUTABLE} 22 | ) 23 | 24 | # this is also a comment 25 | 26 | -------------------------------------------------------------------------------- /tests/data/codeql.ql: -------------------------------------------------------------------------------- 1 | //! 40 lines 17 code 15 comments 8 blanks 2 | 3 | /** 4 | * @name fu 5 | * @description bar 6 | * 7 | * Rerum similique consequatur non dolor sit. Autem doloribus sed in sint 8 | * ratione sit voluptates at. Nihil ut fugiat ab ut aliquid consequatur sunt 9 | * ullam. Adipisci voluptatem hic dicta. 10 | */ 11 | 12 | // asdf 13 | 14 | import cpp 15 | private import test.foo.bar.baz 16 | 17 | /** 18 | * Another comment. 19 | */ 20 | class C extends Expr { 21 | C () { 22 | // single comment 23 | not this.test() and 24 | not this.what() 25 | } 26 | 27 | private predicate what() { 28 | /* TODO */ 29 | this.isAbstract() 30 | } 31 | 32 | predicate test() { this = "what" } 33 | } 34 | 35 | from Function f 36 | where 37 | f.getName() = "function" and /* inline comment */ 38 | f.getArgument(0).asExpr() instanceof FooBar 39 | select f, "function" 40 | 41 | -------------------------------------------------------------------------------- /tests/data/cogent.cogent: -------------------------------------------------------------------------------- 1 | -- 7 lines 2 code 2 comments 3 blanks 2 | 3 | type A -- uncounted comment 4 | 5 | -- comment 6 | 7 | type B 8 | -------------------------------------------------------------------------------- /tests/data/cpp.cpp: -------------------------------------------------------------------------------- 1 | /* 46 lines 37 code 3 comments 6 blanks */ 2 | 3 | #include 4 | 5 | // bubble_sort_function 6 | void bubble_sort(int a[10], int n) { 7 | int t; 8 | int j = n; 9 | int s = 1; 10 | while (s > 0) { 11 | s = 0; 12 | int i = 1; 13 | while (i < j) { 14 | if (a[i] < a[i - 1]) { 15 | t = a[i]; 16 | a[i] = a[i - 1]; 17 | a[i - 1] = t; 18 | s = 1; 19 | } 20 | i++; 21 | } 22 | j--; 23 | } 24 | } 25 | 26 | int main() { 27 | int a[] = {4, 65, 2, -31, 0, 99, 2, 83, 782, 1}; 28 | int n = 10; 29 | int i = 0; 30 | 31 | printf(R"(Before sorting:\n\n" )"); 32 | // Single line comment 33 | while (i < n) { 34 | printf("%d ", a[i]); 35 | i++; 36 | } 37 | 38 | bubble_sort(a, n); 39 | 40 | printf("\n\nAfter sorting:\n\n"); 41 | i = 0; 42 | while (i < n) { 43 | printf("%d ", a[i]); 44 | i++; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/data/crystal.cr: -------------------------------------------------------------------------------- 1 | # 20 lines 14 code 2 comments 4 blanks 2 | x = 3 3 | if x < 2 4 | p = "Smaller" 5 | else 6 | p = "Bigger" 7 | end 8 | 9 | multiline_string = "first line 10 | second line" 11 | 12 | heredoc = <<-SOME 13 | hello 14 | SOME 15 | 16 | # testing. 17 | while x > 2 && x < 10 18 | x += 1 19 | end 20 | 21 | -------------------------------------------------------------------------------- /tests/data/csharp.cs: -------------------------------------------------------------------------------- 1 | // 26 lines 14 code 9 comments 3 blanks 2 | namespace Ns 3 | { 4 | /* 5 | 6 | multi-line comment 7 | 8 | */ 9 | public class Cls 10 | { 11 | private const string BasePath = @"a:\"; 12 | 13 | [Fact] 14 | public void MyTest() 15 | { 16 | // Arrange. 17 | Foo(); 18 | 19 | // Act. 20 | Bar(); 21 | 22 | // Assert. 23 | Baz(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/data/cuda.cu: -------------------------------------------------------------------------------- 1 | /* 7 lines 4 code 2 comments 1 blanks */ 2 | 3 | // add vector 4 | __host__ void add(const int* a, const int* b, int* c) { 5 | int i = threadIdx.x; 6 | c[i] = a[i] + b[i]; 7 | } 8 | -------------------------------------------------------------------------------- /tests/data/cue.cue: -------------------------------------------------------------------------------- 1 | // 12 lines 8 code 2 comments 2 blanks 2 | 3 | // A documentation comment 4 | map: { 5 | normal: "normal string" // inline comment (not counted) 6 | 7 | content: """ 8 | Multi-line string 9 | """ 10 | raw: #"A newline is \#n written as "\n"."# 11 | byte: '\U0001F604' 12 | } 13 | -------------------------------------------------------------------------------- /tests/data/cython.pyx: -------------------------------------------------------------------------------- 1 | # 29 lines, 21 code, 3 comments, 5 blanks 2 | 3 | 4 | def add(x, y): 5 | ''' 6 | Hello World 7 | # Real Second line 8 | Second line 9 | ''' 10 | string = "Hello World #\ 11 | " 12 | y += len(string) 13 | # Add the two numbers. 14 | x + y 15 | 16 | 17 | cdef add2(x, y): 18 | """ 19 | Hello World 20 | # Real Second line 21 | Second line 22 | 23 | Note that docstring lines are counted as code 24 | """ 25 | 26 | string = "Hello World" 27 | y += len(string) 28 | # Add the two numbers. 29 | x + y 30 | -------------------------------------------------------------------------------- /tests/data/d.d: -------------------------------------------------------------------------------- 1 | /* 8 lines 5 code 1 comments 2 blanks */ 2 | 3 | void main() { 4 | auto x = 5; /+ a /+ nested +/ comment /* +/ 5 | writefln("hello"); 6 | auto y = 4; // */ 7 | } 8 | 9 | -------------------------------------------------------------------------------- /tests/data/d2.d2: -------------------------------------------------------------------------------- 1 | # 15 lines 4 code 6 comments 5 blanks 2 | 3 | # Comments start with a hash character and continue until the next newline or EOF. 4 | x -> y 5 | 6 | x -> y # I am at the end 7 | 8 | '#x' -> "#y" 9 | 10 | """ 11 | This is a 12 | block comment 13 | """ 14 | 15 | y -> z 16 | -------------------------------------------------------------------------------- /tests/data/dhall.dhall: -------------------------------------------------------------------------------- 1 | -- 16 lines 9 code 5 comments 2 blanks 2 | {- A comment within the interior of a multi-line literal counts as part of the 3 | literal 4 | -} 5 | 6 | '' 7 | -- Hello 8 | {- world -} 9 | '' 10 | { some = "thing" 11 | 12 | , keys = ["can" 13 | , "have", 14 | -- wait for it 15 | "lists"] 16 | } 17 | -------------------------------------------------------------------------------- /tests/data/dreammaker.dm: -------------------------------------------------------------------------------- 1 | // 17 lines 7 code 6 comments 4 blanks 2 | /* 3 | * /* Hello! */ 4 | */ 5 | 6 | /mob 7 | // I can rely on this file to exist on disk. 8 | var/some_file = './/dreammaker.dm' 9 | 10 | /mob/Login() 11 | // Not counted. /* */ 12 | world << "// Say hello to [src]!" 13 | 14 | src << browse({" 15 | /*Link*/ 16 | "}, "window=google") 17 | 18 | -------------------------------------------------------------------------------- /tests/data/dust.dust: -------------------------------------------------------------------------------- 1 | {! 10 lines 2 code 5 comments 3 blanks !} 2 | 3 | {! All Dust comments are multiline comments. And there's no quoting 4 | comment openers and closers. Instead there are escape sequences 5 | for producing literal brackets in template output: {~lb} outputs a 6 | left-bracket.!}

Hello 7 | 8 | world!

{! More comments !} 9 | 10 |

~{lb}Goodbye, world~{rb}

11 | -------------------------------------------------------------------------------- /tests/data/ebuild.ebuild: -------------------------------------------------------------------------------- 1 | # 16 lines 9 code 2 comments 5 blanks 2 | 3 | # test comment 4 | 5 | EAPI=8 6 | 7 | DESCRIPTION="ebuild file" 8 | HOMEPAGE="https://foo.example.org/" 9 | SRC_URI="ftp://foo.example.org/${P}.tar.gz" 10 | 11 | LICENSE="MIT" 12 | SLOT="0" 13 | 14 | src_compile() { 15 | : 16 | } 17 | -------------------------------------------------------------------------------- /tests/data/edgeql.edgeql: -------------------------------------------------------------------------------- 1 | # 28 lines 21 code 3 comments 4 blanks 2 | 3 | select User { 4 | name, 5 | friends: { 6 | name 7 | }, 8 | has_i := .friends.name ilike '%i%', 9 | has_o := .friends.name ilike '%o%', 10 | } filter .has_i or .has_o; 11 | 12 | select {} ?? User {name}; 13 | 14 | # update the user with the name 'Alice Smith' 15 | with module example 16 | update User 17 | filter .name = 'Alice Smith' 18 | set { 19 | name := 'Alice J. Smith' 20 | }; 21 | 22 | # update all users whose name is 'Bob' 23 | with module example 24 | update User 25 | filter .name like 'Bob%' 26 | set { 27 | name := User.name ++ '*' 28 | }; 29 | -------------------------------------------------------------------------------- /tests/data/edn.edn: -------------------------------------------------------------------------------- 1 | ; 11 lines 6 code 2 comments 3 blanks 2 | 3 | ; Just some random data 4 | 5 | {:a [ 6 | 1] 7 | 8 | :b 1 ; this doesn't count as a comment 9 | :c {1 1 10 | 2 2} 11 | :d [1 2 3]} 12 | -------------------------------------------------------------------------------- /tests/data/eight.8th: -------------------------------------------------------------------------------- 1 | \ 22 lines 9 code 8 comments 5 blanks 2 | 3 | (* multiline comments 4 | (* a nested 5 | comment *) 6 | * 7 | *) 8 | 9 | -- here's a single line comment 10 | "Hello, " var, foo -- line ending comment 11 | 12 | \ here's another single line comment 13 | "!" var, bar \ a different line ending comment 14 | 15 | : hello \ s -- 16 | foo @ s:<+ 17 | bar @ s:+ 18 | . cr 19 | ; 20 | 21 | "World" hello 22 | bye 23 | -------------------------------------------------------------------------------- /tests/data/elvish.elv: -------------------------------------------------------------------------------- 1 | # 16 lines, 9 code, 5 blanks, 2 comments 2 | echo "This is a 3 | multiline string 4 | # with a hash 5 | in it." 6 | 7 | echo 'This is a single-quoted string.' 8 | 9 | # This is a comment. 10 | 11 | use re 12 | 13 | edit:after-readline = [ 14 | [line]{ print "\e]2;"$line"\a" > /dev/tty } 15 | ] 16 | 17 | -------------------------------------------------------------------------------- /tests/data/emacs_dev_env.ede: -------------------------------------------------------------------------------- 1 | ;; 16 lines 6 code 7 comments 3 blanks 2 | 3 | ;; This is an EDE Project file 4 | 5 | ;; Object ede-proj-project 6 | ;; EDE project file. 7 | (ede-proj-project "ede-proj-project" 8 | :name "my-proj" 9 | :version "1.0.0" 10 | :file "Project.ede" 11 | :targets (list 12 | )) 13 | 14 | ;; Local Variables: 15 | ;; mode: emacs-lisp 16 | ;; End: 17 | -------------------------------------------------------------------------------- /tests/data/emacs_lisp.el: -------------------------------------------------------------------------------- 1 | ;; 21 lines 11 code 6 comments 4 blanks 2 | 3 | ; This is a comment line 4 | ;; This too! 5 | ;;; This 3! 6 | ;;;; This 4! 7 | 8 | (setq some-global-var nil) ;Comment 9 | 10 | ;;;###autoload 11 | (defun some-fn () 12 | "Some function." 13 | (interactive) 14 | (message "I am some function")) 15 | 16 | (defun fundamental-mode () 17 | "Major mode not specialized for anything in particular. 18 | Other major modes are defined by comparison with this one." 19 | (interactive) 20 | (kill-all-local-variables) 21 | (run-mode-hooks)) 22 | -------------------------------------------------------------------------------- /tests/data/emojicode.🍇: -------------------------------------------------------------------------------- 1 | 💭 24 lines 10 code 10 comments 4 blanks 2 | 3 | 📘 4 | This package is neat. 5 | 📘 6 | 7 | 💭🔜 Comment! 💭🔜 nested? 🔚💭 8 | 9 | 📗 10 | Simple docstring 11 | with a quote 🔤 12 | 📗 13 | 🐇👨‍🚀🍇 14 | 💭 More quotes! 🔤 15 | 16 | 🐇❗👋 name🔡 🍇 17 | 😀 🍪 🔤Hello there, 🔤 name 🔤! ❌🔤 18 | 💭 no comment here🔤 🍪❗ 19 | 🍉 20 | 🍉 21 | 22 | 🏁 🍇 23 | 👋🐇👨‍🚀 🔤Karen🔤❗ 24 | 🍉 25 | -------------------------------------------------------------------------------- /tests/data/esdl.esdl: -------------------------------------------------------------------------------- 1 | # 20 lines 13 code 4 comments 3 blanks 2 | 3 | # no module block 4 | type default::Movie { 5 | required property title -> str; 6 | # the year of release 7 | property year -> int64; 8 | required link director -> default::Person; 9 | required multi link actors -> default::Person; 10 | } 11 | 12 | type default::Person { 13 | required property first_name -> str; 14 | required property last_name -> str; 15 | } 16 | 17 | abstract link friends_base { 18 | # declare a specific title for the link 19 | annotation title := 'Close contacts'; 20 | } 21 | -------------------------------------------------------------------------------- /tests/data/example.umpl: -------------------------------------------------------------------------------- 1 | ! 68 lines 58 code 2 comments 8 blanks 2 | 3 | create yum with 5 4 | create num with ((plus 7 6 6 yum))> 5 | (num)> 6 | ((plus 1 num))> ! prints 17, the greater than signifies that this should be the printed, the bang symbol signifies a comment, numbers must be in hexadecimal but will be printed in decimal 7 | 8 | potato 😂3 ⧼ ! to create a function we use the potato keyword, functions must be nameed with a single emoji, we put the number of args and then ⧼⧽ is where the code goes 9 | loop ⧼ 10 | (` `)> 11 | if {$3} ⧼ 12 | break 13 | ⧽ else ⧼ 14 | continue 15 | ⧽ 16 | ⧽ 17 | potato 😂 1 ⧼ 18 | ((minus 1 10))> ! prints -15 19 | ⧽ 20 | create final with ((add $1 $2))< ! ! we use the create keyword to create a variable and the with keyword to assign a value to the variable, to refrence the args from a function use $1 for the first arg and so on 21 | ! adds both arg1 and arg2, the less than signifies that this should not be the printed and sets it to the final variable 22 | return: ! we use (:) colon whe returning nothing 23 | ⧽ 24 | ((new 😂 10 1 0x1A))> ! we use the new keyword to call a function followed by function names, prints 32, when the first digit of number is a letre prefix with 0x 25 | 26 | list it with [((not true))> 0] ! creates a list with the values 1,2 (in hex), list can only have two elements and you cant declare recursive lists like: [0 [1 1]], but if you have an identiifer (d) that points to a list you can do: [9 d] 27 | ((set-with it.first 2)) ! prints false 33 | ((set-with other-bool true))< ! we set other-bool to true 34 | 35 | if {other-bool} ⧼ ! the {} must evalte to a boolean, we can also use eq, ne lt, le etc 36 | (`hello`)> ! the bactick (`) is used to encapsulate a string 37 | ⧽ else ⧼ 38 | (`by`)> 39 | ⧽ 40 | 41 | if {true} ⧼ ! there is now else, use nested if elses, condotins must be in {} and we can use nested () within the 42 | ((minus 1 10))> ! prints -15 43 | ⧽ else ⧼ 44 | ((plus 1 10))> ! prints 17 45 | ⧽ 46 | 47 | loop ⧼ 48 | potato 😂 1 ⧼ 49 | ((minus 1 10))> ! prints -15 50 | ⧽ 51 | create inputs with ((input `continue?`))< 52 | if {((eq inputs `y`))<} ⧼ ! there is now else, use nested if elses, condotins must be in {} and we can use nested () within the 53 | potato 😂 1 ⧼ 54 | ((minus 1 10))> ! prints -15 55 | ⧽ 56 | continue 57 | ⧽ else ⧼ 58 | potato 😂 1 ⧼ 59 | ((minus 1 10))> ! prints -15 60 | ⧽ 61 | break ! what the if/esle do can be nothing if you dont pu anything in the parenthesis 62 | ⧽ 63 | ((inputs `continue?`))< 64 | ⧽ 65 | ((new 😂 10 190 0x1A))> ! we use the new keyword to call a function followed by function names, prints 32, when the first digit of number is a letre prefix with 0x 66 | 67 | ((set-with bool (input `ads`)))> 68 | create inputs with ((input `continue?`))< 69 | -------------------------------------------------------------------------------- /tests/data/factor.factor: -------------------------------------------------------------------------------- 1 | ! 14 lines, 5 code, 6 comments, 3 blanks 2 | 3 | /* we can use some dependencies */ 4 | USING: math multiline sequences ; 5 | 6 | ! this is a vocabulary 7 | IN: my-vocab 8 | 9 | ! this comment describes this function 10 | : add ( x y -- z ) 11 | "Hello World !\ 12 | " length /* 13 | Add the three numbers. 14 | */ + + ; 15 | -------------------------------------------------------------------------------- /tests/data/fennel.fnl: -------------------------------------------------------------------------------- 1 | ;; 18 lines 8 code 5 comments 5 blanks 2 | 3 | ; this is a ; single comment 4 | ;;;; this is also a single comment ;;;;;; 5 | 6 | ; "this is a comment too!" 7 | 8 | (local variable "I ;am a ;variable!") 9 | 10 | ; (print "\"I am commented out!\"") 11 | (print "\"Hello world!\"") ; this is an ; end of line comment 12 | (print "This is not a comment: ;") 13 | (print "This is a 14 | multiline string") 15 | 16 | (fn somefn [x] 17 | (print "I am some function.") 18 | (print "My parameter is " (string.format "\"%s\"" x))) 19 | -------------------------------------------------------------------------------- /tests/data/flatbuffers.fbs: -------------------------------------------------------------------------------- 1 | // 34 lines 21 code 6 comments 7 blanks 2 | 3 | include "another_schema.fbs"; 4 | 5 | namespace Example; 6 | 7 | // one line comment 8 | enum PhoneType: byte { 9 | MOBILE, 10 | HOME, 11 | WORK 12 | } 13 | 14 | /* block comment 15 | another line 16 | end */ 17 | table PhoneNumber { 18 | number: string; 19 | type: PhoneType; 20 | } 21 | 22 | /// documentation comment 23 | table Person { 24 | name: string; 25 | id: int32; 26 | email: string; 27 | phones: [PhoneNumber]; // a stray quote " 28 | } 29 | 30 | table AddressBook { 31 | people: /* a block comment inside code */ [Person]; 32 | } 33 | 34 | root_type AddressBook; /* block /* comments cannot be nested (except the start comment) */ 35 | -------------------------------------------------------------------------------- /tests/data/forgecfg.cfg: -------------------------------------------------------------------------------- 1 | # 79 lines 20 code 40 comments 19 blanks 2 | 3 | # Configuration file 4 | 5 | ~CONFIG_VERSION: 0.4.0 6 | 7 | ########################################################################################################## 8 | # advanced 9 | #--------------------------------------------------------------------------------------------------------# 10 | # Advanced config options to change the way JEI functions. 11 | ########################################################################################################## 12 | 13 | advanced { 14 | # Move the JEI search bar to the bottom center of the screen. [default: false] 15 | B:centerSearchBarEnabled=true 16 | B:debugModeEnabled=false 17 | 18 | # Choose if JEI should give ingredients direct to the inventory (inventory) or pick them up with the mouse (mouse_pickup). 19 | # [Default: mouse_pickup] 20 | # [Valid: [inventory, mouse_pickup]] 21 | S:giveMode=inventory 22 | 23 | # The maximum width of the ingredient list. [range: 4 ~ 100, default: 100] 24 | I:maxColumns=100 25 | 26 | # The maximum height of the recipe GUI. [range: 175 ~ 5000, default: 350] 27 | I:maxRecipeGuiHeight=350 28 | 29 | # How the mod name should be formatted in the tooltip for JEI GUIs. Leave blank to disable. [Default: blue italic] [Valid: [black, dark_blue, dark_green, dark_aqua, dark_red, dark_purple, gold, gray, dark_gray, blue, green, aqua, red, light_purple, yellow, white, obfuscated, bold, strikethrough, underline, italic]] 30 | S:modNameFormat=blue italic 31 | 32 | # Enable JEI memory usage optimizations. [default: true] 33 | B:optimizeMemoryUsage=true 34 | } 35 | 36 | 37 | ########################################################################################################## 38 | # search 39 | #--------------------------------------------------------------------------------------------------------# 40 | # Options relating to the search bar. 41 | ########################################################################################################## 42 | 43 | search { 44 | # Search mode for Colors (prefix: ^) 45 | # [Default: disabled] 46 | # [Valid: [enabled, require_prefix, disabled]] 47 | S:colorSearchMode=DISABLED 48 | 49 | # Search mode for Creative Tab Names (prefix: %) 50 | # [Default: disabled] 51 | # [Valid: [enabled, require_prefix, disabled]] 52 | S:creativeTabSearchMode=DISABLED 53 | 54 | # Search mode for Mod Names (prefix: @) 55 | # [Default: require_prefix] 56 | # [Valid: [enabled, require_prefix, disabled]] 57 | S:modNameSearchMode=require_prefix 58 | 59 | # Search mode for Ore Dictionary Names (prefix: $) 60 | # [Default: disabled] 61 | # [Valid: [enabled, require_prefix, disabled]] 62 | S:oreDictSearchMode=require_prefix 63 | 64 | # Search mode for resources ids (prefix: &) 65 | # [Default: disabled] 66 | # [Valid: [enabled, require_prefix, disabled]] 67 | S:resourceIdSearchMode=enabled 68 | 69 | # Search mode for Tooltips (prefix: #) 70 | # [Default: enabled] 71 | # [Valid: [enabled, require_prefix, disabled]] 72 | S:tooltipSearchMode=enabled 73 | } 74 | 75 | 76 | searchadvancedtooltips { 77 | # config.jei.searchAdvancedTooltips.search.comment [default: false] 78 | B:search=false 79 | } 80 | -------------------------------------------------------------------------------- /tests/data/fsharp.fs: -------------------------------------------------------------------------------- 1 | (* 15 lines 6 code 5 comments 4 blanks *) 2 | 3 | // Comment 4 | 5 | let foo = (* 6 | Comment 7 | *) 8 | 5 9 | 10 | let bar = "(* 11 | Code 12 | *)" 13 | 14 | let baz = @"a:\" 15 | // Comment 16 | -------------------------------------------------------------------------------- /tests/data/fstar.fst: -------------------------------------------------------------------------------- 1 | (* 11 lines 3 code 5 comments 3 blanks *) 2 | 3 | module Hello 4 | 5 | (* multi 6 | line 7 | comment *) 8 | open FStar.IO // uncounted comment 9 | 10 | // single line comment 11 | let main = print_string "Hello, F*!\n" (* uncounted comment *) 12 | -------------------------------------------------------------------------------- /tests/data/ftl.ftl: -------------------------------------------------------------------------------- 1 | <#-- 10 lines 5 code 3 comments 2 blanks --> 2 | <#ftl output_format="plainText"/> 3 | 4 | <#-- Define the print macro --> 5 | <#macro print text> 6 | ${text} 7 | 8 | 9 | <#-- Print "Hello world" --> 10 | <@print "Hello world"/> 11 | -------------------------------------------------------------------------------- /tests/data/futhark.fut: -------------------------------------------------------------------------------- 1 | -- 8 lines 2 code 3 comments 3 blanks 2 | 3 | -- this is a test file 4 | 5 | -- add two 6 | let f (x: i32) = x + 2 7 | 8 | let main = f -- eta expand 9 | -------------------------------------------------------------------------------- /tests/data/gas.S: -------------------------------------------------------------------------------- 1 | // 67 lines 46 code 10 comments 11 blanks 2 | #include "config.h" 3 | 4 | /* BIG FAT WARNING GOES HERE */ 5 | #define dbg(char) \ 6 | mov \char, %ax ;\ 7 | out %ax, $0xe9 ;\ 8 | #endif 9 | 10 | .align 16 11 | .code16 12 | .section .resettext, "xa", @progbits 13 | reset_vector: 14 | cli 15 | jmp switch_modes 16 | 17 | .section .text 18 | switch_modes: 19 | /* 20 | * The developer manual builds up the GDT, but since it should get 21 | * cached by the CPU, we can just have it in the flash. 22 | */ 23 | mov %cs, %ax 24 | mov %ax, %ds 25 | 26 | /* Enable protected mode (PE) */ 27 | mov %cr0, %eax 28 | or $1, %al 29 | mov %eax, %cr0 30 | 31 | ljmpl $0x8,$protected_mode 32 | 33 | .code32 34 | protected_mode: 35 | mov $0x10, %ax 36 | mov %ax, %ds 37 | mov %ax, %es 38 | mov %ax, %fs 39 | mov %ax, %gs 40 | mov %ax, %ss 41 | 42 | 43 | gdt_desc: 44 | .word egdt - gdt - 1 45 | .long gdt 46 | 47 | .align 8 48 | gdt: 49 | // 0 segment 50 | .long 0, 0 51 | 52 | // code (0x8) 53 | .word 0xffff // limit 15:0 54 | .word 0x0 // base 15:0 55 | .byte 0x0 // base 23:16 56 | .byte 0x9b // present, ring 0, executable, !conforming, readable, accessed 57 | .byte 0xcf // granularity size, limit[19:16] = f 58 | .byte 0x0 // base 31:24 59 | 60 | // data (0x10) 61 | .word 0xffff // limit 15:0 62 | .word 0x0 // base 15:0 63 | .byte 0x0 // base 23:16 64 | .byte 0x93 // present, priv=0, !executable, stack down, writable, accessed 65 | .byte 0xcf // granularity=1 size=1, limit 19:16 = f 66 | .byte 0x0 // base 31:24 67 | egdt: 68 | -------------------------------------------------------------------------------- /tests/data/gdb.gdb: -------------------------------------------------------------------------------- 1 | # 15 lines 7 code 5 comments 3 blanks 2 | # 3 | # This is a comment line. We don't have multi-comment lines 4 | # 5 | 6 | macro define offsetof(_type, _memb) ((long)(&((_type *)0)->_memb)) 7 | 8 | break foo 9 | continue 10 | 11 | # Let's have something print when a breakpoint is hit. 12 | commands 2 13 | p i 14 | continue 15 | end 16 | -------------------------------------------------------------------------------- /tests/data/gdshader.gdshader: -------------------------------------------------------------------------------- 1 | // 24 lines 6 code 13 comments 5 blanks 2 | /* 3 | test 4 | test 5 | test 6 | */ 7 | 8 | /* /** */ 9 | 10 | void fragment() { 11 | // there is not any string in gdshader 12 | int x, b, c; 13 | float p, q, r; 14 | if(b == c) { 15 | 16 | } 17 | /** 18 | //sdsadasdasdasd /* 19 | **/ 20 | 21 | /* // odpwopdw 22 | // */ 23 | } 24 | 25 | -------------------------------------------------------------------------------- /tests/data/gherkin.feature: -------------------------------------------------------------------------------- 1 | # 13 lines 8 code 3 comments 2 blanks 2 | Feature: Guess the word 3 | 4 | # The first example has two steps 5 | Scenario: Maker starts a game 6 | When the Maker starts a game 7 | Then the Maker waits for a Breaker to join 8 | 9 | # The second example has three steps 10 | Scenario: Breaker joins a game 11 | Given the Maker has started a game with the word "silky" 12 | When the Breaker joins the Maker's game 13 | Then the Breaker must guess a word with 5 characters 14 | -------------------------------------------------------------------------------- /tests/data/gleam.gleam: -------------------------------------------------------------------------------- 1 | //// 34 lines 24 code 4 comments 6 blanks 2 | 3 | import gleam/option.{Option, None} 4 | import gleam/io 5 | 6 | pub type LoadedBool { 7 | Yup 8 | AlsoYup 9 | } 10 | 11 | pub external type Person 12 | 13 | pub opaque type Cat { 14 | Cat( 15 | name: String, 16 | age: Int, 17 | is_cute: LoadedBool, 18 | owner: Some(Person), 19 | ) 20 | } 21 | 22 | pub fn main() { 23 | let jane = // Here is a quote " 24 | new_kitten(called: "Jane") 25 | let kira = new_kitten(called: "Kira") 26 | io.println("Two kitties!") 27 | } 28 | 29 | /// A new baby kitten 30 | /// 31 | fn new_kitten(called name: String) -> Cat { 32 | // No owner yet! 33 | Cat(name: name, age: 0, is_cute: Yup, owner: None) 34 | } 35 | -------------------------------------------------------------------------------- /tests/data/glimmer_js.gjs: -------------------------------------------------------------------------------- 1 | // 27 lines, 18 code, 6 comments, 3 blanks 2 | import { helper } from '@ember/component/helper'; 3 | import { modifier } from 'ember-modifier'; 4 | 5 | // A single-line comment 6 | const plusOne = helper(([num]) => num + 1); 7 | 8 | /** 9 | * A multi-line comment 10 | */ 11 | const setScrollPosition = modifier((element, [position]) => { 12 | element.scrollTop = position 13 | }); 14 | 15 | 28 | -------------------------------------------------------------------------------- /tests/data/glimmer_ts.gts: -------------------------------------------------------------------------------- 1 | // 18 lines, 10 code, 6 comments, 2 blanks 2 | import type { TemplateOnlyComponent } from '@glimmer/component'; 3 | 4 | // A single-line comment 5 | const localVariable = 'foo'; 6 | 7 | /** 8 | * A multi-line comment 9 | */ 10 | const Greet: TemplateOnlyComponent<{ name: string }> = 19 | -------------------------------------------------------------------------------- /tests/data/gml.gml: -------------------------------------------------------------------------------- 1 | /* 17 lines 5 code 9 comments 3 blanks */ 2 | 3 | /* here's a comment */ 4 | 5 | /* 6 | this is also 7 | ...a comment! 8 | */ 9 | 10 | var a = 0; 11 | // @function b(c) 12 | // hi! 13 | function b(c) { 14 | d = 5; 15 | // how are you? 16 | } 17 | e = "good how r u"; -------------------------------------------------------------------------------- /tests/data/go.go: -------------------------------------------------------------------------------- 1 | // 37 lines 24 code 6 comments 7 blanks 2 | 3 | // Package main is a test file. 4 | package main 5 | 6 | import ( 7 | "errors" 8 | ) 9 | 10 | /* /**/ 11 | func main() { 12 | start := "/*" 13 | 14 | for { 15 | if len(start) >= 2 && start[1] == '*' && start[0] == '/' { // found the */ 16 | break 17 | } 18 | } 19 | 20 | if err := Foo(42, start); err != nil { 21 | panic(err) 22 | } 23 | } 24 | 25 | // Foo is a function. /* nested comment */ 26 | func Foo( 27 | // first 28 | a int, 29 | s string, /* second */ 30 | ) (err error) { 31 | m := `a 32 | multiline 33 | string` 34 | return errors.New(m) 35 | } 36 | 37 | // end of file 38 | -------------------------------------------------------------------------------- /tests/data/gohtml.gohtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ .title }} 8 | 9 | 10 | 11 | 15 | 16 | 17 |
18 |
19 |

{{ .title }}

20 |

{{ .text }}

21 |
22 |
23 | 24 | {{ template "footer" . }} 25 | 26 | 27 | 28 | {{/* 29 | GoHTML 30 | multi line 31 | comment 32 | */}} 33 | 34 | 37 | 38 | 41 | 42 | -------------------------------------------------------------------------------- /tests/data/graphql.gql: -------------------------------------------------------------------------------- 1 | # 89 lines 71 code 3 comments 15 blanks 2 | 3 | """ 4 | A simple GraphQL schema which is well described. This is not a comment. 5 | See: https://facebook.github.io/graphql/June2018/#sec-Descriptions 6 | """ 7 | type Query { 8 | """ 9 | Translates a string from a given language into a different language. 10 | """ 11 | translate( 12 | "The original language that `text` is provided in." 13 | fromLanguage: Language 14 | 15 | "The translated language to be returned." 16 | toLanguage: Language 17 | 18 | "The text to be translated." 19 | text: String 20 | ): String 21 | } 22 | 23 | """ 24 | The set of languages supported by `translate`. 25 | """ 26 | enum Language { 27 | "English" 28 | EN 29 | 30 | "French" 31 | FR 32 | 33 | "Chinese" 34 | CH 35 | } 36 | 37 | # Comment the query and use "quotes" inside the comment 38 | query withFragments($expandedInfo: Boolean) { 39 | user(id: "3bd5a1cbed10e") { 40 | id # Insignificant comment 41 | 42 | ... @include(if: $expandedInfo) { 43 | firstName 44 | lastName 45 | birthday 46 | } 47 | 48 | friends(first: 10) { 49 | ...friendFields 50 | } 51 | 52 | profiles( 53 | handles: [ 54 | "zuck", 55 | "cocacola", 56 | "#hashed#hash#inside" 57 | ] 58 | ) { 59 | handle 60 | 61 | ... on User { 62 | friends { 63 | count 64 | } 65 | } 66 | 67 | ... on Page { 68 | likers { 69 | count 70 | } 71 | } 72 | } 73 | } 74 | } 75 | 76 | fragment friendFields on User { 77 | id 78 | firstName 79 | profilePic(size: 50) 80 | } 81 | 82 | # A simple GraphQL type definition 83 | type User { 84 | id: ID 85 | firstName: String 86 | lastName: String 87 | birthday: Date 88 | } 89 | 90 | -------------------------------------------------------------------------------- /tests/data/gwion.gw: -------------------------------------------------------------------------------- 1 | #! 10 lines 8 code 1 comments 1 blanks 2 | class C { 3 | var int i; 4 | var float f; 5 | var Object o; 6 | operator void @dtor () { <<< "dtor" >>>; } 7 | } 8 | 9 | var C c; 10 | <<< c >>>; 11 | -------------------------------------------------------------------------------- /tests/data/haml.haml: -------------------------------------------------------------------------------- 1 | -# 18 lines 11 code 2 comments 5 blanks 2 | 3 | %section.container 4 | 5 | - @posts.each do |post| 6 | -# Ruby comment 7 | %h1= post.title 8 | 9 | %h2= post.subtitle 10 | 11 | .content 12 | = post.content 13 | 14 | / 15 | HTML comment. Not detected as of now. 16 | %div 17 | %span 18 | This is all wrapped in a comment 19 | -------------------------------------------------------------------------------- /tests/data/hcl.tf: -------------------------------------------------------------------------------- 1 | # 22 lines 11 code 7 comments 4 blanks 2 | variable "foo" "bar" { 3 | default = "yes" 4 | } 5 | 6 | /* We like 7 | multiple lines 8 | */ 9 | 10 | locals { 11 | // this 12 | this = "that" 13 | 14 | # list 15 | more = ["foo", "bar"] 16 | 17 | /* map */ 18 | map = { 19 | yep = "nope" # bad comment 20 | nope = "yep" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/data/headache.ha: -------------------------------------------------------------------------------- 1 | // 13 lines 9 code 3 comments 1 blanks 2 | /* //The Headache cat program */ 3 | // Implementation of Unix Cat in Headache 4 | 5 | void main() { 6 | char x; 7 | read x; //read from stdin 8 | while(x){ 9 | @x; //print char x 10 | read x; //read again from stdin 11 | if(x - (255 as char)){} else x = 0; //necessary for terminal emulation 12 | } 13 | } -------------------------------------------------------------------------------- /tests/data/hicad.mac: -------------------------------------------------------------------------------- 1 | REM 10 lines 4 code 3 comments 3 blanks 2 | START 59 3 | 4 | REM Comment on a line 5 | %XY:=42 6 | 7 | rem This is also a comment 8 | IF FOO= "foo" GOTO 10 9 | 10 | END 11 | -------------------------------------------------------------------------------- /tests/data/hledger.hledger: -------------------------------------------------------------------------------- 1 | # 18 lines 6 code 10 comments 2 blanks 2 | # a comment 3 | ; another comment 4 | 5 | ; ^ a blank line 6 | comment 7 | account assets ; Declare valid account names and display order. 8 | a block comment 9 | end comment 10 | 11 | account assets:savings ; A subaccount. This one represents a bank account. 12 | account assets:checking ; Another. Note, 2+ spaces after the account name. 13 | account assets:receivable ; Accounting type is inferred from english names, 14 | account passifs ; or declared with a "type" tag, type:L 15 | account expenses ; type:X 16 | ; A follow-on comment line, indented. 17 | account expenses:rent ; Expense and revenue categories are also accounts. 18 | ; Subaccounts inherit their parent's type. 19 | -------------------------------------------------------------------------------- /tests/data/hpp.hpp: -------------------------------------------------------------------------------- 1 | /* 21 lines 11 code 5 comments 5 blanks */ 2 | #ifndef TEST_H 3 | #define TEST_H 4 | 5 | #include 6 | 7 | //Some definitions 8 | extern int out; 9 | void foo(); 10 | 11 | /* 12 | * Templated function 13 | */ 14 | template 15 | void print_value(T& t) 16 | { 17 | std::cout< 2 | 3 | 4 | 5 | 6 | 7 | 8 | link 9 | 19 | 20 | 21 | body 22 | 23 | 24 | 25 | 28 | 29 | 32 | 33 | 36 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /tests/data/janet.janet: -------------------------------------------------------------------------------- 1 | # 17 lines 12 code 3 comments 2 blanks 2 | 3 | # Below is a function 4 | (defn a-fn 5 | "Docstring with a hash #" 6 | [a b] 7 | (+ 1 1)) 8 | 9 | (defn a-fn2 10 | #"Not a doc" 11 | "String" 12 | [a b] # a and b right? 13 | (let [multiline "I'm 14 | a multline 15 | # string 16 | "] 17 | (str multline a b))) 18 | -------------------------------------------------------------------------------- /tests/data/java.java: -------------------------------------------------------------------------------- 1 | /* 37 lines 23 code 5 comments 9 blanks */ 2 | 3 | /* 4 | * Simple test class 5 | */ 6 | public class Test 7 | { 8 | int j = 0; // Not counted 9 | public static void main(String[] args) 10 | { 11 | Foo f = new Foo(); 12 | f.bar(); 13 | 14 | } 15 | } 16 | 17 | class Foo 18 | { 19 | public void bar() 20 | { 21 | System.out.println("FooBar"); //Not counted 22 | } 23 | } 24 | 25 | // issues/915 26 | public class BackSlash { 27 | public void run() 28 | { 29 | "\\"; // 1 code + 2 blanks 30 | 31 | 32 | "\\"; // 1 code + 3 blanks 33 | 34 | 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/data/javascript.js: -------------------------------------------------------------------------------- 1 | // 33 lines, 14 code, 12 comments, 7 blanks 2 | 3 | /* 4 | * /* Nested comment 5 | * // single line comment 6 | * */ 7 | 8 | /* 9 | 10 | function add(a, b) { 11 | return a + b; 12 | } 13 | */ 14 | 15 | class Rectangle { 16 | constructor(width, height) { 17 | this.width = width; 18 | this.height = height; 19 | } 20 | 21 | get area() { 22 | return this.calcArea(); 23 | } 24 | 25 | calcArea() { 26 | return this.width * this.height; 27 | } 28 | } 29 | 30 | let rect = new Rectangle(20, 20); 31 | console.log(rect.area); // 400 32 | 33 | // Comment 34 | -------------------------------------------------------------------------------- /tests/data/jinja2.j2: -------------------------------------------------------------------------------- 1 | {# 5 lines 1 code 2 comments 2 blanks #} 2 | 3 | {# test comment #} 4 | 5 | {{ testvar }} 6 | -------------------------------------------------------------------------------- /tests/data/jq.jq: -------------------------------------------------------------------------------- 1 | # 11 lines 3 code 5 comments 3 blanks 2 | 3 | # A function to perform arithmetic 4 | def add_mul(adder; multiplier): 5 | # comment chararacter in quotes 6 | "# Result: " + ((. + adder) * multiplier | tostring); 7 | 8 | # and demonstrate it 9 | 10 | add_mul(5; 4) # => "# Result: 60" 10 | 11 | # end of file 12 | -------------------------------------------------------------------------------- /tests/data/jslt.jslt: -------------------------------------------------------------------------------- 1 | // 126 lines 80 code 20 comments 26 blanks 2 | 3 | // https://github.com/schibsted/jslt/blob/master/examples/queens.jslt 4 | // =========================================================================== 5 | // N-Queens problem solution in JSLT 6 | 7 | // board is n lists of length n 8 | // 0 => no queen 9 | // 1 => queen 10 | 11 | // queens(8) produces 12 | // [ 13 | // [ 1, 0, 0, 0, 0, 0, 0, 0 ], 14 | // [ 0, 0, 0, 0, 1, 0, 0, 0 ], 15 | // [ 0, 0, 0, 0, 0, 0, 0, 1 ], 16 | // [ 0, 0, 0, 0, 0, 1, 0, 0 ], 17 | // [ 0, 0, 1, 0, 0, 0, 0, 0 ], 18 | // [ 0, 0, 0, 0, 0, 0, 1, 0 ], 19 | // [ 0, 1, 0, 0, 0, 0, 0, 0 ], 20 | // [ 0, 0, 0, 1, 0, 0, 0, 0 ] 21 | // ] 22 | 23 | def queens(n) 24 | solve(0, make-board($n)) 25 | 26 | def range(length, list) 27 | if (size($list) < $length) 28 | range($length, $list + [size($list)]) 29 | else 30 | $list 31 | 32 | def zeroes(length) 33 | [for (range($length, [])) 0] 34 | 35 | def make-board(n) 36 | [for (range($n, [])) zeroes($n)] 37 | 38 | def solve(row, board) 39 | let n = size($board) 40 | if ($row == $n) 41 | $board 42 | else 43 | let tries = [for (range($n, [])) 44 | let newboard = place-queen($row, ., $board) 45 | if (is-ok($newboard)) 46 | solve($row + 1, $newboard) 47 | else 48 | null] 49 | 50 | filter($tries)[0] 51 | 52 | def is-ok(board) 53 | rows-ok($board) and cols-ok($board) and diagonals-ok($board) 54 | 55 | def rows-ok(board) 56 | all-ok([for ($board) sum(.) <= 1]) 57 | 58 | def cols-ok(board) 59 | // 0, 1, 2, 3, ... 60 | let indexes = range(size($board), []) 61 | 62 | // list of columns instead of list of rows 63 | let columns = [for ($indexes) 64 | let col = (.) 65 | [for ($board) .[$col]] 66 | ] 67 | 68 | rows-ok($columns) 69 | 70 | def diagonals-ok(board) 71 | let n = size($board) 72 | let offsets = range($n - 1, [])[1 : ] // starts with 1 73 | 74 | let diagonals-right = ( 75 | [diagonal-right($board, 0, 0)] + 76 | [for ($offsets) diagonal-right($board, 0, .)] + 77 | [for ($offsets) diagonal-right($board, ., 0)] 78 | ) 79 | 80 | let diagonals-left = ( 81 | [diagonal-left($board, 0, $n - 1)] + 82 | [for ($offsets) diagonal-left($board, ., $n - 1)] + 83 | [for ($offsets) diagonal-left($board, 0, .)] 84 | ) 85 | 86 | rows-ok($diagonals-right + $diagonals-left) 87 | 88 | def diagonal-right(board, rowoff, coloff) 89 | if ($rowoff >= size($board) or $coloff >= size($board)) 90 | [] 91 | else 92 | [$board[$rowoff][$coloff]] + diagonal-right($board, $rowoff+1, $coloff+1) 93 | 94 | def diagonal-left(board, rowoff, coloff) 95 | if ($rowoff >= size($board) or $coloff < 0) 96 | [] 97 | else 98 | diagonal-left($board, $rowoff + 1, $coloff - 1) + [$board[$rowoff][$coloff]] 99 | 100 | def sum(numbers) 101 | if (not($numbers)) 102 | 0 103 | else 104 | $numbers[0] + sum($numbers[1 : ]) 105 | 106 | def all-ok(booleans) 107 | if (not($booleans)) 108 | true 109 | else 110 | $booleans[0] and all-ok($booleans[1 : ]) 111 | 112 | def place-queen(row, col, board) 113 | let changerow = $board[$row] 114 | let newrow = $changerow[ : $col] + [1] + $changerow[$col + 1 : ] 115 | 116 | $board[ : $row] + [$newrow] + $board[$row + 1 : ] 117 | 118 | def filter(array) 119 | if (not($array)) 120 | [] 121 | else if ($array[0]) 122 | [$array[0]] + filter($array[1 : ]) 123 | else 124 | filter($array[1 : ]) 125 | 126 | queens(8) 127 | -------------------------------------------------------------------------------- /tests/data/jsonnet.jsonnet: -------------------------------------------------------------------------------- 1 | // 13 lines 7 code 4 comments 2 blanks 2 | 3 | /* /**/ */ 4 | local func(a, b) = { 5 | // very useful 6 | a: a, 7 | b: b, 8 | 9 | # you forgot about me! 10 | c: " /* comment in a string! */ ", 11 | e: ' // in another string ', // another after 12 | f: ' # in a final string ', # comment after though 13 | } 14 | -------------------------------------------------------------------------------- /tests/data/justfile: -------------------------------------------------------------------------------- 1 | # 215 lines 154 code 11 comments 50 blanks 2 | set shell := ["sh", "-c"] 3 | set windows-shell := ["powershell.exe", "-NoLogo", "-Command"] 4 | set allow-duplicate-recipes 5 | set positional-arguments 6 | set dotenv-load 7 | set export 8 | 9 | alias s := serve 10 | 11 | bt := '0' 12 | 13 | export RUST_BACKTRACE_1 := bt 14 | 15 | log := "warn" 16 | 17 | export JUST_LOG := (log + "ing" + `grep loop /etc/networks | cut -f2`) 18 | 19 | tmpdir := `mktemp` 20 | version := "0.2.7" 21 | tardir := tmpdir / "awesomesauce-" + version 22 | foo1 := / "tmp" 23 | foo2_3 := "a/" 24 | tarball := tardir + ".tar.gz" 25 | 26 | export RUST_BACKTRACE_2 := "1" 27 | string-with-tab := "\t" 28 | string-with-newline := "\n" 29 | string-with-carriage-return := "\r" 30 | string-with-double-quote := "\"" 31 | string-with-slash := "\\" 32 | string-with-no-newline := "\ 33 | " 34 | 35 | # Newlines in variables 36 | single := ' 37 | hello 38 | ' 39 | 40 | double := " 41 | goodbye 42 | " 43 | escapes := '\t\n\r\"\\' 44 | 45 | # this string will evaluate to `foo\nbar\n` 46 | x := ''' 47 | foo 48 | bar 49 | ''' 50 | 51 | # this string will evaluate to `abc\n wuv\nbar\n` 52 | y := """ 53 | abc 54 | wuv 55 | xyz 56 | """ 57 | 58 | for: 59 | for file in `ls .`; do \ 60 | echo $file; \ 61 | done 62 | 63 | serve: 64 | touch {{tmpdir}}/file 65 | 66 | # This backtick evaluates the command `echo foo\necho bar\n`, which produces the value `foo\nbar\n`. 67 | stuff := ``` 68 | echo foo 69 | echo bar 70 | ``` 71 | 72 | 73 | an_arch := trim(lowercase(justfile())) + arch() 74 | trim_end := trim_end("99.99954% ") 75 | home_dir := replace(env_var('HOME') / "yep", 'yep', '') 76 | quoted := quote("some things beyond\"$()^%#@!|-+=_*&'`") 77 | smartphone := trim_end_match('blah.txt', 'txt') 78 | museum := trim_start_match(trim_start(trim_end_matches(' yep_blah.txt.txt', '.txt')), 'yep_') 79 | water := trim_start_matches('ssssssoup.txt', 's') 80 | congress := uppercase(os()) 81 | fam := os_family() 82 | path_1 := absolute_path('test') 83 | path_2 := '/tmp/subcommittee.txt' 84 | ext_z := extension(path_2) 85 | exe_name := file_name(just_executable()) 86 | a_stem := file_stem(path_2) 87 | a_parent := parent_directory(path_2) 88 | sans_ext := without_extension(path_2) 89 | camera := join('tmp', 'dir1', 'dir2', path_2) 90 | cleaned := clean('/tmp/blah/..///thing.txt') 91 | id__path := '/tmp' / sha256('blah') / sha256_file(justfile()) 92 | _another_var := env_var_or_default("HOME", justfile_directory()) 93 | python := `which python` 94 | 95 | exists := if path_exists(just_executable()) =~ '^/User' { uuid() } else { 'yeah' } 96 | 97 | foo := if env_var("_") == "/usr/bin/env" { `touch /tmp/a_file` } else { "dummy-value" } 98 | foo_b := if "hello" == "goodbye" { "xyz" } else { if "no" == "no" { "yep"} else { error("123") } } 99 | foo_c := if "hello" == "goodbye" { 100 | "xyz" 101 | } else if "a" == "a" { 102 | "abc" 103 | } else { 104 | "123" 105 | } 106 | 107 | bar: 108 | @echo {{foo}} 109 | 110 | 111 | bar2 foo_stuff: 112 | echo {{ if foo_stuff == "bar" { "hello" } else { "goodbye" } }} 113 | 114 | executable: 115 | @echo The executable is at: {{just_executable()}} 116 | 117 | 118 | rustfmt: 119 | find {{invocation_directory()}} -name \*.rs -exec rustfmt {} \; 120 | 121 | test: 122 | echo "{{home_dir}}" 123 | 124 | 125 | linewise: 126 | Write-Host "Hello, world!" 127 | 128 | serve2: 129 | @echo "Starting server with database $DATABASE_ADDRESS on port $SERVER_PORT…" 130 | 131 | 132 | shebang := if os() == 'windows' { 133 | 'powershell.exe' 134 | } else { 135 | '/usr/bin/env pwsh' 136 | } 137 | 138 | shebang: 139 | #!{{shebang}} 140 | $PSV = $PSVersionTable.PSVersion | % {"$_" -split "\." } 141 | $psver = $PSV[0] + "." + $PSV[1] 142 | if ($PSV[2].Length -lt 4) { 143 | $psver += "." + $PSV[2] + " Core" 144 | } else { 145 | $psver += " Desktop" 146 | } 147 | echo "PowerShell $psver" 148 | 149 | @foo: 150 | echo bar 151 | 152 | @test5 *args='': 153 | bash -c 'while (( "$#" )); do echo - $1; shift; done' -- "$@" 154 | 155 | test2 $RUST_BACKTRACE="1": 156 | # will print a stack trace if it crashes 157 | cargo test 158 | 159 | 160 | notify m="": 161 | keybase chat send --topic-type "chat" --channel "upd(): {{m}}" 162 | 163 | # Sample project script 2 164 | script2 *ARGS: 165 | {{ python }} script2.py {{ ARGS }} 166 | 167 | braces: 168 | echo 'I {{{{LOVE}} curly braces!' 169 | 170 | _braces2: 171 | echo '{{'I {{LOVE}} curly braces!'}}' 172 | 173 | _braces3: 174 | echo 'I {{ "{{" }}LOVE}} curly braces!' 175 | 176 | foo2: 177 | -@cat foo 178 | echo 'Done!' 179 | 180 | test3 target tests=path_1: 181 | @echo 'Testing {{target}}:{{tests}}…' 182 | ./test --tests {{tests}} {{target}} 183 | 184 | test4 triple=(an_arch + "-unknown-unknown") input=(an_arch / "input.dat"): 185 | ./test {{triple}} 186 | 187 | variadic $VAR1_1 VAR2 VAR3 VAR4=("a") +$FLAGS='-q': foo2 braces 188 | cargo test {{FLAGS}} 189 | 190 | time: 191 | @-date +"%H:%S" 192 | -cat /tmp/nonexistent_file.txt 193 | @echo "finished" 194 | 195 | justwords: 196 | grep just \ 197 | --text /usr/share/dict/words \ 198 | > /tmp/justwords 199 | 200 | # Subsequent dependencies 201 | # https://just.systems/man/en/chapter_37.html 202 | # To test, run `$ just -f test-suite.just b` 203 | a: 204 | echo 'A!' 205 | 206 | b: a && d 207 | echo 'B start!' 208 | just -f {{justfile()}} c 209 | echo 'B end!' 210 | 211 | c: 212 | echo 'C!' 213 | 214 | d: 215 | echo 'D!' 216 | -------------------------------------------------------------------------------- /tests/data/k.k: -------------------------------------------------------------------------------- 1 | // 8 lines 2 code 4 comments 2 blanks 2 | /suduko solver 3 | 4 | / initial state 5 | x:.:'"200370009009200007001004002050000800008000900006000040900100500800007600400089001" 6 | 7 | / breadth search all solutions (p:row col box for each position) 8 | *(,x)(,/{@[x;y;:;]'&~in[!10]x*|/p[;y]=p,:3/:_(p:9\:!81)%3}')/&~x 9 | -------------------------------------------------------------------------------- /tests/data/kakoune_script.kak: -------------------------------------------------------------------------------- 1 | # 13 lines, 8 code, 2 comments, 3 blanks 2 | hook global BufCreate (.*/)?(kakrc|.*.kak) %{ 3 | set-option buffer filetype kak 4 | } 5 | 6 | echo "This is a string". 7 | echo 'This is a 8 | multiline string 9 | # with a hash 10 | in it.' 11 | 12 | # This is a comment. 13 | 14 | -------------------------------------------------------------------------------- /tests/data/ksh.ksh: -------------------------------------------------------------------------------- 1 | #!/bin/ksh 2 | # 17 lines, 11 code, 4 comments, 2 blanks 3 | 4 | # first comment 5 | files="/etc/passwd /etc/group /etc/hosts" 6 | for f in $files; do 7 | if [ ! -f $f ] 8 | then 9 | echo "$f file missing!" 10 | fi 11 | done 12 | 13 | # second comment 14 | for f in $(ls /tmp/*) 15 | do 16 | print "Full file path in /tmp dir : $f" 17 | done 18 | -------------------------------------------------------------------------------- /tests/data/kvlanguage.kv: -------------------------------------------------------------------------------- 1 | # 22 lines 17 code 3 comments 2 blanks 2 | 3 | 4 | #:kivy 2.0.0 5 | #:import C kivy.utils.get_color_from_hex 6 | #:import KeypadButton keypadbutton 7 | #:include keypadbutton.kv 8 | #:set name value 9 | : 10 | color: C('#27272A') 11 | # general comment 12 | : 13 | width: self.minimum_width 14 | height: self.minimum_height 15 | size_hint: None, None 16 | cols: 3 17 | spacing: 6 18 | KeypadButton: 19 | text: '1' 20 | disabled: root.disabled 21 | on_press: root.dispatch('on_key_pressed', self.key_val) 22 | # a final comment 23 | -------------------------------------------------------------------------------- /tests/data/lalrpop.lalrpop: -------------------------------------------------------------------------------- 1 | // 37 lines 26 code 3 comments 8 blanks 2 | use crate::ast::{ExprSymbol, Opcode}; 3 | use crate::tok9::Tok; 4 | 5 | grammar<'input>(input: &'input str); 6 | 7 | // line comment 8 | pub Expr: Box> = { // comment 1 9 | Expr r##"verbatim2"## Factor => Box::new(ExprSymbol::Op(<>)), 10 | Factor, // comment 2 11 | }; 12 | 13 | Factor: Box> = { // comment 3 14 | Factor "FactorOp" Term => Box::new(ExprSymbol::Op(<>)), 15 | Term, 16 | }; 17 | 18 | // comment 4 19 | 20 | Term: Box> = { 21 | r#"verbatim"# => Box::new(ExprSymbol::NumSymbol(<>)), 22 | "(" ")" 23 | }; 24 | 25 | extern { 26 | type Location = usize; 27 | type Error = (); 28 | 29 | enum Tok<'input> { 30 | r#"verbatim"# => Tok::NumSymbol(<&'input str>), 31 | "FactorOp" => Tok::FactorOp(), 32 | r##"verbatim2"## => Tok::ExprOp(), 33 | "(" => Tok::ParenOpen, 34 | ")" => Tok::ParenClose, 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /tests/data/linguafranca.lf: -------------------------------------------------------------------------------- 1 | // 36 lines 16 code 9 comments 11 blanks 2 | 3 | target Rust; 4 | 5 | // A C style comment 6 | import KeyboardEvents from "KeyboardEvents.lf"; 7 | 8 | /* A block comment */ 9 | # a python like comment 10 | 11 | main reactor Snake(grid_side: usize(32), 12 | food_limit: u32(2)) { 13 | 14 | // counts as 2 lines of Rust code and one blank 15 | preamble {= 16 | use crate::snakes::*; 17 | 18 | use rand::prelude::*; 19 | =} 20 | 21 | /// rust doc comment 22 | keyboard = new KeyboardEvents(); 23 | 24 | // T 25 | state snake: CircularSnake ({= CircularSnake::new(grid_side) =}); 26 | state grid: SnakeGrid ({= SnakeGrid::new(grid_side, &snake) =}); 27 | state food_on_grid: u32(0); 28 | 29 | 30 | // 1 line of rust code 31 | reaction(shutdown) {= 32 | // comment in Rust 33 | 34 | println!("New high score: {}", self.snake.len()); 35 | =} 36 | } 37 | -------------------------------------------------------------------------------- /tests/data/liquid.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 24 lines 19 code 1 comments 4 blanks {% endcomment %} 2 | 3 | {% paginate collection.products by 20 %} 4 | 5 |
    6 | {% for product in collection.products %} 7 |
  • 8 |
    9 |
    10 |
    11 |
    12 |

    {{product.title}}

    13 |

    {{ product.description | strip_html | truncatewords: 35 }}

    14 |

    {{ product.price_min | money }}{% if product.price_varies %} - {{ product.price_max | money }}{% endif %}

    15 |
    16 |
  • 17 | {% endfor %} 18 |
19 | 20 | 23 | 24 | {% endpaginate %} 25 | -------------------------------------------------------------------------------- /tests/data/livescript.ls: -------------------------------------------------------------------------------- 1 | # 28 lines, 10 code, 12 comments, 6 blanks 2 | 3 | /* 4 | * /* Nested comment 5 | * # single line comment 6 | * */ 7 | 8 | /* 9 | 10 | add = (a, b) -> 11 | return a + b 12 | */ 13 | 14 | hello = -> 15 | console.log 'hello, world!' 16 | 17 | "hello!" |> capitalize |> console.log 18 | 19 | # Easy listing of implicit objects 20 | table1 = 21 | * id: 1 22 | name: 'george' 23 | * id: 2 24 | name: 'mike' # comment 25 | * id: 3 26 | name: 'donald' 27 | 28 | # Comment 29 | -------------------------------------------------------------------------------- /tests/data/llvm.ll: -------------------------------------------------------------------------------- 1 | ; 21 lines 17 code 1 comments 3 blanks 2 | define i32 @add1(i32 %a, i32 %b) { 3 | entry: 4 | %tmp1 = add i32 %a, %b 5 | ret i32 %tmp1 6 | } 7 | 8 | define i32 @add2(i32 %a, i32 %b) { 9 | entry: 10 | %tmp1 = icmp eq i32 %a, 0 11 | br i1 %tmp1, label %done, label %recurse 12 | 13 | recurse: 14 | %tmp2 = sub i32 %a, 1 15 | %tmp3 = add i32 %b, 1 16 | %tmp4 = call i32 @add2(i32 %tmp2, i32 %tmp3) 17 | ret i32 %tmp4 18 | 19 | done: 20 | ret i32 %b 21 | } -------------------------------------------------------------------------------- /tests/data/logtalk.lgt: -------------------------------------------------------------------------------- 1 | /* 2 | Test file for the Logtalk programming language 3 | (copied by the author from a Logtalk distribution example) 4 | 5 | 65 lines 27 code 18 comments 20 blanks 6 | */ 7 | 8 | 9 | % Alf believes he is the only survivor of his species; no point in 10 | % defining a class if there is only going to be a single instance: 11 | 12 | % a prototype, which is also a stand-alone object 13 | 14 | :- object(alf). 15 | 16 | % prototypes declare predicates for themselves (and derived prototypes) 17 | :- public([ 18 | name/1, planet/1, stomachs/1, favorite_food/1, chases/1, motto/1 19 | ]). 20 | 21 | name('Gordon Shumway'). 22 | planet('Melmac'). 23 | stomachs(8). 24 | favorite_food(cats). 25 | chases('Lucky'). 26 | motto('Are you going to finish that sandwich?'). 27 | 28 | :- end_object. 29 | 30 | 31 | % later on, Alf finds out that his best friend, Skip, and his 32 | % girlfriend, Rhonda, also survived Melmac's explosion; as they 33 | % are all melmacians, they share most attributes (and add some 34 | % of their own): 35 | 36 | % "skip", a derived prototype from "alf", its parent prototype 37 | 38 | :- object(skip, 39 | extends(alf)). 40 | 41 | :- public(best_friend/1). 42 | 43 | best_friend(alf). 44 | name('Skip'). 45 | % still longing for a nice cat to eat since Melmac exploded 46 | chases(_) :- 47 | fail. 48 | 49 | :- end_object. 50 | 51 | 52 | % "rhonda" is also a prototype derived from "alf" 53 | 54 | :- object(rhonda, 55 | extends(alf)). 56 | 57 | :- public(boyfriend/1). 58 | 59 | boyfriend(alf). 60 | name('Rhonda'). 61 | % still longing for a nice cat to eat since Melmac exploded 62 | chases(_) :- 63 | fail. 64 | 65 | :- end_object. 66 | -------------------------------------------------------------------------------- /tests/data/lolcode.lol: -------------------------------------------------------------------------------- 1 | BTW 26 lines 11 code 9 comments 6 blanks 2 | HAI 1.3 3 | 4 | BTW TEST! 5 | I HAS A MSG ITZ "BYE! OBTW" 6 | HOW IZ I PRINT_HELLO 7 | I HAS A MSG ITZ "BTW Hello, World!" BTW OBTW 8 | BTW MORE COMMENTS! 9 | VISIBLE MSG BTW TLDR 10 | IF U SAY SO 11 | 12 | I HAS A MSG ITZ "Hello OBTW BTW TLDR" 13 | I IZ PRINT_HELLO MKAY 14 | 15 | OBTW 16 | a longer test 17 | asd TLDR 18 | 19 | OBTW TLDR 20 | 21 | I IZ PRINT_HELLO MKAY OBTW should be valid 22 | foo bar 23 | TLDR 24 | 25 | VISIBLE MSG 26 | KTHXBYE 27 | -------------------------------------------------------------------------------- /tests/data/m4.m4: -------------------------------------------------------------------------------- 1 | dnl 7 lines 3 code 1 blanks 3 comments 2 | The builtin `dnl' stands for “Discard to Next Line”: 3 | dnl this line is not emitted 4 | Other text is emitted 5 | 6 | You can also make comments with `#' # this is a comment 7 | # This is a comment, too 8 | -------------------------------------------------------------------------------- /tests/data/menhir.mly: -------------------------------------------------------------------------------- 1 | // 47 lines 31 code 7 comments 9 blanks 2 | 3 | (* Example from the menhir development with instrumented comments. 4 | * (* Note: nested C style comments are not allowed. *) 5 | * https://gitlab.inria.fr/fpottier/menhir/-/tree/master/demos/calc-alias *) 6 | 7 | %token INT "42" 8 | %token PLUS "+" 9 | %token MINUS "-" 10 | %token TIMES "*" 11 | %token DIV "/" 12 | %token LPAREN "(" 13 | %token RPAREN ")" 14 | %token EOL 15 | 16 | (* Token aliases can be used throughout the rest of the grammar. E.g., 17 | they can be used in precedence declarations: *) 18 | 19 | %left "+" "-" /* lowest " precedence */ 20 | %left "*" "/" /* medium precedence */ 21 | %nonassoc UMINUS // highest "precedence" 22 | 23 | %start main 24 | 25 | %% 26 | 27 | main: 28 | | e = expr EOL 29 | { e } 30 | 31 | (* Token aliases can also be used inside rules: *) 32 | 33 | expr: 34 | | i = "42" 35 | { i } 36 | | "(" e = expr ")" 37 | { e } 38 | | e1 = expr "+" e2 = expr 39 | { e1 + e2 } 40 | | e1 = expr "-" e2 = expr 41 | { e1 - e2 } 42 | | e1 = expr "*" e2 = expr 43 | { e1 * e2 } 44 | | e1 = expr "/" e2 = expr 45 | { e1 / e2 } 46 | | "-" e = expr %prec UMINUS 47 | { - e } 48 | -------------------------------------------------------------------------------- /tests/data/meson.build: -------------------------------------------------------------------------------- 1 | # 12 lines 6 code 2 comments 4 blanks 2 | 3 | project('xyz', 'c', 4 | meson_version : '>=0.30.0') # not counted 5 | 6 | xyz_gen = ''' 7 | # comment inside 8 | print("This is generated source.") 9 | ''' 10 | 11 | # this is a comment 12 | 13 | -------------------------------------------------------------------------------- /tests/data/metal.metal: -------------------------------------------------------------------------------- 1 | /* 32 lines 21 code 5 comments 6 blanks */ 2 | #include 3 | 4 | // comment 5 | struct Uniforms { 6 | float2 extent; 7 | }; 8 | 9 | struct VertexIn { 10 | float2 position [[attribute(0)]]; 11 | }; 12 | 13 | struct VertexOut { 14 | float2 position [[position]]; 15 | }; 16 | 17 | /* 18 | multi-line comment 19 | */ 20 | 21 | vertex VertexOut vs_main( 22 | VertexIn in [[stage_in]] 23 | ) { 24 | VertexOut out; 25 | return out; 26 | } 27 | 28 | fragment float4 fs_main( 29 | VertexOut in [[stage_in]] 30 | ) { 31 | return float4(0.0); 32 | } 33 | -------------------------------------------------------------------------------- /tests/data/mlatu.mlt: -------------------------------------------------------------------------------- 1 | // 22 lines 14 code 3 comments 5 blanks 2 | 3 | define divisible (Int, Int -> Bool +Fail) { (%) 0 (=) } 4 | 5 | // Here's a random comment that is definitely useful 6 | 7 | define fizzbuzz (Int -> String) { 8 | -> n; 9 | do (with (+Fail)) { n 5 divisible n 3 divisible } 10 | if { if { "FizzBuzz" } else { "Fizz" } } 11 | else { if { "Buzz" } else { n show } } 12 | } 13 | 14 | define fizzbuzzes (Int, Int -> +IO) { 15 | -> c, m; 16 | c fizzbuzz println (c < m) 17 | if { (c + 1) m fizzbuzzes } 18 | else {} // We don't need anything here 19 | } 20 | 21 | 1 100 fizzbuzzes 22 | // Comment at end 23 | -------------------------------------------------------------------------------- /tests/data/moduledef.def: -------------------------------------------------------------------------------- 1 | ; 17 lines 9 code 6 comments 2 blanks 2 | ; 3 | ; Definition file of KERNEL32.dll 4 | ; Automatic generated by gendef 5 | ; written by Kai Tietz 2008 6 | ; 7 | LIBRARY "KERNEL32.dll" 8 | 9 | EXPORTS 10 | "BaseThreadInitThunk;@4" 11 | InterlockedPushListSList@8 12 | AcquireSRWLockExclusive@4 13 | AcquireSRWLockShared@4 14 | ActivateActCtx@8 15 | AddAtomA@4 16 | AddAtomW@4 17 | 18 | -------------------------------------------------------------------------------- /tests/data/mojo.mojo: -------------------------------------------------------------------------------- 1 | # 21 lines 15 code 3 comments 3 blanks 2 | 3 | 4 | ''' 5 | This is a docstring. 6 | # It has multiple lines. 7 | This is the end of the docstring. 8 | ''' 9 | def main(): 10 | # Hello Mojo! 11 | string = "Hello Mojo!" 12 | # The following line prints the string "Hello Mojo!" 13 | print(string) 14 | 15 | """ 16 | This piece of code prints 17 | the numbers "9", "6", and "3". 18 | 'Here is a quote.' 19 | """ 20 | for x in range(9, 0, -3): 21 | print(x) 22 | -------------------------------------------------------------------------------- /tests/data/monkeyc.mc: -------------------------------------------------------------------------------- 1 | // 69 lines 41 code 18 comments 10 blanks 2 | // Slightly modified template from the "Garmin.monkey-c" VS Code extension. 3 | import Toybox.Application; 4 | import Toybox.Graphics; 5 | import Toybox.Lang; 6 | import Toybox.System; 7 | import Toybox.WatchUi; 8 | 9 | class WatchFaceView extends WatchUi.WatchFace { 10 | 11 | function initialize() { 12 | WatchFace.initialize(); 13 | } 14 | 15 | // Load your resources here 16 | function onLayout(dc as Dc) as Void { 17 | setLayout(Rez.Layouts.WatchFace(dc)); 18 | } 19 | 20 | /* 21 | Called when this View is brought to the foreground. Restore 22 | the state of this View and prepare it to be shown. This includes 23 | loading resources into memory. 24 | */ 25 | function onShow() as Void { 26 | } 27 | 28 | // Update the view 29 | function onUpdate(dc as Dc) as Void { 30 | // Get the current time and format it correctly 31 | var timeFormat = "$1$:$2$"; 32 | var clockTime = System.getClockTime(); 33 | var hours = clockTime.hour; 34 | if (!System.getDeviceSettings().is24Hour) { 35 | if (hours > 12) { 36 | hours = hours - 12; 37 | } 38 | } else { 39 | if (getApp().getProperty("UseMilitaryFormat")) { 40 | timeFormat = "$1$$2$"; 41 | hours = hours.format("%02d"); 42 | } 43 | } 44 | var timeString = Lang.format(timeFormat, [hours, clockTime.min.format("%02d")]); 45 | 46 | // Update the view 47 | var view = View.findDrawableById("TimeLabel") as Text; 48 | view.setColor(getApp().getProperty("ForegroundColor") as Number); 49 | view.setText(timeString); 50 | 51 | View.onUpdate(dc); // Call the parent onUpdate function to redraw the layout 52 | } 53 | 54 | /* 55 | Called when this View is removed from the screen. Save the 56 | state of this View here. This includes freeing resources from 57 | memory. 58 | */ 59 | function onHide() as Void { 60 | } 61 | 62 | // The user has just looked at their watch. Timers and animations may be started here. 63 | function onExitSleep() as Void { 64 | } 65 | 66 | // Terminate any active timers and prepare for slow updates. 67 | function onEnterSleep() as Void { 68 | } 69 | } -------------------------------------------------------------------------------- /tests/data/nextflow.nf: -------------------------------------------------------------------------------- 1 | /* 18 lines 10 code 5 comments 3 blanks */ 2 | 3 | /* 4 | Nextflow - hello 5 | */ 6 | 7 | // comment 8 | cheers = Channel.from 'Bonjour', 'Ciao', 'Hello', 'Hola' 9 | 10 | process sayHello { 11 | echo true 12 | input: 13 | val x from cheers 14 | script: 15 | """ 16 | echo '$x world!' 17 | """ 18 | } 19 | -------------------------------------------------------------------------------- /tests/data/nqp.nqp: -------------------------------------------------------------------------------- 1 | # 24 lines 14 code 8 comments 2 blanks 2 | =begin 3 | Regex methods and functions 4 | =end 5 | 6 | =begin item match 7 | Match C<$text> against C<$regex>. If the C<$global> flag is 8 | given, then return an array of all non-overlapping matches. 9 | =end item 10 | 11 | sub match ($text, $regex, :$global?) { 12 | my $match := $text ~~ $regex; 13 | if $global { 14 | my @matches; 15 | while $match { 16 | nqp::push(@matches, $match); 17 | $match := $match.parse($text, :rule($regex), :c($match.to)); 18 | } 19 | @matches; 20 | } 21 | else { 22 | $match; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/data/odin.odin: -------------------------------------------------------------------------------- 1 | // 29 lines 17 code 7 comments 5 blanks 2 | import "core:fmt" 3 | 4 | /* 5 | * Calculates the next number in the Collatz sequence 6 | * 7 | * If `x` is divisible by two, the result is `x` divided by two 8 | * If `x` is not divisible by two, the result is `x` multiplied by three plus one 9 | */ 10 | collatz :: inline proc(x: int) -> int { 11 | if x & 1 == 0 do return x >> 1; 12 | else do return x * 3 + 1; 13 | } 14 | 15 | steps :: proc(x: int) -> int { 16 | count := 0; 17 | 18 | y := x; 19 | for y != 1 { 20 | y = collatz(y); 21 | count += 1; 22 | } 23 | 24 | return count; 25 | } 26 | 27 | main :: proc() { 28 | fmt.println(steps(42)); // 8 29 | } -------------------------------------------------------------------------------- /tests/data/open_policy_agent.rego: -------------------------------------------------------------------------------- 1 | # 13 lines 8 code 3 comments 2 blanks 2 | 3 | package application.authz 4 | 5 | # Only owner can update the pet's information 6 | # Ownership information is provided as part of OPA's input 7 | default allow = false 8 | allow { 9 | input.method == "PUT" 10 | some petid 11 | input.path = ["pets", petid] 12 | input.user == input.owner 13 | } 14 | -------------------------------------------------------------------------------- /tests/data/openscad.scad: -------------------------------------------------------------------------------- 1 | //! 34 lines 15 code 16 comments 3 blanks 2 | // https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Commented_Example_Projects 3 | // The idea is to twist a translated circle: 4 | // - 5 | /* 6 | linear_extrude(height = 10, twist = 360, scale = 0) 7 | translate([1,0]) 8 | circle(r = 1); 9 | */ 10 | 11 | module horn(height = 10, radius = 6, 12 | twist = 720, $fn = 50) 13 | { 14 | // A centered circle translated by 1xR and 15 | // twisted by 360° degrees, covers a 2x(2xR) space. 16 | // - 17 | radius = radius/4; 18 | // De-translate. 19 | // - 20 | translate([-radius,0]) 21 | // The actual code. 22 | // - 23 | linear_extrude(height = height, twist = twist, 24 | scale=0, $fn = $fn) 25 | translate([radius,0]) 26 | circle(r=radius); 27 | } 28 | 29 | translate([3,0]) 30 | mirror() 31 | horn(); 32 | 33 | translate([-3,0]) 34 | horn(); 35 | -------------------------------------------------------------------------------- /tests/data/opentype.fea: -------------------------------------------------------------------------------- 1 | # 54 lines 24 code 24 comments 6 blanks 2 | languagesystem DFLT dflt; 3 | languagesystem latn dflt; 4 | languagesystem latn DEU; 5 | languagesystem latn TRK; 6 | languagesystem cyrl dflt; 7 | 8 | feature smcp { 9 | sub [a-z] by [A.sc-Z.sc]; 10 | # Since all the rules in this feature are of the same type, they will be grouped in a single lookup. 11 | # Since no script or language keyword has been specified yet, 12 | # the lookup will be registered for this feature under all the language systems. 13 | } smcp; 14 | 15 | feature liga { 16 | sub f f by f_f; 17 | sub f i by f_i; 18 | sub f l by f_l; 19 | # Since all the rules in this feature are of the same type, they will be 20 | # grouped in a single lookup. 21 | # Since no script or language keyword has been specified yet, 22 | # the lookup will be registered for this feature under all the language systems. 23 | 24 | script latn; 25 | language dflt; 26 | # lookupflag 0; (implicit) 27 | sub c t by c_t; 28 | sub c s by c_s; 29 | # The rules above will be placed in a lookup that is registered for all 30 | # the specified languages for the script latn, but not any other scripts. 31 | 32 | language DEU; 33 | # script latn; (stays the same) 34 | # lookupflag 0; (stays the same) 35 | sub c h by c_h; 36 | sub c k by c_k; 37 | # The rules above will be placed in a lookup that is registered only 38 | # under the script 'latn', 'language DEU'. 39 | 40 | language TRK; 41 | # This will inherit both the top level default rules - the rules defined 42 | # before the first 'script' statement, and the script-level default 43 | # rules for 'latn: all the lookups of this feature defined after the 44 | # 'script latn' statement, and before the 'language DEU' statement. 45 | # If 'TRK' were not named here, it would not inherit the default rules 46 | # for the script 'latn'. 47 | } liga; 48 | 49 | feature kern { 50 | pos a y -150; 51 | # [more pos statements] 52 | # All the rules in this feature will be grouped in a single lookup 53 | # that is registered under all the languagesystems. 54 | } kern; 55 | -------------------------------------------------------------------------------- /tests/data/org_mode.org: -------------------------------------------------------------------------------- 1 | # 13 lines 7 code 2 comments 4 blanks 2 | 3 | #+TITLE: This is the title, not a comment 4 | 5 | # This is comment 6 | 7 | Some text 8 | 9 | * Heading 1 10 | :PROPERTIES: 11 | :CUSTOM_ID: heading-1 12 | :END: 13 | Text under heading 1 14 | -------------------------------------------------------------------------------- /tests/data/pan.pan: -------------------------------------------------------------------------------- 1 | # 21 lines 11 code 4 comments 6 blanks 2 | 3 | # Pan example code, see https://quattor-pan.readthedocs.io/en/stable/pan-book/index.html 4 | 5 | prefix "/system/aii/osinstall/ks"; 6 | "clearpart" = append("vdb"); 7 | "ignoredisk" = list(); # no disks to ignore 8 | 9 | prefix "/system/blockdevices"; 10 | "physical_devs/vdb/label" = "msdos"; 11 | "partitions/vdb1" = dict( 12 | "holding_dev", "vdb", 13 | ); 14 | 15 | "files/{/srv/elasticsearch}" = dict('size', 0); 16 | 17 | # To facilitate adding other partitions at a later stage, a 18 | # logical volume will be created 19 | "volume_groups/vg1/device_list" = append("partitions/vdb1"); 20 | "logical_volumes" = lvs_add('vg1', dict("elasticsearch", -1)); 21 | 22 | -------------------------------------------------------------------------------- /tests/data/pcss.pcss: -------------------------------------------------------------------------------- 1 | /* 14 lines 6 code 5 comments 3 blanks */ 2 | 3 | .foo { 4 | color: #f00; 5 | 6 | &.bar { 7 | background: url("foobar.jpg"); 8 | } 9 | } 10 | 11 | // inline comments are allowed by some PostCSS syntaxes 12 | /* 13 | * block comments are standard 14 | */ 15 | -------------------------------------------------------------------------------- /tests/data/pest.pest: -------------------------------------------------------------------------------- 1 | // 9 lines 4 code 3 comments 2 blanks 2 | alpha = { 'a'..'z' | 'A'..'Z' } 3 | digit = { '0'..'9' } 4 | 5 | ident = { (alpha | digit)+ } 6 | 7 | ident_list = _{ !digit ~ ident ~ (" " ~ ident)+ } 8 | // ^ 9 | // ident_list rule is silent which means it produces no tokens -------------------------------------------------------------------------------- /tests/data/phix.e: -------------------------------------------------------------------------------- 1 | /* 40 lines 25 code 8 comments 7 blanks */ 2 | 3 | -- copied from cpp, not necessarily idiomatic Euphoria code 4 | 5 | include std/sequence.e 6 | 7 | -- bubble_sort_function 8 | public function bubble_sort(sequence a) 9 | integer t = 0 10 | integer j = length(a) 11 | integer s = 1 12 | while s > 0 do 13 | s = 0 14 | integer i = 2 15 | while i <= j do 16 | if a[i] < a[i - 1] then 17 | t = a[i] 18 | a[i] = a[i - 1] 19 | a[i - 1] = t 20 | s = 1 21 | end if 22 | i += 1 23 | end while 24 | j -= 1 25 | end while 26 | return a 27 | end function 28 | 29 | sequence a = {4, 65, 2, -31, 0, 99, 2, 83, 782, 1} 30 | 31 | -- Single line comment 32 | ? {"Before:", a} 33 | 34 | a = bubble_sort(a) 35 | 36 | /* multi 37 | * line 38 | * comment 39 | */ 40 | ? {"After:", a, equal(a, {-31,0,1,2,2,4,65,83,99,782})} -------------------------------------------------------------------------------- /tests/data/plantuml.puml: -------------------------------------------------------------------------------- 1 | ' 35 lines 10 code 13 comments 12 blanks 2 | ' plantuml line comments must start at the beginning of a line. 3 | ' plantuml block comments must either start on a newline or start and end on the same line as they start. 4 | ' strings cannot span multiple lines. 5 | ' single quotes are a valid string wrapper '', but not when they are the first non-whitespace characters on a line 6 | 7 | ' comment at start uml 8 | @startuml 9 | 10 | !include 11 | 12 | '' this is also a comment 13 | 14 | rectangle "this is a string" as r 15 | /' this 16 | is a multi-line 17 | comment '/ 18 | 19 | /' this is also a multi-line comment '/ 20 | Container(C, "This is some more text", "text") 21 | 22 | node n /' this is a multi-line comment at the end of a line '/ 23 | 24 | /' this is /' a valid '/ block comment '/ 25 | 26 | component "'this is not a comment" 27 | 28 | /' this is a multi-line comment at the start of a line '/ interface i 29 | 30 | boundary "/' this is not a multi-line comment '/" 31 | 32 | System(s, "this is /' not part of a comment", "'/ this is also not part of a comment", "/' '/ /' neither is this") 33 | 34 | ' comment after start uml 35 | @enduml 36 | -------------------------------------------------------------------------------- /tests/data/pofile.po: -------------------------------------------------------------------------------- 1 | # 14 lines 6 code 5 comments 3 blanks 2 | 3 | #: lib/error.c:116 4 | msgid "Unknown system error" 5 | msgstr "Error desconegut del sistema" 6 | 7 | #: disk-utils/addpart.c:15 8 | #, c-format 9 | msgid " %s \n" 10 | msgstr " %s \n" 11 | 12 | #: disk-utils/addpart.c:19 13 | msgid "Tell the kernel about the existence of a specified partition.\n" 14 | msgstr "Informer le noyau de l’existence d’une partition indiquée.\n" 15 | -------------------------------------------------------------------------------- /tests/data/pofile_pot.pot: -------------------------------------------------------------------------------- 1 | # 17 lines 8 code 5 comments 4 blanks 2 | 3 | #: disk-utils/addpart.c:60 disk-utils/delpart.c:61 disk-utils/resizepart.c:101 4 | msgid "invalid partition number argument" 5 | msgstr "" 6 | 7 | #: disk-utils/addpart.c:61 8 | msgid "invalid start argument" 9 | msgstr "" 10 | 11 | #: disk-utils/addpart.c:62 disk-utils/resizepart.c:111 12 | msgid "invalid length argument" 13 | msgstr "" 14 | 15 | #: disk-utils/addpart.c:63 16 | msgid "failed to add partition" 17 | msgstr "" 18 | -------------------------------------------------------------------------------- /tests/data/poke.pk: -------------------------------------------------------------------------------- 1 | /* 4 lines 2 code 1 comments 1 blanks */ 2 | 3 | var N = 3; 4 | fun getoff = offset,B>: { return 2#B; } 5 | -------------------------------------------------------------------------------- /tests/data/pony.pony: -------------------------------------------------------------------------------- 1 | // 12 lines 7 code 3 comments 2 blanks 2 | 3 | /* com- 4 | -ment */ 5 | 6 | actor Main 7 | """ 8 | Some 9 | Docs 10 | """ 11 | new create(env: Env) => 12 | env.out.print("Hello, world.") 13 | -------------------------------------------------------------------------------- /tests/data/postcss.sss: -------------------------------------------------------------------------------- 1 | // 27 lines 18 code 4 comments 5 blanks 2 | 3 | /** 4 | multi-line 5 | */ 6 | div { 7 | width: calc(99.9% * 1/3 - (30px - 30px * 1/3)); 8 | } 9 | 10 | div:nth-child(1n) { 11 | float: left; 12 | margin-right: 30px; 13 | clear: none; 14 | } 15 | 16 | div:last-child { 17 | margin-right: 0; 18 | } 19 | 20 | div:nth-child(3n) { 21 | margin-right: 0; 22 | float: right; 23 | } 24 | 25 | div:nth-child(3n + 1) { 26 | clear: both; 27 | } 28 | -------------------------------------------------------------------------------- /tests/data/powershell.ps1: -------------------------------------------------------------------------------- 1 | # 17 lines 9 code 4 comments 4 blanks 2 | 3 | <# 4 | Test 5 | #> 6 | 7 | 'a' + "b" 8 | 9 | Write-Host @" 10 | Name: $name 11 | Address: $address 12 | "@ 13 | 14 | $template = @' 15 | Name: {0} 16 | Address: {0} 17 | '@ 18 | -------------------------------------------------------------------------------- /tests/data/pug.pug: -------------------------------------------------------------------------------- 1 | //- 13 lines, 8 code, 3 comments, 2 blanks 2 | 3 | doctype html 4 | // this comment will be translated to an HTML comment 5 | //- this comment will be excluded from the generated HTML 6 | 7 | html 8 | head 9 | title Hello, World! 10 | body 11 | p 12 | | Hello, 13 | | World! 14 | -------------------------------------------------------------------------------- /tests/data/puppet.pp: -------------------------------------------------------------------------------- 1 | # 18 lines 14 code 3 comments 1 blanks 2 | class example::class( 3 | $param1, 4 | $param2=2, 5 | $param3=undef, # pass this one 6 | ) { 7 | # comments are really simple 8 | some::resource { 9 | 'bar': 10 | param1 => param2, 11 | # comments here too 12 | param3 => param4; 13 | } 14 | 15 | some::other::resource { 16 | 'baz': 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/data/pyret.arr: -------------------------------------------------------------------------------- 1 | # 22 lines 9 code 8 comments 5 blanks 2 | 3 | fun single-quote(): 4 | doc: "this is a documentation string" 5 | 'foo' 6 | end 7 | 8 | #| 9 | Hello, this is a multiline message 10 | |# 11 | 12 | # This is a line message 13 | 14 | fun double-quotes(): 15 | "bar" 16 | end 17 | 18 | nested = #| 19 | doesn't start yet 20 | or yet 21 | |# 22 | "nested" -------------------------------------------------------------------------------- /tests/data/python.py: -------------------------------------------------------------------------------- 1 | # 15 lines, 10 code, 2 comments, 3 blanks 2 | 3 | 4 | def add(x, y): 5 | """ 6 | Hello World 7 | # Real Second line 8 | Second line 9 | """ 10 | 11 | string = "Hello World #\ 12 | " 13 | y += len(string) 14 | # Add the two numbers. 15 | x + y 16 | -------------------------------------------------------------------------------- /tests/data/q.q: -------------------------------------------------------------------------------- 1 | // 14 lines 5 code 5 comments 4 blanks 2 | 3 | /calc nav for sets of portfolios,ETFs,indices,.. 4 | 5 | /one day of ([]time;sym;price) sorted by time 6 | n:10000000;S:-10000?`4 7 | t:([]time:09:30:00.0+til n;sym:n?S;price:n?1.0) 8 | 9 | /calc price deltas once 10 | \t update deltas price by sym from`t 11 | 12 | /for each portfolio 13 | a:([sym:-100?S]weight:100?1.0) 14 | \t r:select time,sums price*weight from t ij a 15 | -------------------------------------------------------------------------------- /tests/data/qml.qml: -------------------------------------------------------------------------------- 1 | // 20 lines 11 code 5 comments 4 blanks 2 | 3 | import QtQuick 2.7 4 | import QtQuick.Controls 2.0 5 | 6 | ApplicationWindow { 7 | visible: true 8 | 9 | /* 10 | * Multiline comment 11 | */ 12 | Text { 13 | text: "string type 1" 14 | } 15 | 16 | // comment 17 | function testfunc() { 18 | console.log('string type 2'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/data/racket.rkt: -------------------------------------------------------------------------------- 1 | ;;; 40 lines 15 code 14 comments 11 blanks 2 | #lang racket ; defines the language we are using 3 | 4 | ;;; Comments 5 | 6 | ;; Single line comments start with a semicolon 7 | 8 | #| Block comments 9 | can span multiple lines and... 10 | #| 11 | they can be nested! 12 | |# 13 | |# 14 | 15 | ;; S-expression comments discard the following expression 16 | ;; since this is syntax-aware, tokei counts this as code 17 | #; (this expression is discarded) 18 | 19 | ;; Constant 20 | (define %pi 3.14159265358979323846) 21 | 22 | #| This is a block comment |# 23 | (define (degrees->radians deg) 24 | (* deg (/ %pi 180))) 25 | 26 | ;; Function 27 | (define (sq x) (* x x)) 28 | 29 | (define (sum xs) 30 | "Sum list of elements." 31 | (foldl + 0 xs)) ; comment 32 | 33 | (define (sum-upto n) 34 | (/ (* n (+ 1 n)) 2)) 35 | 36 | (define (test-sums n) 37 | (= (sum-upto n) 38 | (sum (range (+ 1 n))))) 39 | 40 | (test-sums 100) 41 | -------------------------------------------------------------------------------- /tests/data/raku.raku: -------------------------------------------------------------------------------- 1 | # 49 lines 37 code 6 comments 6 blanks 2 | 3 | =begin pod 4 | 5 | =begin DESCRIPTION 6 | 7 | =head1 Test file for Tokei 8 | 9 | =end DESCRIPTION 10 | 11 | =begin code :lang 12 | 13 | say 'Hello World'; 14 | 15 | =end code 16 | 17 | =end pod 18 | 19 | #| Fibonacci with multiple dispatch 20 | multi sub fib (0 --> 0) {} 21 | multi sub fib (1 --> 1) {} 22 | multi sub fib (\n where * > 1) { 23 | fib(n - 1) + fib(n - 2) 24 | } 25 | 26 | #|{ 27 | Role shape 28 | for printing area of different shapes 29 | } 30 | role Shape { 31 | method area { ... } 32 | 33 | method print_area { 34 | say "Area of {self.^name} is {self.area}."; 35 | } 36 | } 37 | 38 | class Rectangle does Shape { 39 | has $.width is required; #= Width of rectangle 40 | has $.height is required; #= Height of rectangle 41 | 42 | method area { 43 | #`( 44 | area of rectangle: 45 | width times height 46 | ) 47 | $!width × $!height 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/data/razor.cshtml: -------------------------------------------------------------------------------- 1 | @* 55 lines 35 code 15 comments 5 blanks *@ 2 | @page "/" 3 | @using Microsoft.AspNetCore.Components.Web 4 | @namespace temp.Pages 5 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 6 | 7 | @{ 8 | // foo 9 | string foo = "bar"; 10 | 11 | /* 12 | * bar 13 | */ 14 | string bar = "foo"; 15 | } 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | @* 31 | 32 | multi-line comment 33 | 34 | *@ 35 | 36 | 37 |
38 | 39 | An error has occurred. This application may no longer respond until reloaded. 40 | 41 | 46 | 47 | An unhandled exception has occurred. See browser dev tools for details. 48 | 49 | Reload 50 | 🗙 51 |
52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /tests/data/razorcomponent.razor: -------------------------------------------------------------------------------- 1 | @* 45 lines 16 code 21 comments 8 blanks *@ 2 | @page "/counter" 3 | 4 | @{ 5 | // foo 6 | string foo = "bar"; 7 | 8 | /* 9 | * bar 10 | */ 11 | string bar = "foo"; 12 | } 13 | 14 | Counter 15 | 16 | @* 17 | 18 | multi-line comment 19 | 20 | *@ 21 |

Counter

22 | 23 |

Current count: @currentCount

24 | 25 | 30 | 31 | 32 | @code { 33 | /* 34 | 35 | C# style multi-line comment 36 | 37 | */ 38 | private int currentCount = 0; 39 | 40 | private void IncrementCount() 41 | { 42 | // increment the count 43 | currentCount++; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/data/redscript.reds: -------------------------------------------------------------------------------- 1 | // 75 lines 47 code 20 comments 8 blanks 2 | 3 | // redscript allows line comments 4 | /* as well as block comments */ 5 | 6 | // it supports global functions 7 | func add2(x: Int32, y: Int32) -> Int32 { 8 | return x + y; 9 | } 10 | 11 | // functions without a type annotation default to Void return type 12 | func tutorial() { 13 | let x: Int32 = 10; 14 | // compiler can infer types for local variables, y will be Int32 15 | let y = 20; 16 | // it supports arithmetic 17 | let sum = x + y + 13; 18 | // as well as mutation 19 | let mutable = 0; 20 | mutable += 10; 21 | // numbers with decimal points default to type Float 22 | let num = 10.0; 23 | // you can cast between some types 24 | let uint: Uint8 = Cast(10); 25 | // array literals 26 | let arr = [1, 2, 3]; 27 | // array iteration 28 | for item in arr { 29 | // logging and string operations 30 | Log("at " + ToString(item)); 31 | } 32 | } 33 | 34 | // you can define your own classes 35 | public class IntTuple { 36 | let fst: Int32; 37 | let snd: Int32; 38 | 39 | // you can define static member functions 40 | public static func Create(fst: Int32, snd: Int32) -> ref { 41 | let tuple = new IntTuple(); 42 | tuple.fst = fst; 43 | tuple.snd = snd; 44 | return tuple; 45 | } 46 | 47 | public func Swap() { 48 | let tmp = this.fst; 49 | this.fst = this.snd; 50 | this.snd = tmp; 51 | } 52 | } 53 | 54 | // you can replace existing in-game methods by specifying the class they belong to 55 | @replaceMethod(CraftingSystem) 56 | private final func ProcessCraftSkill(xpAmount: Int32, craftedItem: StatsObjectID) { 57 | // instantiate a class using the new operator 58 | let xpEvent = new ExperiencePointsEvent(); 59 | xpEvent.amount = xpAmount * 100; 60 | xpEvent.type = gamedataProficiencyType.Crafting; 61 | GetPlayer(this.GetGameInstance()).QueueEvent(xpEvent); 62 | } 63 | 64 | // you can add new methods to existing classes as well 65 | // they are visible to other code using the class 66 | @addMethod(BackpackMainGameController) 67 | private final func DisassembleAllJunkItems() -> Void { 68 | let items = this.m_InventoryManager.GetPlayerItemsByType(gamedataItemType.Gen_Junk); 69 | let i = 0; 70 | for item in items { 71 | ItemActionsHelper.DisassembleItem(this.m_player, InventoryItemData.GetID(item)); 72 | }; 73 | // some methods require CName literals, they need to be prefixed with the n letter 74 | this.PlaySound(n"Item", n"OnBuy"); 75 | } -------------------------------------------------------------------------------- /tests/data/renpy.rpy: -------------------------------------------------------------------------------- 1 | # 32 lines 8 code 9 comments 15 blanks 2 | 3 | # Declare characters used by this game. The color argument colorizes the 4 | # name of the character. 5 | 6 | define e = Character("Eileen") 7 | 8 | 9 | # The game starts here. 10 | 11 | label start: 12 | 13 | # Show a background. This uses a placeholder by default, but you can 14 | # add a file (named either "bg room.png" or "bg room.jpg") to the 15 | # images directory to show it. 16 | 17 | scene bg room 18 | 19 | 20 | show eileen happy 21 | 22 | # These display lines of dialogue. 23 | 24 | e "You've created a new Ren'Py game." 25 | 26 | e 'Once you add a story, pictures, and music, you can release it to the world!' 27 | 28 | e `Testing, testing` 29 | 30 | # This ends the game. 31 | 32 | return 33 | -------------------------------------------------------------------------------- /tests/data/roc.roc: -------------------------------------------------------------------------------- 1 | # 36 lines 18 code 10 comments 8 blanks 2 | module [square] 3 | # this is a comment 4 | # this is another comment 5 | 6 | a1 = 1 7 | a2 = 3.14159 # pi 8 | 9 | expect 10 | # simple check 11 | a1 == 1 12 | 13 | expect 14 | a2 |> Num.toStr == "3.14159" 15 | 16 | ## Compute the square 17 | square = \x -> 18 | s = x * x 19 | 20 | # the line above is blank 21 | s 22 | 23 | expect square 3 == 9 24 | 25 | ## """ 26 | ## this is not a multiline string, 27 | ## it's a doc comment 28 | ## """ 29 | multilineString = 30 | """ 31 | # this line is not a comment, it's actually code 32 | 33 | The line above is not blank, it's actually code 34 | """ 35 | 36 | expect multilineString |> Str.toUtf8 |> List.first == Ok '#' 37 | -------------------------------------------------------------------------------- /tests/data/ron.ron: -------------------------------------------------------------------------------- 1 | // 157 lines 137 code 7 comments 13 blanks 2 | 3 | #![enable(implicit_some)] 4 | Container( 5 | transform: ( 6 | id: "background", 7 | anchor: Middle, 8 | stretch: XY( x_margin: 0., y_margin: 0., keep_aspect_ratio: false), 9 | width: 20., 10 | height: 20., 11 | ), 12 | background: SolidColor(0.03, 0.03, 0.03, 1.0), 13 | children: [ 14 | 15 | Container( 16 | transform: ( 17 | id: "container_start", 18 | y: 180, 19 | width: 755., 20 | height: 170., 21 | anchor: Middle, 22 | ), 23 | background: SolidColor(1.0, 0.65, 0.0, 1.0), 24 | children: [ 25 | 26 | // Complex Button 27 | Button( 28 | transform: ( 29 | id: "start", 30 | width: 750., 31 | height: 165., 32 | tab_order: 1, 33 | anchor: Middle, 34 | mouse_reactive: true, 35 | ), 36 | button: ( 37 | text: "START GAME", 38 | font: File("font/square.ttf", ("TTF", ())), 39 | font_size: 75., 40 | normal_text_color: (1.0, 0.65, 0., 1.0), // ffa500 41 | // hover_text_color: (1.0, 0.65, 0., 1.0), 42 | // press_text_color: (1.0, 0.65, 0., 1.0), 43 | normal_image: SolidColor(0., 0., 0., 1.), 44 | hover_image: SolidColor(0.1, 0.1, 0.1, 1.), 45 | press_image: SolidColor(0.15, 0.15, 0.15, 1.), 46 | ) 47 | ), 48 | ] 49 | ), 50 | 51 | 52 | Container( 53 | transform: ( 54 | id: "container_load", 55 | y: 0, 56 | width: 755., 57 | height: 170., 58 | anchor: Middle, 59 | ), 60 | background: SolidColor(1.0, 0.65, 0.0, 1.0), 61 | children: [ 62 | 63 | // Complex Button 64 | Button( 65 | transform: ( 66 | id: "load", 67 | width: 750., 68 | height: 165., 69 | tab_order: 3, 70 | anchor: Middle, 71 | mouse_reactive: true, 72 | ), 73 | button: ( 74 | text: "LOAD GAME", 75 | font: File("font/square.ttf", ("TTF", ())), 76 | font_size: 75., 77 | normal_text_color: (1.0, 0.65, 0., 1.0), // ffa500 78 | normal_image: SolidColor(0., 0., 0., 1.), 79 | hover_image: SolidColor(0.1, 0.1, 0.1, 1.), 80 | press_image: SolidColor(0.15, 0.15, 0.15, 1.), 81 | ) 82 | ), 83 | ] 84 | ), 85 | 86 | 87 | Container( 88 | transform: ( 89 | id: "container_options", 90 | y: -180, 91 | width: 755., 92 | height: 170., 93 | anchor: Middle, 94 | ), 95 | background: SolidColor(1.0, 0.65, 0.0, 1.0), 96 | children: [ 97 | 98 | // Complex Button 99 | Button( 100 | transform: ( 101 | id: "options", 102 | width: 750., 103 | height: 165., 104 | tab_order: 3, 105 | anchor: Middle, 106 | mouse_reactive: true, 107 | ), 108 | button: ( 109 | text: "OPTIONS", 110 | font: File("font/square.ttf", ("TTF", ())), 111 | font_size: 75., 112 | normal_text_color: (1.0, 0.65, 0., 1.0), // ffa500 113 | normal_image: SolidColor(0., 0., 0., 1.), 114 | hover_image: SolidColor(0.1, 0.1, 0.1, 1.), 115 | press_image: SolidColor(0.15, 0.15, 0.15, 1.), 116 | ) 117 | ), 118 | ] 119 | ), 120 | 121 | 122 | Container( 123 | transform: ( 124 | id: "container_credits", 125 | y: -360, 126 | width: 755., 127 | height: 170., 128 | anchor: Middle, 129 | ), 130 | background: SolidColor(1.0, 0.65, 0.0, 1.0), 131 | children: [ 132 | 133 | // Complex Button 134 | Button( 135 | transform: ( 136 | id: "credits", 137 | width: 750., 138 | height: 165., 139 | tab_order: 3, 140 | anchor: Middle, 141 | mouse_reactive: true, 142 | ), 143 | button: ( 144 | text: "CREDITS", 145 | font: File("font/square.ttf", ("TTF", ())), 146 | font_size: 75., 147 | normal_text_color: (1.0, 0.65, 0., 1.0), // ffa500 148 | normal_image: SolidColor(0., 0., 0., 1.), 149 | hover_image: SolidColor(0.1, 0.1, 0.1, 1.), 150 | press_image: SolidColor(0.15, 0.15, 0.15, 1.), 151 | ) 152 | ), 153 | ] 154 | ), 155 | 156 | ], 157 | ) 158 | -------------------------------------------------------------------------------- /tests/data/rpmspec.spec: -------------------------------------------------------------------------------- 1 | # 42 lines 22 code 4 comments 16 blanks 2 | 3 | Name: example 4 | Version: 0.0.1 5 | Release: 1%{?dist} 6 | Summary: an example specfile 7 | 8 | Group: 9 | URL: 10 | Source0: 11 | 12 | # test comments for requirements 13 | BuildRequires: 14 | Requires: 15 | 16 | %description 17 | 18 | 19 | %prep 20 | %setup -q 21 | 22 | 23 | # build the project 24 | %build 25 | %configure 26 | make build 27 | 28 | 29 | # install the files here 30 | %install 31 | make install 32 | 33 | 34 | %clean 35 | 36 | 37 | %files 38 | %defattr(-,root,root,-) 39 | %doc 40 | 41 | 42 | %changelog 43 | -------------------------------------------------------------------------------- /tests/data/ruby.rb: -------------------------------------------------------------------------------- 1 | # 20 lines 9 code 8 comments 3 blanks 2 | x = 3 3 | if x < 2 4 | p = "Smaller" 5 | else 6 | p = "Bigger" 7 | end 8 | 9 | =begin 10 | Comments 11 | Comments 12 | Comments 13 | Comments 14 | =end 15 | 16 | # testing. 17 | while x > 2 and x < 10 18 | x += 1 19 | end 20 | 21 | -------------------------------------------------------------------------------- /tests/data/ruby_env: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 11 lines 3 code 6 comments 2 blanks 3 | 4 | =begin 5 | Comment that only counts if detected as ruby 6 | Comments 7 | =end 8 | 9 | while x > 2 and x < 10 10 | x += 1 11 | end -------------------------------------------------------------------------------- /tests/data/ruby_html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= title %> 8 | 9 | 10 | 11 | 15 | 16 | 17 |
18 |
19 |

<%= header %>

20 |

<%= text %>

21 |
22 |
23 | 24 | <%= template "footer" %> 25 | 26 | 27 | 30 | 31 | 34 | 35 | -------------------------------------------------------------------------------- /tests/data/rust.rs: -------------------------------------------------------------------------------- 1 | //! 48 lines 36 code 6 comments 6 blanks 2 | //! ```rust 3 | //! fn main () { 4 | //! // Comment 5 | //! 6 | //! println!("Hello World!"); 7 | //! } 8 | //! ``` 9 | 10 | /* /**/ */ 11 | fn main() { 12 | let start = r##"/*##\" 13 | \"##; 14 | // comment 15 | loop { 16 | if x.len() >= 2 && x[0] == '*' && x[1] == '/' { // found the */ 17 | break; 18 | } 19 | } 20 | } 21 | 22 | fn foo<'a, 'b>(name: &'b str) { 23 | let this_ends = "a \"test/*."; 24 | call1(); 25 | call2(); 26 | let this_does_not = /* a /* nested */ comment " */ 27 | "*/another /*test 28 | call3(); 29 | */"; 30 | } 31 | 32 | fn foobar() { 33 | let does_not_start = // " 34 | "until here, 35 | test/* 36 | test"; // a quote: " 37 | let also_doesnt_start = /* " */ 38 | "until here, 39 | test,*/ 40 | test"; // another quote: " 41 | } 42 | 43 | fn foo() { 44 | let a = 4; // /* 45 | let b = 5; 46 | let c = 6; // */ 47 | } 48 | 49 | -------------------------------------------------------------------------------- /tests/data/scheme.scm: -------------------------------------------------------------------------------- 1 | ;;; 26 lines 14 code 4 comments 8 blanks 2 | 3 | (import (srfi srfi-1)) ; for reduce 4 | 5 | ;; Constant 6 | (define %pi 3.14159265358979323846) 7 | 8 | #| This is a block comment |# 9 | (define (degrees->radians deg) 10 | (* deg (/ %pi 180))) 11 | 12 | ;; Function 13 | (define (sq x) (* x x)) 14 | 15 | (define (sum xs) 16 | "Sum list of elements." 17 | (reduce + 0 xs)) ; comment 18 | 19 | (define (sum-upto n) 20 | (/ (* n (1+ n)) 2)) 21 | 22 | (define (test-sums n) 23 | (= (sum-upto n) 24 | (sum (iota (1+ n))))) 25 | 26 | (test-sums 100) 27 | -------------------------------------------------------------------------------- /tests/data/shaderlab.shader: -------------------------------------------------------------------------------- 1 | // 43 lines 31 code 8 comments 4 blanks 2 | Shader "Custom/Sample shader" 3 | { 4 | Properties 5 | { 6 | _MainTex ("Texture", 2D) = "white" {} 7 | } 8 | SubShader 9 | { 10 | Tags { "Queue"="Transparent" "RenderType"="Transparent" } 11 | 12 | // blending 13 | Blend SrcAlpha OneMinusSrcAlpha 14 | /* 15 | 16 | multi-line comment 17 | 18 | */ 19 | Pass 20 | { 21 | CGPROGRAM 22 | #pragma vertex vert 23 | 24 | struct appdata 25 | { 26 | float4 vertex : POSITION; 27 | float2 uv : TEXCOORD0; 28 | }; 29 | 30 | sampler2D _MainTex; 31 | 32 | // vertex 33 | v2f vert (appdata v) 34 | { 35 | v2f o; 36 | o.vertex = UnityObjectToClipPos(v.vertex); 37 | o.uv = TRANSFORM_TEX(v.uv, _MainTex); 38 | return o; 39 | } 40 | ENDCG 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/data/slang.slang: -------------------------------------------------------------------------------- 1 | // 15 lines 8 code 5 comments 2 blanks 2 | 3 | Texture2D in_tex; 4 | RWTexture2D out_tex; 5 | 6 | // Blit compute shader 7 | [shader("compute")] 8 | [numthreads(8, 8, 1)] 9 | void main(uint2 id: SV_DispatchThreadID) { 10 | /* 11 | Perform the blit 12 | */ 13 | out_tex[id] = in_tex[id]; 14 | return; 15 | } 16 | -------------------------------------------------------------------------------- /tests/data/slint.slint: -------------------------------------------------------------------------------- 1 | // 26 lines 21 code 2 comments 3 blanks 2 | 3 | component MyButton inherits Text { 4 | color: black; 5 | // ... 6 | } 7 | 8 | export component MyApp inherits Window { 9 | preferred-width: 200px; 10 | preferred-height: 100px; 11 | Rectangle { 12 | width: 200px; 13 | height: 100px; 14 | background: green; 15 | 16 | }/* */ 17 | MyButton { 18 | x:0;y:0; // hello 19 | text: "hello"; 20 | } 21 | MyButton { // world 22 | y:0; 23 | x: 50px; 24 | text: "world"; 25 | } 26 | } -------------------------------------------------------------------------------- /tests/data/solidity.sol: -------------------------------------------------------------------------------- 1 | // 14 lines 6 code 7 comments 1 blanks 2 | pragma solidity >=0.4.22 <0.6.0; 3 | 4 | // Comment line 5 | contract Foo { 6 | /* 7 | Comment line 8 | Comment line 9 | Comment line 10 | */ 11 | function foo(address bar) public { 12 | require(bar != 0); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/data/sql.sql: -------------------------------------------------------------------------------- 1 | -- 12 lines 4 code 5 comments 3 blanks 2 | 3 | 4 | SELECT * FROM Users 5 | WHERE FirstName is not null; -- select rows where the user has a first name 6 | 7 | /* this is the beginning of a block comment 8 | insert a new user into the Users table 9 | -- line comment in a block comment 10 | */ 11 | INSERT INTO Users (FirstName, LastName) 12 | VALUES ("John", "Does"); -------------------------------------------------------------------------------- /tests/data/srecode.srt: -------------------------------------------------------------------------------- 1 | ;; 37 lines 23 code 2 comments 12 blanks 2 | 3 | set escape_start "$" 4 | set escape_end "$" 5 | set mode "srecode-template-mode" 6 | set priority "70" 7 | 8 | set comment_start ";;" 9 | set comment_end "" 10 | set comment_prefix ";;" 11 | 12 | set SEPARATOR "----" 13 | 14 | set DOLLAR "$" 15 | 16 | context file 17 | 18 | prompt MAJORMODE "Major Mode for templates: " read srecode-read-major-mode-name 19 | prompt START "Escape Start Characters: " default "{{" 20 | prompt END "Escape End Characters: " default "}}" 21 | 22 | template empty :file :user :time :srt 23 | "Insert a skeleton for a template file." 24 | ---- 25 | $>:filecomment$ 26 | 27 | set mode "$?MAJORMODE$" 28 | set escape_start "$?START$" 29 | set escape_end "$?END$" 30 | 31 | context file 32 | 33 | $^$ 34 | 35 | 36 | ;; end 37 | ---- 38 | -------------------------------------------------------------------------------- /tests/data/stata.do: -------------------------------------------------------------------------------- 1 | * 16 lines 6 code 7 comments 3 blanks 2 | * This is a comment 3 | **** Any number of * symbol 4 | 5 | use "foo.dta", replace 6 | gen x = 1*2 7 | gen x2 = 1/2 8 | /* 9 | Here's a comment block 10 | */ 11 | 12 | if c(username) == "foobar" { 13 | global FOO 1 14 | } 15 | 16 | // Finally another symbol for comment -------------------------------------------------------------------------------- /tests/data/stratego.str: -------------------------------------------------------------------------------- 1 | // 24 lines 12 code 6 comments 6 blanks 2 | module stratego 3 | 4 | strategies 5 | 6 | /** // */ 7 | main = 8 | !"/* " 9 | ; id // */ 10 | 11 | foo = 12 | ?'a' 13 | 14 | rules 15 | 16 | foobar: "//" -> "\\" // " ' 17 | /* " ' */ 18 | 19 | foo: a -> a // /* 20 | where 21 | b := 'b' // */ 22 | // ; c := $[quotes with anti quotes [b], which are not supported by tokei atm so this is a commented line of code] 23 | // ; c := ${quotes with anti quotes {b}, which are not supported by tokei atm so this is a commented line of code} 24 | // ; c := $, which are not supported by tokei atm so this is a commented line of code> 25 | -------------------------------------------------------------------------------- /tests/data/stylus.styl: -------------------------------------------------------------------------------- 1 | // 20 lines, 10 code, 5 comments, 5 blanks 2 | 3 | /* 4 | * Multi-line comment 5 | */ 6 | 7 | // Single-line comment 8 | 9 | #app 10 | position: absolute 11 | left: 0 12 | top: 0 13 | 14 | .item::before 15 | content: "Stylus" 16 | color: orange 17 | background-color: white 18 | 19 | .item::after 20 | content: 'Lang' 21 | -------------------------------------------------------------------------------- /tests/data/svelte.svelte: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 21 | 22 | 25 | 26 | 42 | -------------------------------------------------------------------------------- /tests/data/swift.swift: -------------------------------------------------------------------------------- 1 | // 24 lines 6 code 14 comments 4 blanks 2 | 3 | // Single-line comment 4 | /* multi-line comment */ 5 | /* /* nested */ */ 6 | /* 7 | multi 8 | line 9 | comment 10 | */ 11 | /* 12 | nested /* */ 13 | /* nested */ 14 | */ 15 | 16 | import UIKit 17 | 18 | class ViewController: UIViewController { 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | 22 | // Do any additional setup after loading the view. 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/data/swig.i: -------------------------------------------------------------------------------- 1 | /* 16 lines 8 code 5 comments 3 blanks */ 2 | %module mymodule 3 | 4 | /* 5 | * Wrapper-includes 6 | */ 7 | %{ 8 | #include "myheader.h" //dummy header 9 | %} 10 | 11 | // Now list ANSI C/C++ declarations 12 | int foo; 13 | int bar(int x); 14 | 15 | %rename(my_print) print; 16 | extern void print(const char *); 17 | -------------------------------------------------------------------------------- /tests/data/tact.tact: -------------------------------------------------------------------------------- 1 | // 20 lines 12 code 4 comments 4 blanks 2 | 3 | import "@stdlib/deploy"; // comment 4 | 5 | /* comment */ 6 | fun global() { 7 | let str: String = "\n \r \t \u1234 \xFF"; 8 | 9 | // comment 10 | while (true) { // comment 11 | if /* comment */ (true) { /* comment */ } 12 | } 13 | } 14 | 15 | // "quoted" 16 | struct St { /* " */ 17 | field1: Int; // /* 18 | field2: Int as uint128; 19 | field3: Int; // */ 20 | } 21 | -------------------------------------------------------------------------------- /tests/data/templ.templ: -------------------------------------------------------------------------------- 1 | // 24 lines, 13 code, 8 comments, 3 blanks 2 | package test 3 | 4 | templ Foo() { 5 |
6 | 9 | 10 |
11 | } 12 | 13 | /* 14 | some css class. 15 | */ 16 | css button() { 17 | padding: 7px; 18 | border-radius: 5px; 19 | } 20 | 21 | // doSomething does something 22 | script doSomething() { 23 | alert("something") 24 | } 25 | -------------------------------------------------------------------------------- /tests/data/thrift.thrift: -------------------------------------------------------------------------------- 1 | // 38 lines 29 code 2 comments 7 blanks 2 | 3 | namespace java test 4 | namespace py test 5 | 6 | /* /* */ 7 | service Twitter extends core.BaseService { 8 | void ping(), 9 | 10 | bool postTweet(1: Tweet tweet) throws (1: TwitterUnavailable unavailable), 11 | 12 | TweetSearchResult searchTweets(1: string query), 13 | } 14 | 15 | enum TweetType { 16 | TWEET, # 1 /* 17 | RETWEET = 2, // 2 18 | DM = 0xa, // 3 */ 19 | REPLY 20 | } 21 | 22 | struct Tweet { 23 | 1: required i32 userId, 24 | 2: required string userName = "/*", 25 | 3: required string text = '...', 26 | 4: optional Location loc, 27 | 5: optional TweetType tweetType = TweetType.TWEET, 28 | 16: optional string language = "en\"glish", // */ 29 | } 30 | 31 | const string TEST1 = // " 32 | "starts here, 33 | test/* 34 | test" // a quote: " 35 | const string TEST2 = /* " */ 36 | 'starts here, 37 | test,*/ 38 | test' # another quote: " 39 | -------------------------------------------------------------------------------- /tests/data/tsx.tsx: -------------------------------------------------------------------------------- 1 | // 9 lines, 5 code, 3 comments, 1 blanks 2 | 3 | /** string two numbers together */ 4 | const stringNums = (x: number, y: number) => { 5 | // the line below makes a string 6 | const firstNum = x + ""; 7 | const secondNum = firstNum + y; 8 | return secondNum; 9 | }; 10 | -------------------------------------------------------------------------------- /tests/data/ttcn.ttcn3: -------------------------------------------------------------------------------- 1 | // 16 lines 7 code 6 comments 3 blanks 2 | /** 3 | * @description A TTCN-3 demo module 4 | * @author John Doe 5 | */ 6 | 7 | module demo { 8 | import from definitions all; 9 | 10 | control { 11 | log("Hello world!"); // write something to log 12 | 13 | // execute(altstepWithTimeout()); 14 | execute(test(), 5.0); /* terminate after 5s */ 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/data/twig.twig: -------------------------------------------------------------------------------- 1 | {# 16 lines 14 code 1 comments 1 blanks #} 2 | 3 |
    4 | {% for product in products %} 5 |
  • 6 |
    7 |
    8 |
    9 |
    10 |

    {{- product.title -}}

    11 |

    {{ product.description | capitalize }}

    12 |

    {{ product.price_min | default('0') }}{% if product.price_varies %} - {{ product.price_max | number_format(2, '.', ',') }}{% endif %}

    13 |
    14 |
  • 15 | {% endfor %} 16 |
17 | -------------------------------------------------------------------------------- /tests/data/typescript.ts: -------------------------------------------------------------------------------- 1 | // 33 lines, 20 code, 10 comments, 3 blanks 2 | /* 3 | 4 | Multi-line comment with blanks 5 | 6 | 7 | * 8 | */ 9 | // Comment 10 | class Person { 11 | #age: number; 12 | #name: string; // end of line comment 13 | #height: number; 14 | 15 | constructor(age: number, name: string, height: number) { 16 | this.#age = age; 17 | this.#name = name; 18 | this.#height = height; 19 | } 20 | } 21 | 22 | let main = () => { 23 | // Comment with quote " 24 | let person = new Person( 25 | 5, 26 | `Phill 27 | 28 | the giant`, 29 | 7 30 | ); 31 | }; 32 | 33 | main(); 34 | -------------------------------------------------------------------------------- /tests/data/typst.typ: -------------------------------------------------------------------------------- 1 | // 16 lines 9 code 3 comments 4 blanks 2 | 3 | // Some example settings 4 | #set document(title: "a title", author: "an author") 5 | #set page(numbering: "1 / 1", number-align: center) 6 | #set par(justify: true) 7 | #set text(size: 13pt, lang: "fr") // with a trailing comment 8 | #set heading(numbering: "1.1") /* with another trailing comment */ 9 | 10 | #let foo = "multiline 11 | string" 12 | 13 | #let bar = "singleline string" 14 | 15 | /* comment */ /* nested /* comment */ */ 16 | #lorem(50) 17 | -------------------------------------------------------------------------------- /tests/data/uiua.ua: -------------------------------------------------------------------------------- 1 | # 9 lines 5 code 3 comments 1 blanks 2 | # Calculate factorial 3 | # Result ? Number 4 | Factorial ← |1 ( 5 | ×. # Line comment 6 | ) 7 | 8 | FactorialThree ← Factorial 3 # Another line comment 9 | FactorialFour ← Factorial 4 10 | -------------------------------------------------------------------------------- /tests/data/unison.u: -------------------------------------------------------------------------------- 1 | -- 16 lines 6 code 8 comments 2 blanks 2 | x = 3 3 | if x < 2 then 4 | "-- {- -} -- Smaller. Test escaped quote \"!" 5 | else 6 | "Bigger -- {- -} --" 7 | 8 | {- 9 | Comments 10 | Comments -- nested -- 11 | Comments 12 | Comments 13 | -} 14 | 15 | -- testing quote in comment "hello there!" 16 | List.map (a -> a + 1) [1,2,3] 17 | -------------------------------------------------------------------------------- /tests/data/urweb.ur: -------------------------------------------------------------------------------- 1 | (* 14 lines 8 code 4 comments 2 blanks *) 2 | fun main () = return 3 | 4 | Hello world! 5 | 6 | 7 | (* multi 8 | line 9 | comment *) 10 | 11 | (* uncounted comment *) 12 |

Hello world!

13 | 14 |
15 | -------------------------------------------------------------------------------- /tests/data/urweb_urp.urp: -------------------------------------------------------------------------------- 1 | # 3 lines 1 code 1 comments 1 blanks 2 | 3 | urweb # uncounted comment 4 | -------------------------------------------------------------------------------- /tests/data/urweb_urs.urs: -------------------------------------------------------------------------------- 1 | (* 3 lines 1 code 1 comments 1 blanks *) 2 | 3 | val main : unit -> transaction page (* uncounted comment *) 4 | -------------------------------------------------------------------------------- /tests/data/vb6_bas.bas: -------------------------------------------------------------------------------- 1 | ' 12 lines 6 code 3 comments 3 blanks 2 | Attribute VB_Name = "Module1" 3 | Public Function SayHello(Name As String) 4 | 5 | ' Create a response string 6 | Dim Response As String 7 | Response = "Hello " & Name 8 | 9 | 'Return response string 10 | SayHello = Response 11 | 12 | End Function 13 | -------------------------------------------------------------------------------- /tests/data/vb6_cls.cls: -------------------------------------------------------------------------------- 1 | ' 22 lines 17 code 3 comments 2 blanks 2 | VERSION 1.0 CLASS 3 | BEGIN 4 | MultiUse = -1 'True 5 | Persistable = 0 'NotPersistable 6 | DataBindingBehavior = 0 'vbNone 7 | DataSourceBehavior = 0 'vbNone 8 | MTSTransactionMode = 0 'NotAnMTSObject 9 | END 10 | Attribute VB_Name = "Class1" 11 | Attribute VB_GlobalNameSpace = False 12 | Attribute VB_Creatable = True 13 | Attribute VB_PredeclaredId = False 14 | Attribute VB_Exposed = False 15 | 'This is a comment 16 | Private Sub Class_Initialize() 17 | 18 | 'This is another comment 19 | Dim test As String 20 | test = "TESTING" 21 | 22 | End Sub 23 | -------------------------------------------------------------------------------- /tests/data/vb6_frm.frm: -------------------------------------------------------------------------------- 1 | ' 34 lines 29 code 3 comments 2 blanks 2 | VERSION 5.00 3 | Begin VB.Form Form1 4 | Caption = "Form1" 5 | ClientHeight = 3015 6 | ClientLeft = 120 7 | ClientTop = 465 8 | ClientWidth = 4560 9 | LinkTopic = "Form1" 10 | ScaleHeight = 3015 11 | ScaleWidth = 4560 12 | StartUpPosition = 3 'Windows Default 13 | Begin VB.CommandButton btnTest 14 | Caption = "Test" 15 | Height = 495 16 | Left = 720 17 | TabIndex = 0 18 | Top = 840 19 | Width = 1095 20 | End 21 | End 22 | Attribute VB_Name = "Form1" 23 | Attribute VB_GlobalNameSpace = False 24 | Attribute VB_Creatable = False 25 | Attribute VB_PredeclaredId = True 26 | Attribute VB_Exposed = False 27 | 'This is a comment 28 | Private Sub btnTest_Click() 29 | 30 | 'This is another comment 31 | Dim test As String 32 | test = "TESTING" 33 | 34 | End Sub 35 | -------------------------------------------------------------------------------- /tests/data/vbscript.vbs: -------------------------------------------------------------------------------- 1 | ' 8 lines 3 code 3 comments 2 blanks 2 | Dim MyStr1, MyStr2 3 | 4 | MyStr1 = "Hello" 5 | 6 | ' This is also a comment 7 | MyStr2 = "Goodbye" 8 | REM Comment on a line 9 | -------------------------------------------------------------------------------- /tests/data/velocity.vm: -------------------------------------------------------------------------------- 1 | ## 11 lines 4 code 5 comments 2 blanks 2 | 3 | This text is visible. #* This text, as part of a multi-line 4 | comment, is not visible. This text is not visible; it is also 5 | part of the multi-line comment. This text still not 6 | visible. *# This text is outside the comment, so it is visible. 7 | ## This text is not visible. 8 | 9 | #macro( d ) 10 | 11 | #end 12 | -------------------------------------------------------------------------------- /tests/data/vhdl.vhd: -------------------------------------------------------------------------------- 1 | -- 34 lines 20 code 7 comments 7 blanks 2 | 3 | /* 4 | Since VHDL 2008 C-Style delimited comment are allowed. 5 | */ 6 | 7 | library IEEE; 8 | use IEEE.STD_LOGIC_1164.ALL; 9 | use IEEE.NUMERIC_STD.ALL; 10 | 11 | entity tb is 12 | Port ( clk : in STD_LOGIC; -- clock 13 | rst : in STD_LOGIC; -- reset 14 | -- removed: in STD_LOGIC_VECTOR(7 downto 0) 15 | ); 16 | end tb; 17 | 18 | -- architecture 19 | architecture behavioural of tb is 20 | signal toggle : STD_LOGIC := '0'; 21 | 22 | begin 23 | 24 | -- Toggles signal 25 | process(clk, rst) 26 | begin 27 | if (rst='1') then 28 | toggle <= '0'; 29 | else 30 | toggle <= not toggle; 31 | end if; 32 | end process; 33 | 34 | end 35 | -------------------------------------------------------------------------------- /tests/data/visualbasic.vb: -------------------------------------------------------------------------------- 1 | ' 7 lines 4 code 2 comments 1 blanks 2 | Public Class C 3 | Public Sub M() 4 | ' This is a comment 5 | End Sub 6 | 7 | End Class 8 | -------------------------------------------------------------------------------- /tests/data/vqe.qasm: -------------------------------------------------------------------------------- 1 | // 89 lines 58 code 21 comments 10 blanks 2 | /* 3 | * Variational eigensolver example 4 | * 5 | * Goal is to estimate the energy for a fixed set of parameters. 6 | * The parameters are updated outside of this program and a new 7 | * OpenQASM circuit is generated for the next iteration. 8 | */ 9 | include "stdgates.inc"; 10 | 11 | const int[32] n = 10; // number of qubits 12 | const int[32] layers = 3; // number of entangler layers 13 | const int[32] prec = 16; // precision of all types 14 | const int[32] shots = 1000; // number of shots per Pauli observable 15 | 16 | // Parameters could be written to local variables for this 17 | // iteration, but we will request them using extern functions 18 | extern get_parameter(uint[prec], uint[prec]) -> angle[prec]; 19 | extern get_npaulis() -> uint[prec]; 20 | extern get_pauli(int[prec]) -> bit[2 * n]; 21 | 22 | // The energy calculation uses floating point division, 23 | // so we do that calculation in an extern function 24 | extern update_energy(int[prec], uint[prec], float[prec]) -> float[prec]; 25 | 26 | gate entangler q { for uint i in [0:n-2] { cx q[i], q[i+1]; } } 27 | def xmeasure(qubit q) -> bit { h q; return measure q; } 28 | def ymeasure(qubit q) -> bit { s q; h q; return measure q; } 29 | 30 | /* Pauli measurement circuit. 31 | * The first n-bits of spec are the X component. 32 | * The second n-bits of spec are the Z component. 33 | */ 34 | def pauli_measurement(bit[2*n] spec, qubit[n] q) -> bit { 35 | bit b = 0; 36 | for uint[prec] i in [0: n - 1] { 37 | bit temp; 38 | if(spec[i]==1 && spec[n+i]==0) { temp = xmeasure(q[i]); } 39 | if(spec[i]==0 && spec[n+i]==1) { temp = measure q[i]; } 40 | if(spec[i]==1 && spec[n+i]==1) { temp = ymeasure(q[i]); } 41 | b ^= temp; 42 | } 43 | return b; 44 | } 45 | 46 | // Circuit to prepare trial wave function 47 | def trial_circuit(qubit[n] q) { 48 | for int[prec] l in [0: layers - 1] { 49 | for uint[prec] i in [0: n - 1] { 50 | angle[prec] theta; 51 | theta = get_parameter(l * layers + i); 52 | ry(theta) q[i]; 53 | } 54 | if(l != layers - 1) entangler q; 55 | } 56 | } 57 | 58 | /* Apply VQE ansatz circuit and measure a Pauli operator 59 | * given by spec. Return the number of 1 outcomes. 60 | */ 61 | def counts_for_term(bit[2*n] spec, qubit[n] q) -> uint[prec] { 62 | uint[prec] counts; 63 | for uint i in [1: shots] { 64 | bit b; 65 | reset q; 66 | trial_circuit q; 67 | b = pauli_measurement(spec, q); 68 | counts += int[1](b); 69 | } 70 | return counts; 71 | } 72 | 73 | // Estimate the expected energy 74 | def estimate_energy(qubit[n] q) -> float[prec] { 75 | float[prec] energy; 76 | uint[prec] npaulis = get_npaulis(); 77 | for int[prec] t in [0:npaulis-1] { 78 | bit[2*n] spec = get_pauli(t); 79 | uint[prec] counts; 80 | counts = counts_for_term(spec, q); 81 | energy = update_energy(t, counts, energy); 82 | } 83 | return energy; 84 | } 85 | 86 | qubit[n] q; 87 | float[prec] energy; 88 | 89 | energy = estimate_energy(q); 90 | -------------------------------------------------------------------------------- /tests/data/vue.vue: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 28 | 29 | 37 | -------------------------------------------------------------------------------- /tests/data/webassembly.wat: -------------------------------------------------------------------------------- 1 | ;; 10 lines 8 code 1 comments 1 blanks 2 | 3 | (module 4 | (import "console" "log" (func $log (param i32 i32))) 5 | (import "js" "mem" (memory 1)) 6 | (data (i32.const 0) "Hi") 7 | (func (export "writeHi") 8 | i32.const 0 ;; pass offset 0 to log 9 | i32.const 2 ;; pass length 2 to log 10 | call $log)) 11 | -------------------------------------------------------------------------------- /tests/data/wenyan.wy: -------------------------------------------------------------------------------- 1 | //! 141 lines 107 code 1 comments 33 blanks 2 | 吾嘗觀「「曆法」」之書。方悟「今何紀元時」「彼時何小時」「彼刻何刻」「彼分何分」「彼秒何秒」之義。 3 | 吾嘗觀「「畫譜」」之書。方悟「備紙」「擇筆」「蘸色」「落筆」「運筆」「提筆」「設色」「裱畫」之義。 4 | 吾嘗觀「「算經」」之書。方悟「倍圓周率」「正弦」「餘弦」之義。 5 | 6 | 施「今何紀元時」。名之曰「紀元時」。 7 | 施「彼時何小時」於「紀元時」。名之曰「小時」。 8 | 施「彼刻何刻」於「紀元時」。名之曰「刻」。 9 | 施「彼分何分」於「紀元時」。名之曰「分」。 10 | 施「彼秒何秒」於「紀元時」。名之曰「秒」。 11 | 12 | 有數四百。名之曰「紙縱」。 13 | 有數四百。名之曰「紙橫」。 14 | 除二於「紙縱」。名之曰「半縱」。 15 | 除二於「紙橫」。名之曰「半橫」。 16 | 吾有一數。名之曰「比例」。 17 | 18 | 批曰。「「文氣淋灕。字句切實」」。 19 | 20 | 若「半橫」小於「半縱」者。 21 | 昔之「比例」者。今「半橫」是矣。 22 | 若非。 23 | 昔之「比例」者。今「半縱」是矣。 24 | 云云。 25 | 26 | 吾有一術。名之曰「縱坐標」。欲行是術。必先得一數。曰「南」。是術曰。 27 | 乘「南」以「比例」。減其於「半縱」。乃得矣。 28 | 是謂「縱坐標」之術也。 29 | 30 | 吾有一術。名之曰「橫坐標」。欲行是術。必先得一數。曰「東」。是術曰。 31 | 乘「東」以「比例」。減其於「半橫」。乃得矣。 32 | 是謂「橫坐標」之術也。 33 | 34 | 吾有一術。名之曰「極坐標」。欲行是術。必先得二數。曰「距」。曰「角」。是術曰。 35 | 施「餘弦」於「角」。乘其以「距」。取一以施「縱坐標」。名之曰「縱」。 36 | 施「正弦」於「角」。乘其以「距」。取一以施「橫坐標」。名之曰「橫」。 37 | 吾有一物。名之曰「坐標」。其物如是。 38 | 物之「「橫」」者。數曰「橫」。 39 | 物之「「縱」」者。數曰「縱」。 40 | 是謂「坐標」之物也。乃得「坐標」。 41 | 是謂「極坐標」之術也。 42 | 43 | 吾有一術。名之曰「畫鐘面」。 44 | 欲行是術。必先得一物。曰「紙」。一數。曰「半徑」。 45 | 是術曰。 46 | 47 | 有數一千零二十四。名之曰「割圓」。 48 | 夫「半徑」。夫零。取二以施「極坐標」。名之曰「始坐標」。 49 | 夫「紙」。夫「始坐標」之「「橫」」。夫「始坐標」之「「縱」」。取三以施「落筆」。 50 | 51 | 有數一。名之曰「甲」。 52 | 為是「割圓」遍。 53 | 除「甲」以「割圓」。乘其以「倍圓周率」。名之曰「乙」。 54 | 夫「半徑」。夫「乙」。取二以施「極坐標」。名之曰「坐標」。 55 | 夫「紙」。夫「坐標」之「「橫」」。夫「坐標」之「「縱」」。取三以施「運筆」。 56 | 加「甲」以一。昔之「甲」者。今其是矣。 57 | 云云。 58 | 59 | 施「蘸色」於「紙」於「「鈦白」」。 60 | 施「設色」於「紙」。 61 | 施「蘸色」於「紙」於「「黑」」。 62 | 施「提筆」於「紙」。 63 | 64 | 有數零。名之曰「丙」。 65 | 66 | 為是六十遍。 67 | 除「丙」以六十。乘其以「倍圓周率」。名之曰「丁」。 68 | 夫「半徑」。夫「丁」。取二以施「極坐標」。名之曰「正刻外坐標」。 69 | 夫「紙」。夫「正刻外坐標」之「「橫」」。夫「正刻外坐標」之「「縱」」。取三以施「落筆」。 70 | 乘九分五於「半徑」。夫「丁」。取二以施「極坐標」。名之曰「正刻內坐標」。 71 | 夫「紙」。夫「正刻內坐標」之「「橫」」。夫「正刻內坐標」之「「縱」」。取三以施「運筆」。 72 | 施「提筆」於「紙」。 73 | 74 | 加「丙」以一。昔之「丙」者。今其是矣。 75 | 云云。 76 | 77 | 78 | 有數零。名之曰「丙」。 79 | 80 | 為是十二遍。 81 | 除「丙」以十二。乘其以「倍圓周率」。名之曰「戊」。 82 | 夫「半徑」。夫「戊」。取二以施「極坐標」。名之曰「初刻外坐標」。 83 | 夫「紙」。夫「初刻外坐標」之「「橫」」。夫「初刻外坐標」之「「縱」」。取三以施「落筆」。 84 | 乘八分五於「半徑」。夫「戊」。取二以施「極坐標」。名之曰「初刻內坐標」。 85 | 夫「紙」。夫「初刻內坐標」之「「橫」」。夫「初刻內坐標」之「「縱」」。取三以施「運筆」。 86 | 施「提筆」於「紙」。 87 | 88 | 加「丙」以一。昔之「丙」者。今其是矣。 89 | 云云。 90 | 91 | 是謂「畫鐘面」之術也。 92 | 93 | 吾有一術。名之曰「畫指針」。 94 | 欲行是術。必先得一物。曰「紙」。五數。曰「角」。曰「針長」。曰「尾長」。曰「針角」。曰「尾角」。 95 | 是術曰。 96 | 97 | 夫「針長」。加「針角」於「角」。取二以施「極坐標」。名之曰「甲」。 98 | 乘負一於「尾長」。減「尾角」於「角」。取二以施「極坐標」。名之曰「乙」。 99 | 乘負一於「尾長」。加「尾角」於「角」。取二以施「極坐標」。名之曰「丙」。 100 | 夫「針長」。減「針角」於「角」。取二以施「極坐標」。名之曰「丁」。 101 | 102 | 夫「紙」。夫「甲」之「「橫」」。夫「甲」之「「縱」」。取三以施「落筆」。 103 | 夫「紙」。夫「乙」之「「橫」」。夫「乙」之「「縱」」。取三以施「運筆」。 104 | 夫「紙」。夫「丙」之「「橫」」。夫「丙」之「「縱」」。取三以施「運筆」。 105 | 夫「紙」。夫「丁」之「「橫」」。夫「丁」之「「縱」」。取三以施「運筆」。 106 | 夫「紙」。夫「甲」之「「橫」」。夫「甲」之「「縱」」。取三以施「運筆」。 107 | 108 | 施「蘸色」於「紙」於「「花青」」。 109 | 施「設色」於「紙」。 110 | 111 | 是謂「畫指針」之術也。 112 | 113 | 吾有一術。名之曰「执笔」。是術曰。 114 | 115 | 施「(()=>document.getElementById("out").innerHTML="")」。 116 | 施「今何紀元時」。名之曰「紀元時」。 117 | 施「彼時何小時」於「紀元時」。名之曰「時」。 118 | 施「彼分何分」於「紀元時」。名之曰「分」。 119 | 施「彼刻何刻」於「紀元時」。名之曰「刻」。 120 | 施「彼秒何秒」於「紀元時」。名之曰「秒」。 121 | 122 | 乘「刻」以十五。加其於「分」。昔之「分」者。今其是矣。 123 | 124 | 除「秒」以六十。加其於「分」。昔之「分」者。今其是矣。 125 | 除「分」以六十。加其於「時」。昔之「時」者。今其是矣。 126 | 127 | 除「分」以六十。乘其以「倍圓周率」。乘其以負一。名之曰「分角」。 128 | 除「時」以十二。乘其以「倍圓周率」。乘其以負一。名之曰「時角」。 129 | 除「秒」以六十。乘其以「倍圓周率」。乘其以負一。名之曰「秒角」。 130 | 131 | 132 | 施「備紙」於「紙橫」。於「紙縱」。名之曰「紙」。 133 | 施「畫鐘面」於「紙」。於九分。 134 | 施「畫指針」於「紙」。於「秒角」。於八分。於一分。於三毫。於一分。 135 | 施「畫指針」於「紙」。於「分角」。於七分五釐。於一分。於三毫。於三分。 136 | 施「畫指針」於「紙」。於「時角」。於五分五釐。於八釐。於五毫。於五分。 137 | 施「裱畫」於「紙」於「「out」」。 138 | 139 | 是謂「执笔」之術也。 140 | 141 | 施「(x=>setInterval(x, 500))」於「执笔」。 -------------------------------------------------------------------------------- /tests/data/wgsl.wgsl: -------------------------------------------------------------------------------- 1 | // 13 lines 10 code 2 comments 1 blanks 2 | // comment 3 | [[stage(vertex)]] 4 | fn vs_main([[builtin(vertex_index)]] in_vertex_index: u32) -> [[builtin(position)]] vec4 { 5 | const x = f32(i32(in_vertex_index) - 1); 6 | const y = f32(i32(in_vertex_index & 1u) * 2 - 1); 7 | return vec4(x, y, 0.0, 1.0); 8 | } 9 | 10 | [[stage(fragment)]] 11 | fn fs_main() -> [[location(0)]] vec4 { 12 | return vec4(1.0, 0.0, 0.0, 1.0); 13 | } 14 | -------------------------------------------------------------------------------- /tests/data/xsl.xsl: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/data/xtend.xtend: -------------------------------------------------------------------------------- 1 | // 23 lines 13 code 4 comments 6 blanks 2 | 3 | class Test { 4 | 5 | static def void main(String[] args) { 6 | /* 7 | * Multiline comment 8 | */ 9 | val f = new Foo() 10 | f.bar() // Not counted 11 | } 12 | 13 | } 14 | 15 | class Foo { 16 | 17 | def bar() { 18 | println('string type 1') 19 | println("string type 2") 20 | println('''string type 3''') 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /tests/data/yaml.yaml: -------------------------------------------------------------------------------- 1 | # 34 lines 29 code 3 comments 2 blanks 2 | 3 | # Manifest file from Kubernetes documentation: 4 | # https://kubernetes.io/docs/tutorials/stateless-application/guestbook/ 5 | 6 | apiVersion: apps/v1 7 | kind: Deployment 8 | metadata: 9 | name: redis-master 10 | labels: 11 | app: redis 12 | spec: 13 | selector: 14 | matchLabels: 15 | app: redis 16 | role: master 17 | tier: backend 18 | replicas: 1 19 | template: 20 | metadata: 21 | labels: 22 | app: redis 23 | role: master 24 | tier: backend 25 | spec: 26 | containers: 27 | - name: master 28 | image: k8s.gcr.io/redis:e2e 29 | resources: 30 | requests: 31 | cpu: 100m 32 | memory: 100Mi 33 | ports: 34 | - containerPort: 6379 -------------------------------------------------------------------------------- /tests/data/zencode.zs: -------------------------------------------------------------------------------- 1 | // 21 lines 9 code 7 comments 5 blanks 2 | 3 | // This is a single line comment. 4 | /* This is a multiline comment on a single line. */ 5 | /* 6 | This is a multiline comment. 7 | */ 8 | 9 | var str = "/*"; 10 | var arr = [str, @"wysiwyg", '\"']; 11 | 12 | for item in arr { 13 | print(item); // Found the */ 14 | } 15 | 16 | // Comment with quote " 17 | 18 | var badStr = // Comment before value 19 | "\""; 20 | badStr = // Another comment before value 21 | @'zen'; 22 | -------------------------------------------------------------------------------- /tests/data/zig.zig: -------------------------------------------------------------------------------- 1 | // 11 lines 5 code 3 comments 3 blanks 2 | 3 | /// Documentation comment 4 | pub fn main() void { 5 | const a = 5; // not-counted 6 | 7 | // Leading-comment 8 | const b = c"line comment embedded //"; 9 | const c = \\line comment embedded // // 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/data/zokrates.zok: -------------------------------------------------------------------------------- 1 | // 11 lines 3 code 6 comments 2 blanks 2 | 3 | /* 4 | This is a multi-line comment 5 | written in more than just one line. 6 | */ 7 | 8 | def main() -> field { 9 | // an inline comment 10 | return 42; // on a line. 11 | } 12 | -------------------------------------------------------------------------------- /tests/embedding/file_triggeringprincipal_frame_1.html: -------------------------------------------------------------------------------- 1 | 2 | < 0!DOCTYPE HTML> 3 | 4 | 5 | 6 | Frame 1
7 | 8 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /tokei.example.toml: -------------------------------------------------------------------------------- 1 | # The width of the terminal output in columns. 2 | columns = 80 3 | # Sort languages based on the specified column. 4 | sort = "lines" 5 | # If set, tokei will only show the languages in `types`. 6 | types = ["Python"] 7 | # Any doc strings (e.g. `"""hello"""` in python) will be counted as comments. 8 | treat_doc_strings_as_comments = true 9 | --------------------------------------------------------------------------------