Rust-Ncurses rs: ncurses-rs — ncurses bindings

ncurses-rs Build Status

This is a very thin wrapper around the ncurses TUI lib.

NOTE: The ncurses lib is terribly unsafe and ncurses-rs is only the lightest wrapper it can be. If you want a safe and idiomatic TUI library for Rust, look elsewhere. If you want a 1:1 port of C to Rust or you want to crank a TUI out C-style in Rust, this will probably do the trick.

Building

The compiled library will go to the target directory.

cargo build

Note that you must to have the ncurses library installed and linkable for ncurses-rs to work. On Linux, this should be trivial. On OS X, consider installing ncurses using Homebrew. (Note that you have to force Homebrew to link the library to /usr/local/lib: brew link --force ncurses and set that path to LIBRARY_PATH environmental variable.)

Examples

Examples are built by cargo build. To run them, use cargo run --example ex_<NUMBER>. Example numbers increase along with the complexity of the example.

Current examples:
1. Hello World
2. Basic Input & Attributes
3. Simple Pager
4. Window Movement
5. Menu Library (requires rust nightly)
6. Pager & Syntax Highlighting
7. Basic Input & Attributes (Unicode)
8. Special ACS Characters

Environment variables

Some environment variables are read by build.rs:

If set, NCURSES_RS_RUSTC_LINK_LIB will be used for NCURSES_RS_RUSTC_LINK_LIB.

If set, NCURSES_RS_RUSTC_FLAGS will be used for cargo:rustc-flags.

If set, NCURSES_RS_CFLAGS will be used for the compilation of the test program chtype_size.c.

Comments

  • Memory Leak, even when destroying windows
    Memory Leak, even when destroying windows

    May 24, 2019

    example: I have run ex_4.rs sample with valgrind tool

    ==27342== LEAK SUMMARY: ==27342== definitely lost: 0 bytes in 0 blocks ==27342== indirectly lost: 0 bytes in 0 blocks ==27342== possibly lost: 0 bytes in 0 blocks ==27342== still reachable: 499,249 bytes in 238 blocks ==27342== suppressed: 0 bytes in 0 blocks ==27342== ==27342== For counts of detected and suppressed errors, rerun with: -v ==27342== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

    Reply
  • Tracker: All unsafe blocks must be removed and then re-added one by one after careful verification of actual safety.
    Tracker: All unsafe blocks must be removed and then re-added one by one after careful verification of actual safety.

    Sep 3, 2019

    Using the FFI is unsafe, but simply putting unsafe { } around the call is not enough to get rid of the problem. It's unsafe for a reason. It's unsafe because it can do horrible things and cause UB.

    You need to adjust the library so that only functions that cannot possibly cause UB, no matter what, are wrapped in an unsafe block and marked as safe. All other functions must be left as unsafe functions, hopefully with explanations in the docs of what to do to avoid problems.

    help wanted 
    Reply
  • Modified examples printw -> addstr
    Modified examples printw -> addstr

    Dec 11, 2019

    Hi, I'm masahiko-ofgp.

    I tried using the example of ncurses-rs. However, since printw was displayed as being deprecated, I changed printw to addstr. I'm sorry if it was unnecessary.

    my environment:

    • Manjaro Linux
    • Rust edition 2018
    Reply
  • undefined reference to `COLORS'
    undefined reference to `COLORS'

    Dec 12, 2019

    When compiling ncspot from git, I have this linker error at the end:

    ...
    pe" "-lxcb-xfixes" "-lncursesw" "-ltinfo" "-lutil" "-lutil" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
      = note: /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: /home/aplanas/ncspot/target/release/deps/libncurses-9568030c4c279be4.rlib(ncurses-9568030c4c279be4.ncurses.6tisobd3-cgu.4.rcgu.o): in function `ncurses::constants::COLORS':
              ncurses.6tisobd3-cgu.4:(.text._ZN7ncurses9constants6COLORS17h28f96c61a3832871E+0x3): undefined reference to `COLORS'
              collect2: error: ld returned 1 exit status
    

    I have openSUSE Tumbleweed:

    > rpm -qa | grep ncurses
    ncurses-devel-6.1-24.1.x86_64
    ncurses-utils-6.1-24.1.x86_64
    libncurses6-6.1-24.1.x86_64
    
    > rpm -qa | grep terminfo
    terminfo-screen-6.1-24.1.x86_64
    terminfo-6.1-24.1.x86_64
    terminfo-base-6.1-24.1.x86_64
    
    Reply
  • failure to build on architecture arm64
    failure to build on architecture arm64

    Apr 25, 2020

    Hi

    I'm packaging this crate for debian, and it fails to build on arm64 with the following error:

    error[E0308]: mismatched types
       --> src/menu/wrapper.rs:166:39
        |
    166 |             let _ = CString::from_raw(name);
        |                                       ^^^^ expected `u8`, found `i8`
        |
        = note: expected raw pointer `*mut u8`
                   found raw pointer `*mut i8`
    

    Full build log can be found here: https://ci.debian.net/data/autopkgtest/testing/arm64/r/rust-ncurses/5114573/log.gz

    I think the correct solution should be to cast to c_char instead of i8, per this commit: https://github.com/alexanderkjall/ncurses-rs/commit/4fe1f7dc230673d48bc46c67b2522dda6a67b601

    But I haven't managed to get hold of a arm64 system to test it yet.

    Reply
  • for building on arm64
    for building on arm64

    Apr 26, 2020

    fixes https://github.com/jeaye/ncurses-rs/issues/193

    Reply
  • Fix Makefile for OSX
    Fix Makefile for OSX

    Nov 28, 2014

    This fixes an issue with the Makefile caused by the version of sed that ships with OSX. It does rely on uname existing, but I think that's fair considering the platforms ncurses itself is available for.

    Reply
  • Should  ncurses-rs perform / expose `setlocale`.
    Should ncurses-rs perform / expose `setlocale`.

    Jan 28, 2015

    For wide characters to work, before initializing ncurses the following must be done:

    setlocale(LC_CTYPE, "");
    

    Right now I've resorted to using https://github.com/mahkoh/posix.rs.git, but it seems an overkill to include another library to do something that is a part of standard procedure.

    How about including setlocale in ncurses-rs?

    Reply
  • Add resize_term functions
    Add resize_term functions

    Dec 13, 2017

    Add the three resize_term functions (resize_term, resizeterm, is_term_resized). I don't see any reason for these to not be a part of the library.

    For reference, see http://invisible-island.net/ncurses/man/resizeterm.3x.html or the ncurses man page (specifically the resizeterm man page).

    Reply
  • test fail to build on fedora 25:   undefined reference to 'wget_wch'
    test fail to build on fedora 25: undefined reference to 'wget_wch'

    Oct 13, 2017

    ncurses 6.0

    cargo test  --verbose
    
    warning: path `/tmp/ncurses-rs/src/ncurses.rs` was erroneously implicitly accepted for library `ncurses`,
    please rename the file to `src/lib.rs` or set lib.path in Cargo.toml
           Fresh libc v0.2.32
           Fresh gcc v0.3.54
           Fresh pkg-config v0.3.9
       Compiling ncurses v5.86.0 (file:///tmp/ncurses-rs)
         Running `rustc --crate-name ex_7 examples/ex_7.rs --crate-type bin --emit=dep-info,link -C debuginfo=2 --cfg 'feature="default"' -C metadata=32c66cdfcc872a56 -C extra-filename=-32c66cdfcc872a56 --out-dir /tmp/ncurses-rs/target/debug/examples -L dependency=/tmp/ncurses-rs/target/debug/deps --extern libc=/tmp/ncurses-rs/target/debug/deps/liblibc-126a44a53dfd6129.rlib --extern ncurses=/tmp/ncurses-rs/target/debug/deps/libncurses-9c81af12678bde21.rlib -C target-cpu=native -L native=/usr/lib64`
    error: linking with `cc` failed: exit code: 1
      |
      = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_70.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_71.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_710.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_711.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_712.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_713.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_714.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_715.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_72.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_73.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_74.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_75.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_76.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_77.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_78.rust-cgu.o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.ex_79.rust-cgu.o" "-o" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56" "/tmp/ncurses-rs/target/debug/examples/ex_7-32c66cdfcc872a56.crate.allocator.rust-cgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "-L" "/tmp/ncurses-rs/target/debug/deps" "-L" "/usr/lib64" "-L" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/tmp/ncurses-rs/target/debug/deps/libncurses-9c81af12678bde21.rlib" "/tmp/ncurses-rs/target/debug/deps/liblibc-126a44a53dfd6129.rlib" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-ef68455a36f432e0.rlib" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_jemalloc-f6e1402098866357.rlib" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_system-4217dfafb936c36b.rlib" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librand-97fa3d5ef4bd4fdd.rlib" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-cf9300d96e8efc7d.rlib" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-e6f731c8a56b92a5.rlib" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-58100a6f9c048547.rlib" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-f59d3752d69fd895.rlib" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_unicode-fe3fcd278911a505.rlib" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-fcc46f3067b1a58b.rlib" "/home/matthias/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-295aef536590064a.rlib" "-Wl,-Bdynamic" "-l" "ncurses" "-l" "tinfo" "-l" "util" "-l" "dl" "-l" "rt" "-l" "pthread" "-l" "pthread" "-l" "gcc_s" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util"
      = note: src/ncurses.rs:349: error: undefined reference to 'wget_wch'
              collect2: error: ld returned 1 exit status
              
    
    error: aborting due to previous error
    
    error: Could not compile `ncurses`.
    
    Caused by:
      process didn't exit successfully: `rustc --crate-name ex_7 examples/ex_7.rs --crate-type bin --emit=dep-info,link -C debuginfo=2 --cfg feature="default" -C metadata=32c66cdfcc872a56 -C extra-filename=-32c66cdfcc872a56 --out-dir /tmp/ncurses-rs/target/debug/examples -L dependency=/tmp/ncurses-rs/target/debug/deps --extern libc=/tmp/ncurses-rs/target/debug/deps/liblibc-126a44a53dfd6129.rlib --extern ncurses=/tmp/ncurses-rs/target/debug/deps/libncurses-9c81af12678bde21.rlib -C target-cpu=native -L native=/usr/lib64` (exit code: 101)
    
    Reply
  • Relicense under dual MIT/Apache-2.0
    Relicense under dual MIT/Apache-2.0

    Jan 10, 2016

    This issue was automatically generated. Feel free to close without ceremony if you do not agree with re-licensing or if it is not possible for other reasons. Respond to @cmr with any questions or concerns, or pop over to #rust-offtopic on IRC to discuss.

    You're receiving this because someone (perhaps the project maintainer) published a crates.io package with the license as "MIT" xor "Apache-2.0" and the repository field pointing here.

    TL;DR the Rust ecosystem is largely Apache-2.0. Being available under that license is good for interoperation. The MIT license as an add-on can be nice for GPLv2 projects to use your code.

    Why?

    The MIT license requires reproducing countless copies of the same copyright header with different names in the copyright field, for every MIT library in use. The Apache license does not have this drawback. However, this is not the primary motivation for me creating these issues. The Apache license also has protections from patent trolls and an explicit contribution licensing clause. However, the Apache license is incompatible with GPLv2. This is why Rust is dual-licensed as MIT/Apache (the "primary" license being Apache, MIT only for GPLv2 compat), and doing so would be wise for this project. This also makes this crate suitable for inclusion and unrestricted sharing in the Rust standard distribution and other projects using dual MIT/Apache, such as my personal ulterior motive, the Robigalia project.

    Some ask, "Does this really apply to binary redistributions? Does MIT really require reproducing the whole thing?" I'm not a lawyer, and I can't give legal advice, but some Google Android apps include open source attributions using this interpretation. Others also agree with it. But, again, the copyright notice redistribution is not the primary motivation for the dual-licensing. It's stronger protections to licensees and better interoperation with the wider Rust ecosystem.

    How?

    To do this, get explicit approval from each contributor of copyrightable work (as not all contributions qualify for copyright, due to not being a "creative work", e.g. a typo fix) and then add the following to your README:

    ## License
    
    Licensed under either of
    
     * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
     * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
    
    at your option.
    
    ### Contribution
    
    Unless you explicitly state otherwise, any contribution intentionally submitted
    for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
    additional terms or conditions.
    

    and in your license headers, if you have them, use the following boilerplate (based on that used in Rust):

    // Copyright 2016 ncurses-rs Developers
    //
    // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
    // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
    // http://opensource.org/licenses/MIT>, at your option. This file may not be
    // copied, modified, or distributed except according to those terms.
    

    It's commonly asked whether license headers are required. I'm not comfortable making an official recommendation either way, but the Apache license recommends it in their appendix on how to use the license.

    Be sure to add the relevant LICENSE-{MIT,APACHE} files. You can copy these from the Rust repo for a plain-text version.

    And don't forget to update the license metadata in your Cargo.toml to:

    license = "MIT OR Apache-2.0"
    

    I'll be going through projects which agree to be relicensed and have approval by the necessary contributors and doing this changes, so feel free to leave the heavy lifting to me!

    Contributor checkoff

    To agree to relicensing, comment with :

    I license past and future contributions under the dual MIT/Apache-2.0 license, allowing licensees to chose either at their option.
    

    Or, if you're a contributor, you can check the box in this repo next to your name. My scripts will pick this exact phrase up and check your checkbox, but I'll come through and manually review this issue later as well.

    • [ ] @Gyscos
    • [ ] @LindseyB
    • [ ] @Marckvdv
    • [ ] @NewbiZ
    • [ ] @Reisen
    • [x] @aatxe
    • [ ] @alan-andrade
    • [ ] @alexchandel
    • [ ] @arbitrary-cat
    • [ ] @benekastah
    • [ ] @brandonson
    • [ ] @chengsun
    • [ ] @chris-morgan
    • [x] @cmr
    • [ ] @coolwanglu
    • [ ] @dpc
    • [ ] @dsyang
    • [ ] @ebfe
    • [ ] @emintham
    • [ ] @euclio
    • [ ] @evanpw
    • [ ] @golddranks
    • [ ] @hsoft
    • [ ] @hyPiRion
    • [ ] @itsjustsoda
    • [ ] @jeaye
    • [ ] @jxs
    • [ ] @leshow
    • [ ] @mahkoh
    • [ ] @manuc66
    • [ ] @marchelzo
    • [ ] @petevine
    • [ ] @phillipw
    • [ ] @pmsanford
    • [ ] @skullzzz
    • [ ] @tsurai
    • [ ] @uasi
    • [ ] @untitaker
    • [ ] @utkarshkukreti
    • [ ] @yeahnoob
    Reply
  • Added mouse support.
    Added mouse support.

    Jan 26, 2014

    I've added mouse support. I tested building against the latest rust and it worked, but I can't write an example to test it out. I was able to run has_mouse(), but it returns false for me. Hopefully that's not because of something I did wrong :)

    Try it out and let me know.

    Reply