{"id":31978561,"url":"https://github.com/deinstapel/cursive-tabs","last_synced_at":"2025-10-14T22:23:00.049Z","repository":{"id":45005530,"uuid":"205585605","full_name":"deinstapel/cursive-tabs","owner":"deinstapel","description":"Tabs for gyscos/cursive views 🖥️","archived":false,"fork":false,"pushed_at":"2024-08-12T17:33:51.000Z","size":473,"stargazers_count":30,"open_issues_count":5,"forks_count":8,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-09-20T02:38:23.953Z","etag":null,"topics":["cursive","cursive-views","gyscos","tabs","tui","view"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/deinstapel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-31T19:05:18.000Z","updated_at":"2025-08-19T10:58:08.000Z","dependencies_parsed_at":"2024-08-12T20:15:40.099Z","dependency_job_id":null,"html_url":"https://github.com/deinstapel/cursive-tabs","commit_stats":{"total_commits":133,"total_committers":7,"mean_commits":19.0,"dds":"0.24812030075187974","last_synced_commit":"52e94cb6bc686a209127ce7bf9b7087a2d602ba2"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/deinstapel/cursive-tabs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deinstapel%2Fcursive-tabs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deinstapel%2Fcursive-tabs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deinstapel%2Fcursive-tabs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deinstapel%2Fcursive-tabs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deinstapel","download_url":"https://codeload.github.com/deinstapel/cursive-tabs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deinstapel%2Fcursive-tabs/sbom","scorecard":{"id":332738,"data":{"date":"2025-08-11","repo":{"name":"github.com/deinstapel/cursive-tabs","commit":"12998c24702f3e537946235db3a372e1bce3809c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":1,"reason":"Found 4/22 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: downloadThenRun not pinned by hash: .github/workflows/test_and_push.yml:18","Info:   0 out of   1 downloadThenRun dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/test_and_push.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 12 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T03:58:30.769Z","repository_id":45005530,"created_at":"2025-08-18T03:58:30.769Z","updated_at":"2025-08-18T03:58:30.769Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279021779,"owners_count":26087055,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cursive","cursive-views","gyscos","tabs","tui","view"],"created_at":"2025-10-14T22:22:56.616Z","updated_at":"2025-10-14T22:23:00.041Z","avatar_url":"https://github.com/deinstapel.png","language":"Rust","readme":"\u003ch1 align=\"center\"\u003eWelcome to cursive-tabs 👋\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/deinstapel/cursive-tabs/actions\"\u003e\n    \u003cimg src=\"https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fdeinstapel.github.io%2Fcursive-tabs%2Fstable-build.json\" alt=\"stable build\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/deinstapel/cursive-tabs/actions\"\u003e\n    \u003cimg src=\"https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fdeinstapel.github.io%2Fcursive-tabs%2Fnightly-build.json\" alt=\"nightly build\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://crates.io/crates/cursive-tabs\"\u003e\n    \u003cimg alt=\"crates.io\" src=\"https://img.shields.io/crates/v/cursive-tabs.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://docs.rs/cursive-tabs\"\u003e\n    \u003cimg alt=\"Docs.rs\" src=\"https://docs.rs/cursive-tabs/badge.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/deinstapel/cursive-tabs/blob/master/LICENSE\"\u003e\n    \u003cimg alt=\"GitHub\" src=\"https://img.shields.io/github/license/deinstapel/cursive-tabs.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"http://spacemacs.org\"\u003e\n    \u003cimg src=\"https://cdn.rawgit.com/syl20bnr/spacemacs/442d025779da2f62fc86c2082703697714db6514/assets/spacemacs-badge.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"http://makeapullrequest.com\"\u003e\n    \u003cimg alt=\"PRs Welcome\" src=\"https://img.shields.io/badge/PRs-welcome-brightgreen.svg\"\u003e\n  \u003c/a\u003e\n  \u003cbr\u003e\n  \u003ci\u003eA tab view wrapper for\n  \u003ca href=\"https://github.com/gyscos/cursive\"\u003egyscos/cursive\u003c/a\u003e\n  views\u003c/i\u003e\n\u003c/p\u003e\n\n---\n\n\u003e This project is work-in-progress\n\nThis project provides a wrapper view to be able to easily handle multiple tabs that can be switched to at any time without having to change the order of the views for [gyscos/cursive](https://github.com/gyscos/cursive) views.\n\n## How does it look like? `demo` [![terminalizer](https://img.shields.io/badge/GIF-terminalizer-blueviolet.svg)](https://github.com/faressoft/terminalizer)\n\n\u003cdetails\u003e\n  \u003csummary\u003eExpand to view\u003c/summary\u003e\n  \u003cimg src=\"assets/demo.gif\" alt=\"tabs demo\"\u003e\n\u003c/details\u003e\n\n## Usage\n\nSimply add to your `Cargo.toml`\n\n```toml\n[dependencies]\ncursive-tabs = \"^0\"\n```\n\n### Creating a `TabPanel`\n\nThe easiest way to use this crate is by creating a `TabPanel` and add your views to it.\nIn the `TabPanel` included is a bar that shows all tabs and allows to switch between them by clicking the desired tab. \nBelow it is the `TabView` showing the current tab.\n\nIt can be created by simply calling new on `TabPanel` and views and customize it as you want, have a look at the [documentation](https://docs.rs/cursive-tabs) to see all options.\n\n```rust\nuse cursive::views::TextView;\nuse cursive_tabs::TabPanel;\nuse cursive::view::Nameable;\n\nlet mut siv = cursive::default();\n\n//Create your panel and add tabs\nlet mut panel = TabPanel::new()\n    .with_tab(TextView::new(\"This is the first view!\").with_name(\"First\"))\n    .with_tab(TextView::new(\"This is the second view!\").with_name(\"Second\"));\nsiv.add_layer(panel);\nsiv.run();\n```\n\n### Creating a `TabView`\n\nThis crate also provides a struct `TabView` you can use to add tabs and switch between them, if you do not need a separate bar to switch and e.g. want to switch programmatically.\n\nThe `TabView` can also be used to create your own Panel/Bar if you want to design your cursive environment a different way.\n\n```rust\nuse cursive::{views::TextView};\nuse cursive_tabs::TabView;\nuse cursive::view::Nameable;\n\nlet mut siv = cursive::default();\nlet tabs = TabView::new().with_tab(TextView::new(\"Our first tab!\").with_name(\"0\"));\n// We can continue to add as many tabs as we want!\n\nsiv.add_layer(tabs);\nsiv.run();\n```\n\nLook into the [documentation](https://docs.rs/cursive-tabs) for more examples and a detailed explanation.\n\n### Creating your own Panel :hammer::construction:\n\nWhen you create a `TabBar` it will more or less look similar to the view e.g. also used in the example. To customize it you then need to create a view, creating a `TabBar` and a `TabView` events between them can be exchanged e.g. with channels.\nChannels have been chosen in this case by us, because they provide the easiest way to communicate between to instances of views in cursive.\n\nTo make these channels work you have to create two separate channels transmitting both keys, once for the direction from the bar to the tab view, transmitting keys that have been selected by e.g. buttons, and the other from the tab view to the bar.\n\nAn example for such a button would look like this.\n```rust \nlet button_tx_clone = button_tx.clone();\nlet button = Button::new_raw(format!(\" {} \", key), move |_| {\n                match button_tx_clone.send(key) {\n                    Ok(_) =\u003e {}\n                    Err(err) =\u003e {\n                        debug!(\"button could not send key: {:?}\", err);\n                    }\n                }\n            });\n```\n\nTo make the `TabView` respond to messages over this channel pass the receiving end to the tab view via the method `set_bar_rx`.\n\nThe other direction can be set by passing the Sender to `TabView` via the method `set_active_key_tx`. In this channel the currently active is send everytime a switch between tabs occurs. You can use this to register switches in your tab bar.\n\nThe rest is depending on how you want to style your panel, but if you have anymore questions or problems have a look at the source of the provided `TabPanel`.\n \n## Troubleshooting\n\nIf you find any bugs/unexpected behaviour or you have a proposition for future changes open an issue describing the current behaviour and what you expected.\n\n## Development [![cargo test](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fdeinstapel.github.io%2Fcursive-tabs%2Fcargo-test.json)](https://github.com/deinstapel/cursive-tabs/actions)\n\n### Running the tests\n\n#### Running all test suites\n\nJust run\n\n```\n$ cargo test\n```\n\nto execute all available tests.\n\n#### Investigating failed tests\n\nIn case some test fails with your changes, you can use the `cargo-insta` tool to investigate the test case.\n\nTo install\n```\n$ cargo install cargo-insta\n```\n\nand to run the tests and investigate all failing tests interactively.\n\n```\n$ cargo insta review\n```\n\n\nAny changes between the expected and received screen will be then displayed.\n\n#### shields.io endpoints\n\n[shields.io](https://shields.io) endpoints are generated inside the `./target/shields` folder. They are used in this README.\n\n### Public API naming\n\nThe current public API of this crate is not consistent with [RFC 344](https://github.com/rust-lang/rfcs/pull/344). This is due to `cursive` itself not being\nconsistent with `RFC 344`. This crate tries to implement a smooth user experience for cursive\nusers. Therefore, the `cursive` naming convention was adapted. When `cursive` upstream converts\ntheir API to a `RFC 344` consistent naming scheme, this crate will adapt to the changes.\n\n## Authors\n\n**Fin Christensen**\n\n\u003e [:octocat: `@fin-ger`](https://github.com/fin-ger)  \n\u003e [:elephant: `@fin_ger@weirder.earth`](https://weirder.earth/@fin_ger)  \n\u003e [:bird: `@fin_ger_github`](https://twitter.com/fin_ger_github)  \n\n\u003cbr\u003e\n\n**Johannes Wünsche**\n\n\u003e [:octocat: `@jwuensche`](https://github.com/jwuensche)  \n\u003e [:elephant: `@fredowald@mastodon.social`](https://mastodon.social/web/accounts/843376)  \n\u003e [:bird: `@Fredowald`](https://twitter.com/fredowald)  \n\n## Show your support\n\nGive a :star: if this project helped you!\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeinstapel%2Fcursive-tabs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeinstapel%2Fcursive-tabs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeinstapel%2Fcursive-tabs/lists"}