auto merge of #11120 : alexcrichton/rust/rustdoc-test, r=brson
This commit adds a `--test` flag to rustdoc to expose the ability to test code examples in doc strings. This work by using sundown's `lang` attribute to figure out how a code block should be tested. The format for this is: ``` 1. ```rust 2. ```rust,ignore 3. ```rust,notest 4. ```rust,should_fail ``` Where `rust` means that rustdoc will attempt to test is, `ignore` means that it will not execute the test but it will compile it, `notest` means that rustdoc completely ignores it, and `should_fail` means that the test should fail. This commit also leverages `extra::test` for the testing harness in order to allow parallelization and whatnot. I have fixed all existing code examples in libstd and libextra, but I have not made a pass through the crates in order to change code blocks to testable code blocks. It may also be a questionable decision to require opting-in to a testable code block. Finally, I kept our sugar in the doc suite to omit lines starting with `#` in documentation but still process them during tests. Closes #2925
This commit is contained in:
commit
d9c06586f2
|
@ -85,3 +85,92 @@ javascript and a statically-generated search index. No special web server is
|
|||
required for the search.
|
||||
|
||||
[sundown]: https://github.com/vmg/sundown/
|
||||
|
||||
# Testing the Documentation
|
||||
|
||||
`rustdoc` has support for testing code examples which appear in the
|
||||
documentation. This is helpful for keeping code examples up to date with the
|
||||
source code.
|
||||
|
||||
To test documentation, the `--test` argument is passed to rustdoc:
|
||||
|
||||
~~~
|
||||
rustdoc --test crate.rs
|
||||
~~~
|
||||
|
||||
## Defining tests
|
||||
|
||||
Rust documentation currently uses the markdown format, and code blocks can refer
|
||||
to any piece of code-related documentation, which isn't always rust. Because of
|
||||
this, only code blocks with the language of "rust" will be considered for
|
||||
testing.
|
||||
|
||||
~~~
|
||||
```rust
|
||||
// This is a testable code block
|
||||
```
|
||||
|
||||
```
|
||||
// This is not a testable code block
|
||||
```
|
||||
|
||||
// This is not a testable code block (4-space indent)
|
||||
~~~
|
||||
|
||||
In addition to only testing "rust"-language code blocks, there are additional
|
||||
specifiers that can be used to dictate how a code block is tested:
|
||||
|
||||
~~~
|
||||
```rust,ignore
|
||||
// This code block is ignored by rustdoc, but is passed through to the test
|
||||
// harness
|
||||
```
|
||||
|
||||
```rust,should_fail
|
||||
// This code block is expected to generate a failure
|
||||
```
|
||||
~~~
|
||||
|
||||
Rustdoc also supplies some extra sugar for helping with some tedious
|
||||
documentation examples. If a line is prefixed with a `#` character, then the
|
||||
line will not show up in the HTML documentation, but it will be used when
|
||||
testing the code block.
|
||||
|
||||
~~~
|
||||
```rust
|
||||
# // showing 'fib' in this documentation would just be tedious and detracts from
|
||||
# // what's actualy being documented.
|
||||
# fn fib(n: int) { n + 2 }
|
||||
|
||||
do spawn { fib(200); }
|
||||
```
|
||||
~~~
|
||||
|
||||
The documentation online would look like `do spawn { fib(200); }`, but when
|
||||
testing this code, the `fib` function will be included (so it can compile).
|
||||
|
||||
## Running tests (advanced)
|
||||
|
||||
Running tests often requires some special configuration to filter tests, find
|
||||
libraries, or try running ignored examples. The testing framework that rustdoc
|
||||
uses is build on `extra::test`, which is also used when you compile crates with
|
||||
rustc's `--test` flag. Extra arguments can be passed to rustdoc's test harness
|
||||
with the `--test-args` flag.
|
||||
|
||||
~~~
|
||||
// Only run tests containing 'foo' in their name
|
||||
rustdoc --test lib.rs --test-args 'foo'
|
||||
|
||||
// See what's possible when running tests
|
||||
rustdoc --test lib.rs --test-args '--help'
|
||||
|
||||
// Run all ignored tests
|
||||
rustdoc --test lib.rs --test-args '--ignored'
|
||||
~~~
|
||||
|
||||
When testing a library, code examples will often show how functions are used,
|
||||
and this code often requires `use`-ing paths from the crate. To accomodate this,
|
||||
rustdoc will implicitly add `extern mod <crate>;` where `<crate>` is the name of
|
||||
the crate being tested to the top of each code example. This means that rustdoc
|
||||
must be able to find a compiled version of the library crate being tested. Extra
|
||||
search paths may be added via the `-L` flag to `rustdoc`.
|
||||
|
|
27
mk/tests.mk
27
mk/tests.mk
|
@ -15,6 +15,7 @@
|
|||
|
||||
# The names of crates that must be tested
|
||||
TEST_TARGET_CRATES = std extra rustuv
|
||||
TEST_DOC_CRATES = std extra
|
||||
TEST_HOST_CRATES = rustpkg rustc rustdoc syntax
|
||||
TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES)
|
||||
|
||||
|
@ -281,6 +282,7 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
|
|||
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rmake-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-bench-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \
|
||||
|
@ -303,6 +305,10 @@ check-stage$(1)-T-$(2)-H-$(3)-crates-exec: \
|
|||
|
||||
endif
|
||||
|
||||
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec: \
|
||||
$$(foreach crate,$$(TEST_DOC_CRATES), \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-doc-$$(crate)-exec)
|
||||
|
||||
check-stage$(1)-T-$(2)-H-$(3)-doc-exec: \
|
||||
$$(foreach docname,$$(DOC_TEST_NAMES), \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-doc-$$(docname)-exec)
|
||||
|
@ -734,6 +740,26 @@ $(foreach host,$(CFG_HOST), \
|
|||
$(foreach docname,$(DOC_TEST_NAMES), \
|
||||
$(eval $(call DEF_RUN_DOC_TEST,$(stage),$(target),$(host),$(docname)))))))
|
||||
|
||||
CRATE_DOC_LIB-std = $(STDLIB_CRATE)
|
||||
CRATE_DOC_LIB-extra = $(EXTRALIB_CRATE)
|
||||
|
||||
define DEF_CRATE_DOC_TEST
|
||||
|
||||
check-stage$(1)-T-$(2)-H-$(2)-doc-$(3)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(2),doc-$(3))
|
||||
|
||||
$$(call TEST_OK_FILE,$(1),$(2),$(2),doc-$(3)): \
|
||||
$$(TEST_SREQ$(1)_T_$(2)_H_$(2)) \
|
||||
$$(HBIN$(1)_H_$(2))/rustdoc$$(X_$(2))
|
||||
@$$(call E, run doc-$(3) [$(2)])
|
||||
$$(Q)$$(HBIN$(1)_H_$(2))/rustdoc$$(X_$(2)) --test \
|
||||
$$(CRATE_DOC_LIB-$(3)) && touch $$@
|
||||
|
||||
endef
|
||||
|
||||
$(foreach host,$(CFG_HOST), \
|
||||
$(foreach stage,$(STAGES), \
|
||||
$(foreach crate,$(TEST_DOC_CRATES), \
|
||||
$(eval $(call DEF_CRATE_DOC_TEST,$(stage),$(host),$(crate))))))
|
||||
|
||||
######################################################################
|
||||
# Extracting tests for docs
|
||||
|
@ -762,6 +788,7 @@ $(foreach host,$(CFG_HOST), \
|
|||
TEST_GROUPS = \
|
||||
crates \
|
||||
$(foreach crate,$(TEST_CRATES),$(crate)) \
|
||||
$(foreach crate,$(TEST_DOC_CRATES),doc-$(crate)) \
|
||||
rpass \
|
||||
rpass-full \
|
||||
rfail \
|
||||
|
|
|
@ -18,18 +18,19 @@
|
|||
* With simple pipes, without Arc, a copy would have to be made for each task.
|
||||
*
|
||||
* ```rust
|
||||
* extern mod std;
|
||||
* use extra::arc;
|
||||
* let numbers=vec::from_fn(100, |ind| (ind as float)*rand::random());
|
||||
* let shared_numbers=arc::Arc::new(numbers);
|
||||
* use extra::arc::Arc;
|
||||
* use std::{rand, vec};
|
||||
*
|
||||
* do 10.times {
|
||||
* let (port, chan) = stream();
|
||||
* let numbers = vec::from_fn(100, |i| (i as f32) * rand::random());
|
||||
* let shared_numbers = Arc::new(numbers);
|
||||
*
|
||||
* for _ in range(0, 10) {
|
||||
* let (port, chan) = Chan::new();
|
||||
* chan.send(shared_numbers.clone());
|
||||
*
|
||||
* do spawn {
|
||||
* let shared_numbers=port.recv();
|
||||
* let local_numbers=shared_numbers.get();
|
||||
* let shared_numbers = port.recv();
|
||||
* let local_numbers = shared_numbers.get();
|
||||
*
|
||||
* // Work with the local numbers
|
||||
* }
|
||||
|
@ -448,15 +449,18 @@ impl<T:Freeze + Send> RWArc<T> {
|
|||
* # Example
|
||||
*
|
||||
* ```rust
|
||||
* do arc.write_downgrade |mut write_token| {
|
||||
* do write_token.write_cond |state, condvar| {
|
||||
* ... exclusive access with mutable state ...
|
||||
* }
|
||||
* use extra::arc::RWArc;
|
||||
*
|
||||
* let arc = RWArc::new(1);
|
||||
* arc.write_downgrade(|mut write_token| {
|
||||
* write_token.write_cond(|state, condvar| {
|
||||
* // ... exclusive access with mutable state ...
|
||||
* });
|
||||
* let read_token = arc.downgrade(write_token);
|
||||
* do read_token.read |state| {
|
||||
* ... shared access with immutable state ...
|
||||
* }
|
||||
* }
|
||||
* read_token.read(|state| {
|
||||
* // ... shared access with immutable state ...
|
||||
* });
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
pub fn write_downgrade<U>(&self, blk: |v: RWWriteMode<T>| -> U) -> U {
|
||||
|
|
|
@ -15,9 +15,10 @@
|
|||
* # Example
|
||||
*
|
||||
* ```rust
|
||||
* use extra::future::Future;
|
||||
* # fn fib(n: uint) -> uint {42};
|
||||
* # fn make_a_sandwich() {};
|
||||
* let mut delayed_fib = extra::future::spawn (|| fib(5000) );
|
||||
* let mut delayed_fib = do Future::spawn { fib(5000) };
|
||||
* make_a_sandwich();
|
||||
* println!("fib(5000) = {}", delayed_fib.get())
|
||||
* ```
|
||||
|
|
|
@ -53,8 +53,10 @@ pub struct GlobIterator {
|
|||
/// `puppies.jpg` and `hamsters.gif`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use extra::glob::glob;
|
||||
///
|
||||
/// for path in glob("/media/pictures/*.jpg") {
|
||||
/// println(path.to_str());
|
||||
/// println!("{}", path.display());
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
@ -188,21 +190,23 @@ enum MatchResult {
|
|||
impl Pattern {
|
||||
|
||||
/**
|
||||
* This function compiles Unix shell style patterns: `?` matches any single character,
|
||||
* `*` matches any (possibly empty) sequence of characters and `[...]` matches any character
|
||||
* inside the brackets, unless the first character is `!` in which case it matches any
|
||||
* character except those between the `!` and the `]`. Character sequences can also specify
|
||||
* ranges of characters, as ordered by Unicode, so e.g. `[0-9]` specifies any character
|
||||
* between 0 and 9 inclusive.
|
||||
* This function compiles Unix shell style patterns: `?` matches any single
|
||||
* character, `*` matches any (possibly empty) sequence of characters and
|
||||
* `[...]` matches any character inside the brackets, unless the first
|
||||
* character is `!` in which case it matches any character except those
|
||||
* between the `!` and the `]`. Character sequences can also specify ranges
|
||||
* of characters, as ordered by Unicode, so e.g. `[0-9]` specifies any
|
||||
* character between 0 and 9 inclusive.
|
||||
*
|
||||
* The metacharacters `?`, `*`, `[`, `]` can be matched by using brackets (e.g. `[?]`).
|
||||
* When a `]` occurs immediately following `[` or `[!` then it is interpreted as
|
||||
* being part of, rather then ending, the character set, so `]` and NOT `]` can be
|
||||
* matched by `[]]` and `[!]]` respectively. The `-` character can be specified inside a
|
||||
* character sequence pattern by placing it at the start or the end, e.g. `[abc-]`.
|
||||
* The metacharacters `?`, `*`, `[`, `]` can be matched by using brackets
|
||||
* (e.g. `[?]`). When a `]` occurs immediately following `[` or `[!` then
|
||||
* it is interpreted as being part of, rather then ending, the character
|
||||
* set, so `]` and NOT `]` can be matched by `[]]` and `[!]]` respectively.
|
||||
* The `-` character can be specified inside a character sequence pattern by
|
||||
* placing it at the start or the end, e.g. `[abc-]`.
|
||||
*
|
||||
* When a `[` does not have a closing `]` before the end of the string then the `[` will
|
||||
* be treated literally.
|
||||
* When a `[` does not have a closing `]` before the end of the string then
|
||||
* the `[` will be treated literally.
|
||||
*/
|
||||
pub fn new(pattern: &str) -> Pattern {
|
||||
|
||||
|
@ -229,7 +233,8 @@ impl Pattern {
|
|||
match chars.slice_from(i + 3).position_elem(&']') {
|
||||
None => (),
|
||||
Some(j) => {
|
||||
let cs = parse_char_specifiers(chars.slice(i + 2, i + 3 + j));
|
||||
let chars = chars.slice(i + 2, i + 3 + j);
|
||||
let cs = parse_char_specifiers(chars);
|
||||
tokens.push(AnyExcept(cs));
|
||||
i += j + 4;
|
||||
continue;
|
||||
|
@ -292,6 +297,8 @@ impl Pattern {
|
|||
* # Example
|
||||
*
|
||||
* ```rust
|
||||
* use extra::glob::Pattern;
|
||||
*
|
||||
* assert!(Pattern::new("c?t").matches("cat"));
|
||||
* assert!(Pattern::new("k[!e]tteh").matches("kitteh"));
|
||||
* assert!(Pattern::new("d*g").matches("doog"));
|
||||
|
@ -509,7 +516,7 @@ impl MatchOptions {
|
|||
*
|
||||
* This function always returns this value:
|
||||
*
|
||||
* ```rust
|
||||
* ```rust,ignore
|
||||
* MatchOptions {
|
||||
* case_sensitive: true,
|
||||
* require_literal_separator: false.
|
||||
|
|
|
@ -28,7 +28,6 @@ impl<'a> ToHex for &'a [u8] {
|
|||
* # Example
|
||||
*
|
||||
* ```rust
|
||||
* extern mod extra;
|
||||
* use extra::hex::ToHex;
|
||||
*
|
||||
* fn main () {
|
||||
|
@ -71,12 +70,11 @@ impl<'a> FromHex for &'a str {
|
|||
* This converts a string literal to hexadecimal and back.
|
||||
*
|
||||
* ```rust
|
||||
* extern mod extra;
|
||||
* use extra::hex::{FromHex, ToHex};
|
||||
* use std::str;
|
||||
*
|
||||
* fn main () {
|
||||
* let hello_str = "Hello, World".to_hex();
|
||||
* let hello_str = "Hello, World".as_bytes().to_hex();
|
||||
* println!("{}", hello_str);
|
||||
* let bytes = hello_str.from_hex().unwrap();
|
||||
* println!("{:?}", bytes);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! use extra::lru_cache::LruCache;
|
||||
//!
|
||||
//! let mut cache: LruCache<int, int> = LruCache::new(2);
|
||||
//! cache.put(1, 10);
|
||||
//! cache.put(2, 20);
|
||||
|
|
|
@ -568,13 +568,16 @@ impl RWLock {
|
|||
* # Example
|
||||
*
|
||||
* ```rust
|
||||
* use extra::sync::RWLock;
|
||||
*
|
||||
* let lock = RWLock::new();
|
||||
* lock.write_downgrade(|mut write_token| {
|
||||
* write_token.write_cond(|condvar| {
|
||||
* ... exclusive access ...
|
||||
* // ... exclusive access ...
|
||||
* });
|
||||
* let read_token = lock.downgrade(write_token);
|
||||
* read_token.read(|| {
|
||||
* ... shared access ...
|
||||
* // ... shared access ...
|
||||
* })
|
||||
* })
|
||||
* ```
|
||||
|
|
|
@ -26,6 +26,8 @@ use std::uint;
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use extra::url::{Url, UserInfo};
|
||||
///
|
||||
/// let url = Url { scheme: ~"https",
|
||||
/// user: Some(UserInfo { user: ~"username", pass: None }),
|
||||
/// host: ~"example.com",
|
||||
|
@ -388,8 +390,10 @@ fn query_from_str(rawquery: &str) -> Query {
|
|||
* # Example
|
||||
*
|
||||
* ```rust
|
||||
* use extra::url;
|
||||
*
|
||||
* let query = ~[(~"title", ~"The Village"), (~"north", ~"52.91"), (~"west", ~"4.10")];
|
||||
* println(query_to_str(&query)); // title=The%20Village&north=52.91&west=4.10
|
||||
* println(url::query_to_str(&query)); // title=The%20Village&north=52.91&west=4.10
|
||||
* ```
|
||||
*/
|
||||
pub fn query_to_str(query: &Query) -> ~str {
|
||||
|
|
|
@ -1147,13 +1147,17 @@ fn name_from_pat(p: &ast::Pat) -> ~str {
|
|||
fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>,
|
||||
id: ast::NodeId) -> Type {
|
||||
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
|
||||
let tycx = match cx.tycx {
|
||||
Some(tycx) => tycx,
|
||||
// If we're extracting tests, this return value doesn't matter.
|
||||
None => return Bool
|
||||
};
|
||||
debug!("searching for {:?} in defmap", id);
|
||||
let d = match cx.tycx.def_map.find(&id) {
|
||||
let d = match tycx.def_map.find(&id) {
|
||||
Some(k) => k,
|
||||
None => {
|
||||
let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap());
|
||||
debug!("could not find {:?} in defmap (`{}`)", id,
|
||||
syntax::ast_map::node_id_to_str(ctxt.tycx.items, id, ctxt.sess.intr()));
|
||||
syntax::ast_map::node_id_to_str(tycx.items, id, cx.sess.intr()));
|
||||
fail!("Unexpected failure: unresolved id not in defmap (this is a bug!)")
|
||||
}
|
||||
};
|
||||
|
@ -1182,7 +1186,7 @@ fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>,
|
|||
if ast_util::is_local(def_id) {
|
||||
ResolvedPath{ path: path, typarams: tpbs, id: def_id.node }
|
||||
} else {
|
||||
let fqn = csearch::get_item_path(cx.tycx, def_id);
|
||||
let fqn = csearch::get_item_path(tycx, def_id);
|
||||
let fqn = fqn.move_iter().map(|i| {
|
||||
match i {
|
||||
ast_map::path_mod(id) |
|
||||
|
@ -1203,6 +1207,11 @@ fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
|
|||
}
|
||||
|
||||
fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> {
|
||||
let dm = local_data::get(super::ctxtkey, |x| *x.unwrap()).tycx.def_map;
|
||||
dm.find(&id).map(|&d| ast_util::def_id_of_def(d))
|
||||
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
|
||||
match cx.tycx {
|
||||
Some(tcx) => {
|
||||
tcx.def_map.find(&id).map(|&d| ast_util::def_id_of_def(d))
|
||||
}
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ use clean::Clean;
|
|||
|
||||
pub struct DocContext {
|
||||
crate: ast::Crate,
|
||||
tycx: middle::ty::ctxt,
|
||||
tycx: Option<middle::ty::ctxt>,
|
||||
sess: driver::session::Session
|
||||
}
|
||||
|
||||
|
@ -78,17 +78,13 @@ fn get_ast_and_resolve(cpath: &Path,
|
|||
} = phase_3_run_analysis_passes(sess, &crate);
|
||||
|
||||
debug!("crate: {:?}", crate);
|
||||
return (DocContext { crate: crate, tycx: ty_cx, sess: sess },
|
||||
return (DocContext { crate: crate, tycx: Some(ty_cx), sess: sess },
|
||||
CrateAnalysis { exported_items: exported_items });
|
||||
}
|
||||
|
||||
pub fn run_core (libs: HashSet<Path>, cfgs: ~[~str], path: &Path) -> (clean::Crate, CrateAnalysis) {
|
||||
let (ctxt, analysis) = get_ast_and_resolve(path, libs, cfgs);
|
||||
let ctxt = @ctxt;
|
||||
debug!("defmap:");
|
||||
for (k, v) in ctxt.tycx.def_map.iter() {
|
||||
debug!("{:?}: {:?}", k, v);
|
||||
}
|
||||
local_data::set(super::ctxtkey, ctxt);
|
||||
|
||||
let v = @mut RustdocVisitor::new();
|
||||
|
|
|
@ -22,9 +22,12 @@
|
|||
//! // ... something using html
|
||||
//! ```
|
||||
|
||||
use std::cast;
|
||||
use std::fmt;
|
||||
use std::libc;
|
||||
use std::io;
|
||||
use std::libc;
|
||||
use std::str;
|
||||
use std::unstable::intrinsics;
|
||||
use std::vec;
|
||||
|
||||
/// A unit struct which has the `fmt::Default` trait implemented. When
|
||||
|
@ -41,8 +44,10 @@ static MKDEXT_STRIKETHROUGH: libc::c_uint = 1 << 4;
|
|||
|
||||
type sd_markdown = libc::c_void; // this is opaque to us
|
||||
|
||||
// this is a large struct of callbacks we don't use
|
||||
type sd_callbacks = [libc::size_t, ..26];
|
||||
struct sd_callbacks {
|
||||
blockcode: extern "C" fn(*buf, *buf, *buf, *libc::c_void),
|
||||
other: [libc::size_t, ..25],
|
||||
}
|
||||
|
||||
struct html_toc_data {
|
||||
header_count: libc::c_int,
|
||||
|
@ -56,6 +61,11 @@ struct html_renderopt {
|
|||
link_attributes: Option<extern "C" fn(*buf, *buf, *libc::c_void)>,
|
||||
}
|
||||
|
||||
struct my_opaque {
|
||||
opt: html_renderopt,
|
||||
dfltblk: extern "C" fn(*buf, *buf, *buf, *libc::c_void),
|
||||
}
|
||||
|
||||
struct buf {
|
||||
data: *u8,
|
||||
size: libc::size_t,
|
||||
|
@ -84,7 +94,28 @@ extern {
|
|||
|
||||
}
|
||||
|
||||
fn render(w: &mut io::Writer, s: &str) {
|
||||
pub fn render(w: &mut io::Writer, s: &str) {
|
||||
extern fn block(ob: *buf, text: *buf, lang: *buf, opaque: *libc::c_void) {
|
||||
unsafe {
|
||||
let my_opaque: &my_opaque = cast::transmute(opaque);
|
||||
vec::raw::buf_as_slice((*text).data, (*text).size as uint, |text| {
|
||||
let text = str::from_utf8(text);
|
||||
let mut lines = text.lines().filter(|l| {
|
||||
!l.trim().starts_with("#")
|
||||
});
|
||||
let text = lines.to_owned_vec().connect("\n");
|
||||
|
||||
let buf = buf {
|
||||
data: text.as_bytes().as_ptr(),
|
||||
size: text.len() as libc::size_t,
|
||||
asize: text.len() as libc::size_t,
|
||||
unit: 0,
|
||||
};
|
||||
(my_opaque.dfltblk)(ob, &buf, lang, opaque);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// This code is all lifted from examples/sundown.c in the sundown repo
|
||||
unsafe {
|
||||
let ob = bufnew(OUTPUT_UNIT);
|
||||
|
@ -100,11 +131,16 @@ fn render(w: &mut io::Writer, s: &str) {
|
|||
flags: 0,
|
||||
link_attributes: None,
|
||||
};
|
||||
let callbacks: sd_callbacks = [0, ..26];
|
||||
let mut callbacks: sd_callbacks = intrinsics::init();
|
||||
|
||||
sdhtml_renderer(&callbacks, &options, 0);
|
||||
let opaque = my_opaque {
|
||||
opt: options,
|
||||
dfltblk: callbacks.blockcode,
|
||||
};
|
||||
callbacks.blockcode = block;
|
||||
let markdown = sd_markdown_new(extensions, 16, &callbacks,
|
||||
&options as *html_renderopt as *libc::c_void);
|
||||
&opaque as *my_opaque as *libc::c_void);
|
||||
|
||||
|
||||
sd_markdown_render(ob, s.as_ptr(), s.len() as libc::size_t, markdown);
|
||||
|
@ -118,6 +154,48 @@ fn render(w: &mut io::Writer, s: &str) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) {
|
||||
extern fn block(_ob: *buf, text: *buf, lang: *buf, opaque: *libc::c_void) {
|
||||
unsafe {
|
||||
if text.is_null() || lang.is_null() { return }
|
||||
let (test, shouldfail, ignore) =
|
||||
vec::raw::buf_as_slice((*lang).data,
|
||||
(*lang).size as uint, |lang| {
|
||||
let s = str::from_utf8(lang);
|
||||
(s.contains("rust"), s.contains("should_fail"),
|
||||
s.contains("ignore"))
|
||||
});
|
||||
if !test { return }
|
||||
vec::raw::buf_as_slice((*text).data, (*text).size as uint, |text| {
|
||||
let tests: &mut ::test::Collector = intrinsics::transmute(opaque);
|
||||
let text = str::from_utf8(text);
|
||||
let mut lines = text.lines().map(|l| l.trim_chars(&'#'));
|
||||
let text = lines.to_owned_vec().connect("\n");
|
||||
tests.add_test(text, ignore, shouldfail);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let ob = bufnew(OUTPUT_UNIT);
|
||||
let extensions = MKDEXT_NO_INTRA_EMPHASIS | MKDEXT_TABLES |
|
||||
MKDEXT_FENCED_CODE | MKDEXT_AUTOLINK |
|
||||
MKDEXT_STRIKETHROUGH;
|
||||
let callbacks = sd_callbacks {
|
||||
blockcode: block,
|
||||
other: intrinsics::init()
|
||||
};
|
||||
|
||||
let tests = tests as *mut ::test::Collector as *libc::c_void;
|
||||
let markdown = sd_markdown_new(extensions, 16, &callbacks, tests);
|
||||
|
||||
sd_markdown_render(ob, doc.as_ptr(), doc.len() as libc::size_t,
|
||||
markdown);
|
||||
sd_markdown_free(markdown);
|
||||
bufrelease(ob);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Default for Markdown<'a> {
|
||||
fn fmt(md: &Markdown<'a>, fmt: &mut fmt::Formatter) {
|
||||
// This is actually common enough to special-case
|
||||
|
|
|
@ -47,6 +47,7 @@ pub mod html {
|
|||
pub mod passes;
|
||||
pub mod plugins;
|
||||
pub mod visit_ast;
|
||||
pub mod test;
|
||||
|
||||
pub static SCHEMA_VERSION: &'static str = "0.8.1";
|
||||
|
||||
|
@ -100,6 +101,9 @@ pub fn opts() -> ~[groups::OptGroup] {
|
|||
optmulti("", "plugins", "space separated list of plugins to also load",
|
||||
"PLUGINS"),
|
||||
optflag("", "no-defaults", "don't run the default passes"),
|
||||
optflag("", "test", "run code examples as tests"),
|
||||
optmulti("", "test-args", "arguments to pass to the test runner",
|
||||
"ARGS"),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -114,6 +118,19 @@ pub fn main_args(args: &[~str]) -> int {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if matches.free.len() == 0 {
|
||||
println("expected an input file to act on");
|
||||
return 1;
|
||||
} if matches.free.len() > 1 {
|
||||
println("only one input file may be specified");
|
||||
return 1;
|
||||
}
|
||||
let input = matches.free[0].as_slice();
|
||||
|
||||
if matches.opt_present("test") {
|
||||
return test::run(input, &matches);
|
||||
}
|
||||
|
||||
if matches.opt_strs("passes") == ~[~"list"] {
|
||||
println("Available passes for running rustdoc:");
|
||||
for &(name, _, description) in PASSES.iter() {
|
||||
|
@ -126,7 +143,7 @@ pub fn main_args(args: &[~str]) -> int {
|
|||
return 0;
|
||||
}
|
||||
|
||||
let (crate, res) = match acquire_input(&matches) {
|
||||
let (crate, res) = match acquire_input(input, &matches) {
|
||||
Ok(pair) => pair,
|
||||
Err(s) => {
|
||||
println!("input error: {}", s);
|
||||
|
@ -157,14 +174,8 @@ pub fn main_args(args: &[~str]) -> int {
|
|||
|
||||
/// Looks inside the command line arguments to extract the relevant input format
|
||||
/// and files and then generates the necessary rustdoc output for formatting.
|
||||
fn acquire_input(matches: &getopts::Matches) -> Result<Output, ~str> {
|
||||
if matches.free.len() == 0 {
|
||||
return Err(~"expected an input file to act on");
|
||||
} if matches.free.len() > 1 {
|
||||
return Err(~"only one input file may be specified");
|
||||
}
|
||||
|
||||
let input = matches.free[0].as_slice();
|
||||
fn acquire_input(input: &str,
|
||||
matches: &getopts::Matches) -> Result<Output, ~str> {
|
||||
match matches.opt_str("r") {
|
||||
Some(~"rust") => Ok(rust_input(input, matches)),
|
||||
Some(~"json") => json_input(input),
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.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.
|
||||
|
||||
use std::hashmap::HashSet;
|
||||
use std::local_data;
|
||||
use std::os;
|
||||
use std::run;
|
||||
use std::str;
|
||||
|
||||
use extra::tempfile::TempDir;
|
||||
use extra::getopts;
|
||||
use extra::test;
|
||||
use rustc::driver::driver;
|
||||
use rustc::driver::session;
|
||||
use syntax::diagnostic;
|
||||
use syntax::parse;
|
||||
|
||||
use core;
|
||||
use clean;
|
||||
use clean::Clean;
|
||||
use fold::DocFolder;
|
||||
use html::markdown;
|
||||
use passes;
|
||||
use visit_ast::RustdocVisitor;
|
||||
|
||||
pub fn run(input: &str, matches: &getopts::Matches) -> int {
|
||||
let parsesess = parse::new_parse_sess(None);
|
||||
let input = driver::file_input(Path::new(input));
|
||||
let libs = matches.opt_strs("L").map(|s| Path::new(s.as_slice()));
|
||||
let libs = @mut libs.move_iter().collect();
|
||||
|
||||
let sessopts = @session::options {
|
||||
binary: @"rustdoc",
|
||||
maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
|
||||
addl_lib_search_paths: libs,
|
||||
outputs: ~[session::OutputDylib],
|
||||
.. (*session::basic_options()).clone()
|
||||
};
|
||||
|
||||
|
||||
let diagnostic_handler = diagnostic::mk_handler(None);
|
||||
let span_diagnostic_handler =
|
||||
diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);
|
||||
|
||||
let sess = driver::build_session_(sessopts,
|
||||
parsesess.cm,
|
||||
@diagnostic::DefaultEmitter as
|
||||
@diagnostic::Emitter,
|
||||
span_diagnostic_handler);
|
||||
|
||||
let cfg = driver::build_configuration(sess);
|
||||
let mut crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
|
||||
crate = driver::phase_2_configure_and_expand(sess, cfg, crate);
|
||||
|
||||
let ctx = @core::DocContext {
|
||||
crate: crate,
|
||||
tycx: None,
|
||||
sess: sess,
|
||||
};
|
||||
local_data::set(super::ctxtkey, ctx);
|
||||
|
||||
let v = @mut RustdocVisitor::new();
|
||||
v.visit(&ctx.crate);
|
||||
let crate = v.clean();
|
||||
let (crate, _) = passes::unindent_comments(crate);
|
||||
let (crate, _) = passes::collapse_docs(crate);
|
||||
|
||||
let mut collector = Collector {
|
||||
tests: ~[],
|
||||
names: ~[],
|
||||
cnt: 0,
|
||||
libs: libs,
|
||||
cratename: crate.name.to_owned(),
|
||||
};
|
||||
collector.fold_crate(crate);
|
||||
|
||||
let args = matches.opt_strs("test-args");
|
||||
let mut args = args.iter().flat_map(|s| s.words()).map(|s| s.to_owned());
|
||||
let mut args = args.to_owned_vec();
|
||||
args.unshift(~"rustdoctest");
|
||||
|
||||
test::test_main(args, collector.tests);
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
fn runtest(test: &str, cratename: &str, libs: HashSet<Path>) {
|
||||
let test = maketest(test, cratename);
|
||||
let parsesess = parse::new_parse_sess(None);
|
||||
let input = driver::str_input(test);
|
||||
|
||||
let sessopts = @session::options {
|
||||
binary: @"rustdoctest",
|
||||
maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
|
||||
addl_lib_search_paths: @mut libs,
|
||||
outputs: ~[session::OutputExecutable],
|
||||
debugging_opts: session::prefer_dynamic,
|
||||
.. (*session::basic_options()).clone()
|
||||
};
|
||||
|
||||
let diagnostic_handler = diagnostic::mk_handler(None);
|
||||
let span_diagnostic_handler =
|
||||
diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);
|
||||
|
||||
let sess = driver::build_session_(sessopts,
|
||||
parsesess.cm,
|
||||
@diagnostic::DefaultEmitter as
|
||||
@diagnostic::Emitter,
|
||||
span_diagnostic_handler);
|
||||
|
||||
let outdir = TempDir::new("rustdoctest").expect("rustdoc needs a tempdir");
|
||||
let out = Some(outdir.path().clone());
|
||||
let cfg = driver::build_configuration(sess);
|
||||
driver::compile_input(sess, cfg, &input, &out, &None);
|
||||
|
||||
let exe = outdir.path().join("rust_out");
|
||||
let out = run::process_output(exe.as_str().unwrap(), []);
|
||||
match out {
|
||||
None => fail!("couldn't run the test"),
|
||||
Some(out) => {
|
||||
if !out.status.success() {
|
||||
fail!("test executable failed:\n{}",
|
||||
str::from_utf8(out.error));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn maketest(s: &str, cratename: &str) -> @str {
|
||||
let mut prog = ~r"
|
||||
#[deny(warnings)];
|
||||
#[allow(unused_variable, dead_assignment, unused_mut, attribute_usage, dead_code)];
|
||||
#[feature(macro_rules, globs, struct_variant, managed_boxes)];
|
||||
";
|
||||
if s.contains("extra") {
|
||||
prog.push_str("extern mod extra;\n");
|
||||
}
|
||||
if s.contains(cratename) {
|
||||
prog.push_str(format!("extern mod {};\n", cratename));
|
||||
}
|
||||
if s.contains("fn main") {
|
||||
prog.push_str(s);
|
||||
} else {
|
||||
prog.push_str("fn main() {\n");
|
||||
prog.push_str(s);
|
||||
prog.push_str("\n}");
|
||||
}
|
||||
|
||||
return prog.to_managed();
|
||||
}
|
||||
|
||||
pub struct Collector {
|
||||
priv tests: ~[test::TestDescAndFn],
|
||||
priv names: ~[~str],
|
||||
priv libs: @mut HashSet<Path>,
|
||||
priv cnt: uint,
|
||||
priv cratename: ~str,
|
||||
}
|
||||
|
||||
impl Collector {
|
||||
pub fn add_test(&mut self, test: &str, ignore: bool, should_fail: bool) {
|
||||
let test = test.to_owned();
|
||||
let name = format!("{}_{}", self.names.connect("::"), self.cnt);
|
||||
self.cnt += 1;
|
||||
let libs = (*self.libs).clone();
|
||||
let cratename = self.cratename.to_owned();
|
||||
self.tests.push(test::TestDescAndFn {
|
||||
desc: test::TestDesc {
|
||||
name: test::DynTestName(name),
|
||||
ignore: ignore,
|
||||
should_fail: should_fail,
|
||||
},
|
||||
testfn: test::DynTestFn(proc() {
|
||||
runtest(test, cratename, libs);
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl DocFolder for Collector {
|
||||
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
|
||||
let pushed = match item.name {
|
||||
Some(ref name) if name.len() == 0 => false,
|
||||
Some(ref name) => { self.names.push(name.to_owned()); true }
|
||||
None => false
|
||||
};
|
||||
match item.doc_value() {
|
||||
Some(doc) => {
|
||||
self.cnt = 0;
|
||||
markdown::find_testable_code(doc, self);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
let ret = self.fold_item_recur(item);
|
||||
if pushed {
|
||||
self.names.pop();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -12,11 +12,10 @@
|
|||
//! usable for clean
|
||||
|
||||
use syntax::abi::AbiSet;
|
||||
use syntax::{ast, ast_map};
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use doctree::*;
|
||||
use std::local_data;
|
||||
|
||||
pub struct RustdocVisitor {
|
||||
module: Module,
|
||||
|
@ -91,15 +90,8 @@ impl RustdocVisitor {
|
|||
}
|
||||
|
||||
fn visit_mod_contents(span: Span, attrs: ~[ast::Attribute], vis:
|
||||
ast::visibility, id: ast::NodeId, m: &ast::_mod) -> Module {
|
||||
let am = local_data::get(super::ctxtkey, |x| *x.unwrap()).tycx.items;
|
||||
let name = match am.find(&id) {
|
||||
Some(m) => match m {
|
||||
&ast_map::node_item(ref it, _) => Some(it.ident),
|
||||
_ => fail!("mod id mapped to non-item in the ast map")
|
||||
},
|
||||
None => None
|
||||
};
|
||||
ast::visibility, id: ast::NodeId, m: &ast::_mod,
|
||||
name: Option<ast::Ident>) -> Module {
|
||||
let mut om = Module::new(name);
|
||||
om.view_items = m.view_items.clone();
|
||||
om.where = span;
|
||||
|
@ -117,7 +109,8 @@ impl RustdocVisitor {
|
|||
match item.node {
|
||||
ast::item_mod(ref m) => {
|
||||
om.mods.push(visit_mod_contents(item.span, item.attrs.clone(),
|
||||
item.vis, item.id, m));
|
||||
item.vis, item.id, m,
|
||||
Some(item.ident)));
|
||||
},
|
||||
ast::item_enum(ref ed, ref gen) => om.enums.push(visit_enum_def(item, ed, gen)),
|
||||
ast::item_struct(sd, ref gen) => om.structs.push(visit_struct_def(item, sd, gen)),
|
||||
|
@ -182,6 +175,7 @@ impl RustdocVisitor {
|
|||
}
|
||||
|
||||
self.module = visit_mod_contents(crate.span, crate.attrs.clone(),
|
||||
ast::public, ast::CRATE_NODE_ID, &crate.module);
|
||||
ast::public, ast::CRATE_NODE_ID,
|
||||
&crate.module, None);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,13 +51,13 @@ let my_string = "Hello, world!";
|
|||
let my_c_string = my_string.to_c_str();
|
||||
my_c_string.with_ref(|c_buffer| {
|
||||
unsafe { puts(c_buffer); }
|
||||
})
|
||||
});
|
||||
|
||||
// Don't save off the allocation of the C string, the `c_buffer` will be
|
||||
// deallocated when this block returns!
|
||||
my_string.with_c_str(|c_buffer| {
|
||||
unsafe { puts(c_buffer); }
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
*/
|
||||
|
@ -216,7 +216,11 @@ pub trait ToCStr {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let s = "PATH".with_c_str(|path| libc::getenv(path))
|
||||
/// use std::libc;
|
||||
///
|
||||
/// let s = "PATH".with_c_str(|path| unsafe {
|
||||
/// libc::getenv(path)
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// # Failure
|
||||
|
|
|
@ -49,7 +49,9 @@ pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }
|
|||
* # Example
|
||||
*
|
||||
* ```rust
|
||||
* let v: &[u8] = transmute("L");
|
||||
* use std::cast;
|
||||
*
|
||||
* let v: &[u8] = unsafe { cast::transmute("L") };
|
||||
* assert!(v == [76u8]);
|
||||
* ```
|
||||
*/
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! ```rust,should_fail
|
||||
//! // Create a simple streaming channel
|
||||
//! let (port, chan) = Chan::new();
|
||||
//! do spawn {
|
||||
|
@ -81,7 +81,7 @@
|
|||
//!
|
||||
//! // The call to recv() will fail!() because the channel has already hung
|
||||
//! // up (or been deallocated)
|
||||
//! let (port, chan) = Chan::new();
|
||||
//! let (port, chan) = Chan::<int>::new();
|
||||
//! drop(chan);
|
||||
//! port.recv();
|
||||
//! ```
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! ```rust,ignore
|
||||
//! let (mut p1, c1) = Chan::new();
|
||||
//! let (mut p2, c2) = Chan::new();
|
||||
//!
|
||||
|
@ -40,6 +40,7 @@
|
|||
//! assert_eq!(val, 2);
|
||||
//! }
|
||||
//! )
|
||||
//! ```
|
||||
|
||||
#[allow(dead_code)];
|
||||
|
||||
|
|
|
@ -23,13 +23,17 @@ A condition is declared through the `condition!` macro provided by the compiler:
|
|||
condition! {
|
||||
pub my_error: int -> ~str;
|
||||
}
|
||||
```
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
This macro declares an inner module called `my_error` with one static variable,
|
||||
`cond` that is a static `Condition` instance. To help understand what the other
|
||||
parameters are used for, an example usage of this condition would be:
|
||||
|
||||
```rust
|
||||
# condition! { pub my_error: int -> ~str; }
|
||||
# fn main() {
|
||||
|
||||
my_error::cond.trap(|raised_int| {
|
||||
|
||||
// the condition `my_error` was raised on, and the value it raised is stored
|
||||
|
@ -51,6 +55,8 @@ my_error::cond.trap(|raised_int| {
|
|||
println(my_error::cond.raise(4)); // prints "oh well"
|
||||
|
||||
})
|
||||
|
||||
# }
|
||||
```
|
||||
|
||||
Condition handling is useful in cases where propagating errors is either to
|
||||
|
@ -99,10 +105,12 @@ impl<T, U> Condition<T, U> {
|
|||
/// ```rust
|
||||
/// condition! { my_error: int -> int; }
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let trap = my_error::cond.trap(|error| error + 3);
|
||||
///
|
||||
/// // use `trap`'s inside method to register the handler and then run a
|
||||
/// // block of code with the handler registered
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn trap<'a>(&'a self, h: 'a |T| -> U) -> Trap<'a, T, U> {
|
||||
let h: Closure = unsafe { ::cast::transmute(h) };
|
||||
|
@ -176,10 +184,12 @@ impl<'a, T, U> Trap<'a, T, U> {
|
|||
/// ```rust
|
||||
/// condition! { my_error: int -> int; }
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let result = my_error::cond.trap(|error| error + 3).inside(|| {
|
||||
/// my_error::cond.raise(4)
|
||||
/// });
|
||||
/// assert_eq!(result, 7);
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn inside<V>(&self, inner: 'a || -> V) -> V {
|
||||
let _g = Guard { cond: self.cond };
|
||||
|
|
|
@ -34,12 +34,12 @@ arguments directly while performing minimal allocations.
|
|||
Some examples of the `format!` extension are:
|
||||
|
||||
```rust
|
||||
format!("Hello") // => ~"Hello"
|
||||
format!("Hello, {:s}!", "world") // => ~"Hello, world!"
|
||||
format!("The number is {:d}", 1) // => ~"The number is 1"
|
||||
format!("{:?}", ~[3, 4]) // => ~"~[3, 4]"
|
||||
format!("{value}", value=4) // => ~"4"
|
||||
format!("{} {}", 1, 2) // => ~"1 2"
|
||||
format!("Hello"); // => ~"Hello"
|
||||
format!("Hello, {:s}!", "world"); // => ~"Hello, world!"
|
||||
format!("The number is {:d}", 1); // => ~"The number is 1"
|
||||
format!("{:?}", ~[3, 4]); // => ~"~[3, 4]"
|
||||
format!("{value}", value=4); // => ~"4"
|
||||
format!("{} {}", 1, 2); // => ~"1 2"
|
||||
```
|
||||
|
||||
From these, you can see that the first argument is a format string. It is
|
||||
|
@ -62,7 +62,7 @@ iterator over the argument. Each time a "next argument" specifier is seen, the
|
|||
iterator advances. This leads to behavior like this:
|
||||
|
||||
```rust
|
||||
format!("{1} {} {0} {}", 1, 2) // => ~"2 1 1 2"
|
||||
format!("{1} {} {0} {}", 1, 2); // => ~"2 1 1 2"
|
||||
```
|
||||
|
||||
The internal iterator over the argument has not been advanced by the time the
|
||||
|
@ -89,9 +89,9 @@ identifier '=' expression
|
|||
For example, the following `format!` expressions all use named argument:
|
||||
|
||||
```rust
|
||||
format!("{argument}", argument = "test") // => ~"test"
|
||||
format!("{name} {}", 1, name = 2) // => ~"2 1"
|
||||
format!("{a:s} {c:d} {b:?}", a="a", b=(), c=3) // => ~"a 3 ()"
|
||||
format!("{argument}", argument = "test"); // => ~"test"
|
||||
format!("{name} {}", 1, name = 2); // => ~"2 1"
|
||||
format!("{a:s} {c:d} {b:?}", a="a", b=(), c=3); // => ~"a 3 ()"
|
||||
```
|
||||
|
||||
It is illegal to put positional parameters (those without names) after arguments
|
||||
|
@ -160,7 +160,11 @@ When implementing a format trait for your own time, you will have to implement a
|
|||
method of the signature:
|
||||
|
||||
```rust
|
||||
# use std;
|
||||
# struct T;
|
||||
# trait SomeName<T> {
|
||||
fn fmt(value: &T, f: &mut std::fmt::Formatter);
|
||||
# }
|
||||
```
|
||||
|
||||
Your type will be passed by-reference in `value`, and then the function should
|
||||
|
@ -218,7 +222,7 @@ fn main() {
|
|||
There are a number of related macros in the `format!` family. The ones that are
|
||||
currently implemented are:
|
||||
|
||||
```rust
|
||||
```rust,ignore
|
||||
format! // described above
|
||||
write! // first argument is a &mut io::Writer, the destination
|
||||
writeln! // same as write but appends a newline
|
||||
|
@ -261,9 +265,13 @@ references information on the stack. Under the hood, all of
|
|||
the related macros are implemented in terms of this. First
|
||||
off, some example usage is:
|
||||
|
||||
```rust
|
||||
```rust,ignore
|
||||
use std::fmt;
|
||||
|
||||
# fn lol<T>() -> T { fail!() }
|
||||
# let my_writer: &mut ::std::io::Writer = lol();
|
||||
# let my_fn: fn(&fmt::Arguments) = lol();
|
||||
|
||||
format_args!(fmt::format, "this returns {}", "~str");
|
||||
format_args!(|args| { fmt::write(my_writer, args) }, "some {}", "args");
|
||||
format_args!(my_fn, "format {}", "string");
|
||||
|
@ -305,7 +313,7 @@ to reference the string value of the argument which was selected upon. As an
|
|||
example:
|
||||
|
||||
```rust
|
||||
format!("{0, select, other{#}}", "hello") // => ~"hello"
|
||||
format!("{0, select, other{#}}", "hello"); // => ~"hello"
|
||||
```
|
||||
|
||||
This example is the equivalent of `{0:s}` essentially.
|
||||
|
@ -585,7 +593,9 @@ pub trait Float { fn fmt(&Self, &mut Formatter); }
|
|||
///
|
||||
/// ```rust
|
||||
/// use std::fmt;
|
||||
/// let w: &mut io::Writer = ...;
|
||||
/// use std::io;
|
||||
///
|
||||
/// let w = &mut io::stdout() as &mut io::Writer;
|
||||
/// format_args!(|args| { fmt::write(w, args) }, "Hello, {}!", "world");
|
||||
/// ```
|
||||
pub fn write(output: &mut io::Writer, args: &Arguments) {
|
||||
|
@ -650,8 +660,9 @@ pub unsafe fn write_unsafe(output: &mut io::Writer,
|
|||
///
|
||||
/// ```rust
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// let s = format_args!(fmt::format, "Hello, {}!", "world");
|
||||
/// assert_eq!(s, "Hello, world!");
|
||||
/// assert_eq!(s, ~"Hello, world!");
|
||||
/// ```
|
||||
pub fn format(args: &Arguments) -> ~str {
|
||||
unsafe { format_unsafe(args.fmt, args.args) }
|
||||
|
|
|
@ -26,6 +26,10 @@ Some examples of obvious things you might want to do
|
|||
* Read lines from stdin
|
||||
|
||||
```rust
|
||||
use std::io::buffered::BufferedReader;
|
||||
use std::io::stdin;
|
||||
|
||||
# let _g = ::std::io::ignore_io_error();
|
||||
let mut stdin = BufferedReader::new(stdin());
|
||||
for line in stdin.lines() {
|
||||
print(line);
|
||||
|
@ -35,12 +39,18 @@ Some examples of obvious things you might want to do
|
|||
* Read a complete file
|
||||
|
||||
```rust
|
||||
use std::io::File;
|
||||
|
||||
# let _g = ::std::io::ignore_io_error();
|
||||
let contents = File::open(&Path::new("message.txt")).read_to_end();
|
||||
```
|
||||
|
||||
* Write a line to a file
|
||||
|
||||
```rust
|
||||
use std::io::File;
|
||||
|
||||
# let _g = ::std::io::ignore_io_error();
|
||||
let mut file = File::create(&Path::new("message.txt"));
|
||||
file.write(bytes!("hello, file!\n"));
|
||||
```
|
||||
|
@ -48,6 +58,10 @@ Some examples of obvious things you might want to do
|
|||
* Iterate over the lines of a file
|
||||
|
||||
```rust
|
||||
use std::io::buffered::BufferedReader;
|
||||
use std::io::File;
|
||||
|
||||
# let _g = ::std::io::ignore_io_error();
|
||||
let path = Path::new("message.txt");
|
||||
let mut file = BufferedReader::new(File::open(&path));
|
||||
for line in file.lines() {
|
||||
|
@ -58,6 +72,10 @@ Some examples of obvious things you might want to do
|
|||
* Pull the lines of a file into a vector of strings
|
||||
|
||||
```rust
|
||||
use std::io::buffered::BufferedReader;
|
||||
use std::io::File;
|
||||
|
||||
# let _g = ::std::io::ignore_io_error();
|
||||
let path = Path::new("message.txt");
|
||||
let mut file = BufferedReader::new(File::open(&path));
|
||||
let lines: ~[~str] = file.lines().collect();
|
||||
|
@ -67,7 +85,11 @@ Some examples of obvious things you might want to do
|
|||
XXX This needs more improvement: TcpStream constructor taking &str,
|
||||
`write_str` and `write_line` methods.
|
||||
|
||||
```rust
|
||||
```rust,should_fail
|
||||
use std::io::net::ip::SocketAddr;
|
||||
use std::io::net::tcp::TcpStream;
|
||||
|
||||
# let _g = ::std::io::ignore_io_error();
|
||||
let addr = from_str::<SocketAddr>("127.0.0.1:8080").unwrap();
|
||||
let mut socket = TcpStream::connect(addr).unwrap();
|
||||
socket.write(bytes!("GET / HTTP/1.0\n\n"));
|
||||
|
|
|
@ -60,11 +60,11 @@ pub enum Signum {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// ```rust,ignore
|
||||
/// use std::io::signal::{Listener, Interrupt};
|
||||
///
|
||||
/// let mut listener = Listener::new();
|
||||
/// listener.register(signal::Interrupt);
|
||||
/// listener.register(Interrupt);
|
||||
///
|
||||
/// do spawn {
|
||||
/// loop {
|
||||
|
|
|
@ -17,7 +17,7 @@ and create ports which will receive notifications after a period of time.
|
|||
|
||||
# Example
|
||||
|
||||
```rust
|
||||
```rust,ignore
|
||||
|
||||
use std::io::Timer;
|
||||
|
||||
|
|
|
@ -218,8 +218,8 @@ pub trait Iterator<A> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let a = [100, 200, 300];
|
||||
/// let mut it = xs.iter().map(|&x|x).peekable();
|
||||
/// let xs = [100, 200, 300];
|
||||
/// let mut it = xs.iter().map(|x| *x).peekable();
|
||||
/// assert_eq!(it.peek().unwrap(), &100);
|
||||
/// assert_eq!(it.next().unwrap(), 100);
|
||||
/// assert_eq!(it.next().unwrap(), 200);
|
||||
|
@ -338,12 +338,14 @@ pub trait Iterator<A> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::iter::count;
|
||||
///
|
||||
/// let xs = [2u, 3];
|
||||
/// let ys = [0u, 1, 0, 1, 2];
|
||||
/// let mut it = xs.iter().flat_map(|&x| count(0u, 1).take(x));
|
||||
/// // Check that `it` has the same elements as `ys`
|
||||
/// let mut i = 0;
|
||||
/// for x: uint in it {
|
||||
/// for x in it {
|
||||
/// assert_eq!(x, ys[i]);
|
||||
/// i += 1;
|
||||
/// }
|
||||
|
@ -366,7 +368,7 @@ pub trait Iterator<A> {
|
|||
/// let mut sum = 0;
|
||||
/// for x in it {
|
||||
/// if x > 5 {
|
||||
/// break;
|
||||
/// continue;
|
||||
/// }
|
||||
/// sum += x;
|
||||
/// }
|
||||
|
@ -391,14 +393,16 @@ pub trait Iterator<A> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
///let xs = [1u, 4, 2, 3, 8, 9, 6];
|
||||
///let sum = xs.iter()
|
||||
/// .map(|&x| x)
|
||||
/// .inspect(|&x| debug!("filtering %u", x))
|
||||
/// .filter(|&x| x % 2 == 0)
|
||||
/// .inspect(|&x| debug!("%u made it through", x))
|
||||
/// .sum();
|
||||
///println(sum.to_str());
|
||||
/// use std::iter::AdditiveIterator;
|
||||
///
|
||||
/// let xs = [1u, 4, 2, 3, 8, 9, 6];
|
||||
/// let sum = xs.iter()
|
||||
/// .map(|&x| x)
|
||||
/// .inspect(|&x| debug!("filtering {}", x))
|
||||
/// .filter(|&x| x % 2 == 0)
|
||||
/// .inspect(|&x| debug!("{} made it through", x))
|
||||
/// .sum();
|
||||
/// println(sum.to_str());
|
||||
/// ```
|
||||
#[inline]
|
||||
fn inspect<'r>(self, f: 'r |&A|) -> Inspect<'r, A, Self> {
|
||||
|
@ -554,8 +558,8 @@ pub trait Iterator<A> {
|
|||
///
|
||||
/// ```rust
|
||||
/// let a = [1, 2, 3, 4, 5];
|
||||
/// assert!(a.iter().all(|&x| *x > 0));
|
||||
/// assert!(!a.iter().all(|&x| *x > 2));
|
||||
/// assert!(a.iter().all(|x| *x > 0));
|
||||
/// assert!(!a.iter().all(|x| *x > 2));
|
||||
/// ```
|
||||
#[inline]
|
||||
fn all(&mut self, f: |A| -> bool) -> bool {
|
||||
|
@ -571,8 +575,8 @@ pub trait Iterator<A> {
|
|||
/// ```rust
|
||||
/// let a = [1, 2, 3, 4, 5];
|
||||
/// let mut it = a.iter();
|
||||
/// assert!(it.any(|&x| *x == 3));
|
||||
/// assert!(!it.any(|&x| *x == 3));
|
||||
/// assert!(it.any(|x| *x == 3));
|
||||
/// assert!(!it.any(|x| *x == 3));
|
||||
/// ```
|
||||
#[inline]
|
||||
fn any(&mut self, f: |A| -> bool) -> bool {
|
||||
|
@ -618,7 +622,7 @@ pub trait Iterator<A> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let xs = [-3, 0, 1, 5, -10];
|
||||
/// let xs = [-3i, 0, 1, 5, -10];
|
||||
/// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
|
||||
/// ```
|
||||
#[inline]
|
||||
|
@ -642,7 +646,7 @@ pub trait Iterator<A> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let xs = [-3, 0, 1, 5, -10];
|
||||
/// let xs = [-3i, 0, 1, 5, -10];
|
||||
/// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
|
||||
/// ```
|
||||
#[inline]
|
||||
|
@ -811,6 +815,8 @@ pub trait AdditiveIterator<A> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::iter::AdditiveIterator;
|
||||
///
|
||||
/// let a = [1, 2, 3, 4, 5];
|
||||
/// let mut it = a.iter().map(|&x| x);
|
||||
/// assert!(it.sum() == 15);
|
||||
|
@ -834,7 +840,7 @@ pub trait MultiplicativeIterator<A> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::iter::count;
|
||||
/// use std::iter::{count, MultiplicativeIterator};
|
||||
///
|
||||
/// fn factorial(n: uint) -> uint {
|
||||
/// count(1u, 1).take_while(|&i| i <= n).product()
|
||||
|
@ -907,6 +913,8 @@ pub trait ClonableIterator {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::iter::{ClonableIterator, count};
|
||||
///
|
||||
/// let a = count(1,1).take(1);
|
||||
/// let mut cy = a.cycle();
|
||||
/// assert_eq!(cy.next(), Some(1));
|
||||
|
|
|
@ -29,10 +29,10 @@ local_data_key!(key_int: int)
|
|||
local_data_key!(key_vector: ~[int])
|
||||
|
||||
local_data::set(key_int, 3);
|
||||
local_data::get(key_int, |opt| assert_eq!(opt, Some(&3)));
|
||||
local_data::get(key_int, |opt| assert_eq!(opt.map(|x| *x), Some(3)));
|
||||
|
||||
local_data::set(key_vector, ~[4]);
|
||||
local_data::get(key_vector, |opt| assert_eq!(opt, Some(&~[4])));
|
||||
local_data::get(key_vector, |opt| assert_eq!(*opt.unwrap(), ~[4]));
|
||||
```
|
||||
|
||||
*/
|
||||
|
|
|
@ -78,7 +78,7 @@ error,hello=warn // turn on global error logging and also warn for hello
|
|||
|
||||
Each of these macros will expand to code similar to:
|
||||
|
||||
```rust
|
||||
```rust,ignore
|
||||
if log_level <= my_module_log_level() {
|
||||
::std::logging::log(log_level, format!(...));
|
||||
}
|
||||
|
|
|
@ -339,7 +339,8 @@ impl Round for f32 {
|
|||
/// The fractional part of the number, satisfying:
|
||||
///
|
||||
/// ```rust
|
||||
/// assert!(x == trunc(x) + fract(x))
|
||||
/// let x = 1.65f32;
|
||||
/// assert!(x == x.trunc() + x.fract())
|
||||
/// ```
|
||||
///
|
||||
#[inline]
|
||||
|
|
|
@ -357,7 +357,8 @@ impl Round for f64 {
|
|||
/// The fractional part of the number, satisfying:
|
||||
///
|
||||
/// ```rust
|
||||
/// assert!(x == trunc(x) + fract(x))
|
||||
/// let x = 1.65f64;
|
||||
/// assert!(x == x.trunc() + x.fract())
|
||||
/// ```
|
||||
///
|
||||
#[inline]
|
||||
|
|
|
@ -101,8 +101,7 @@ pub trait Unsigned: Num {}
|
|||
/// Times trait
|
||||
///
|
||||
/// ```rust
|
||||
/// use num::Times;
|
||||
/// let ten = 10 as uint;
|
||||
/// let ten = 10u;
|
||||
/// let mut accum = 0;
|
||||
/// ten.times(|| { accum += 1; })
|
||||
/// ```
|
||||
|
@ -176,10 +175,10 @@ pub trait Round {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_approx_eq!(1.3f32.round(), 1.0);
|
||||
/// assert_approx_eq!((-1.3f32).round(), -1.0);
|
||||
/// assert_approx_eq!(1.5f32.round(), 1.0);
|
||||
/// assert_approx_eq!((-1.5f32).round(), -1.0);
|
||||
/// assert_approx_eq!(1.3f32.trunc(), 1.0);
|
||||
/// assert_approx_eq!((-1.3f32).trunc(), -1.0);
|
||||
/// assert_approx_eq!(1.5f32.trunc(), 1.0);
|
||||
/// assert_approx_eq!((-1.5f32).trunc(), -1.0);
|
||||
/// ```
|
||||
fn trunc(&self) -> Self;
|
||||
|
||||
|
@ -188,10 +187,10 @@ pub trait Round {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_approx_eq!(1.3f32.round(), 0.3);
|
||||
/// assert_approx_eq!((-1.3f32).round(), -0.3);
|
||||
/// assert_approx_eq!(1.5f32.round(), 0.5);
|
||||
/// assert_approx_eq!((-1.5f32).round(), -0.5);
|
||||
/// assert_approx_eq!(1.3f32.fract(), 0.3);
|
||||
/// assert_approx_eq!((-1.3f32).fract(), -0.3);
|
||||
/// assert_approx_eq!(1.5f32.fract(), 0.5);
|
||||
/// assert_approx_eq!((-1.5f32).fract(), -0.5);
|
||||
/// ```
|
||||
fn fract(&self) -> Self;
|
||||
}
|
||||
|
@ -225,7 +224,9 @@ pub trait Algebraic {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let sixteen: float = num::pow(2.0, 4.0);
|
||||
/// use std::num;
|
||||
///
|
||||
/// let sixteen: f64 = num::pow(2.0, 4.0);
|
||||
/// assert_eq!(sixteen, 16.0);
|
||||
/// ```
|
||||
#[inline(always)] pub fn pow<T: Algebraic>(value: T, n: T) -> T { value.pow(&n) }
|
||||
|
@ -266,6 +267,8 @@ pub trait Trigonometric {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::f32;
|
||||
///
|
||||
/// let y = 3f32.sqrt();
|
||||
/// let x = 1f32;
|
||||
/// assert_approx_eq!(y.atan2(&x), f32::consts::PI / 3f32);
|
||||
|
|
|
@ -54,12 +54,11 @@ actually operates on the path; it is only intended for display.
|
|||
|
||||
```rust
|
||||
let mut path = Path::new("/tmp/path");
|
||||
debug!("path: {}", path.display());
|
||||
println!("path: {}", path.display());
|
||||
path.set_filename("foo");
|
||||
path.push("bar");
|
||||
debug!("new path: {}", path.display());
|
||||
let b = std::os::path_exists(&path);
|
||||
debug!("path exists: {}", b);
|
||||
println!("new path: {}", path.display());
|
||||
println!("path exists: {}", path.exists());
|
||||
```
|
||||
|
||||
*/
|
||||
|
|
|
@ -39,7 +39,7 @@ use num;
|
|||
///
|
||||
/// fn main() {
|
||||
/// let gamma = Gamma::new(2.0, 5.0);
|
||||
/// let v = gamma.ind_sample(rand::task_rng());
|
||||
/// let v = gamma.ind_sample(&mut rand::task_rng());
|
||||
/// println!("{} is from a Gamma(2, 5) distribution", v);
|
||||
/// }
|
||||
/// ```
|
||||
|
|
|
@ -98,10 +98,10 @@ pub struct Weighted<T> {
|
|||
/// let wc = WeightedChoice::new(~[Weighted { weight: 2, item: 'a' },
|
||||
/// Weighted { weight: 4, item: 'b' },
|
||||
/// Weighted { weight: 1, item: 'c' }]);
|
||||
/// let rng = rand::task_rng();
|
||||
/// let mut rng = rand::task_rng();
|
||||
/// for _ in range(0, 16) {
|
||||
/// // on average prints 'a' 4 times, 'b' 8 and 'c' twice.
|
||||
/// println!("{}", wc.ind_sample(rng));
|
||||
/// println!("{}", wc.ind_sample(&mut rng));
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
|
|
|
@ -123,7 +123,7 @@ impl IndependentSample<f64> for Normal {
|
|||
/// fn main() {
|
||||
/// // mean 2, standard deviation 3
|
||||
/// let log_normal = LogNormal::new(2.0, 3.0);
|
||||
/// let v = normal.ind_sample(&mut rand::task_rng());
|
||||
/// let v = log_normal.ind_sample(&mut rand::task_rng());
|
||||
/// println!("{} is from an ln N(2, 9) distribution", v)
|
||||
/// }
|
||||
/// ```
|
||||
|
|
|
@ -39,10 +39,10 @@ use rand::distributions::{Sample, IndependentSample};
|
|||
///
|
||||
/// fn main() {
|
||||
/// let between = Range::new(10u, 10000u);
|
||||
/// let rng = rand::task_rng();
|
||||
/// let mut rng = rand::task_rng();
|
||||
/// let mut sum = 0;
|
||||
/// for _ in range(0, 1000) {
|
||||
/// sum += between.ind_sample(rng);
|
||||
/// sum += between.ind_sample(&mut rng);
|
||||
/// }
|
||||
/// println!("{}", sum);
|
||||
/// }
|
||||
|
|
|
@ -64,7 +64,7 @@ use std::rand;
|
|||
|
||||
fn main () {
|
||||
let tuple_ptr = rand::random::<~(f64, char)>();
|
||||
println!(tuple_ptr)
|
||||
println!("{:?}", tuple_ptr)
|
||||
}
|
||||
```
|
||||
*/
|
||||
|
@ -227,7 +227,7 @@ pub trait Rng {
|
|||
/// let mut rng = rand::task_rng();
|
||||
/// let n: uint = rng.gen_range(0u, 10);
|
||||
/// println!("{}", n);
|
||||
/// let m: float = rng.gen_range(-40.0, 1.3e5);
|
||||
/// let m: f64 = rng.gen_range(-40.0, 1.3e5);
|
||||
/// println!("{}", m);
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -292,8 +292,10 @@ pub trait Rng {
|
|||
/// use std::rand::Rng;
|
||||
///
|
||||
/// fn main() {
|
||||
/// println!("{:?}", rand::task_rng().choose_option([1,2,4,8,16,32]));
|
||||
/// println!("{:?}", rand::task_rng().choose_option([]));
|
||||
/// let choices = [1, 2, 4, 8, 16, 32];
|
||||
/// let mut rng = rand::task_rng();
|
||||
/// println!("{:?}", rng.choose_option(choices));
|
||||
/// println!("{:?}", rng.choose_option(choices.slice_to(0)));
|
||||
/// }
|
||||
/// ```
|
||||
fn choose_option<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> {
|
||||
|
@ -388,11 +390,10 @@ pub trait SeedableRng<Seed>: Rng {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::rand;
|
||||
/// use std::rand::Rng;
|
||||
/// use std::rand::{Rng, SeedableRng, StdRng};
|
||||
///
|
||||
/// fn main() {
|
||||
/// let mut rng: rand::StdRng = rand::SeedableRng::from_seed(&[1, 2, 3, 4]);
|
||||
/// let mut rng: StdRng = SeedableRng::from_seed(&[1, 2, 3, 4]);
|
||||
/// println!("{}", rng.gen::<f64>());
|
||||
/// rng.reseed([5, 6, 7, 8]);
|
||||
/// println!("{}", rng.gen::<f64>());
|
||||
|
|
|
@ -1458,10 +1458,10 @@ pub trait StrSlice<'a> {
|
|||
/// let v: ~[(uint, uint)] = "abcXXXabcYYYabc".match_indices("abc").collect();
|
||||
/// assert_eq!(v, ~[(0,3), (6,9), (12,15)]);
|
||||
///
|
||||
/// let v: ~[(uint, uint)] = "1abcabc2".split_str("abc").collect();
|
||||
/// let v: ~[(uint, uint)] = "1abcabc2".match_indices("abc").collect();
|
||||
/// assert_eq!(v, ~[(1,4), (4,7)]);
|
||||
///
|
||||
/// let v: ~[(uint, uint)] = "ababa".split_str("aba").collect();
|
||||
/// let v: ~[(uint, uint)] = "ababa".match_indices("aba").collect();
|
||||
/// assert_eq!(v, ~[(0, 3)]); // only the first `aba`
|
||||
/// ```
|
||||
fn match_indices(&self, sep: &'a str) -> MatchesIndexIterator<'a>;
|
||||
|
@ -1536,7 +1536,7 @@ pub trait StrSlice<'a> {
|
|||
/// assert!(" \t\n".is_whitespace());
|
||||
/// assert!("".is_whitespace());
|
||||
///
|
||||
/// assert!( !"abc.is_whitespace());
|
||||
/// assert!( !"abc".is_whitespace());
|
||||
/// ```
|
||||
fn is_whitespace(&self) -> bool;
|
||||
|
||||
|
@ -1606,7 +1606,7 @@ pub trait StrSlice<'a> {
|
|||
/// let s = "Löwe 老虎 Léopard";
|
||||
/// assert_eq!(s.slice(0, 1), "L");
|
||||
///
|
||||
/// assert_eq!(s.slice(1, 9), "öwe 老"));
|
||||
/// assert_eq!(s.slice(1, 9), "öwe 老");
|
||||
///
|
||||
/// // these will fail:
|
||||
/// // byte 2 lies within `ö`:
|
||||
|
@ -1808,6 +1808,8 @@ pub trait StrSlice<'a> {
|
|||
/// `.char_indices`.
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::str::CharRange;
|
||||
///
|
||||
/// let s = "中华Việt Nam";
|
||||
/// let mut i = 0u;
|
||||
/// while i < s.len() {
|
||||
|
@ -1949,11 +1951,11 @@ pub trait StrSlice<'a> {
|
|||
///
|
||||
/// ```rust
|
||||
/// let s = "Löwe 老虎 Léopard";
|
||||
/// let (c, s1) = s.shift_slice_char();
|
||||
/// let (c, s1) = s.slice_shift_char();
|
||||
/// assert_eq!(c, 'L');
|
||||
/// assert_eq!(s1, "öwe 老虎 Léopard");
|
||||
///
|
||||
/// let (c, s2) = s1.shift_slice_char();
|
||||
/// let (c, s2) = s1.slice_shift_char();
|
||||
/// assert_eq!(c, 'ö');
|
||||
/// assert_eq!(s2, "we 老虎 Léopard");
|
||||
/// ```
|
||||
|
|
|
@ -2174,12 +2174,12 @@ pub trait MutableVector<'a, T> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let mut v = [5, 4, 1, 3, 2];
|
||||
/// v.sort(|a, b| a.cmp(b));
|
||||
/// let mut v = [5i, 4, 1, 3, 2];
|
||||
/// v.sort_by(|a, b| a.cmp(b));
|
||||
/// assert_eq!(v, [1, 2, 3, 4, 5]);
|
||||
///
|
||||
/// // reverse sorting
|
||||
/// v.sort(|a, b| b.cmp(a));
|
||||
/// v.sort_by(|a, b| b.cmp(a));
|
||||
/// assert_eq!(v, [5, 4, 3, 2, 1]);
|
||||
/// ```
|
||||
fn sort_by(self, compare: |&T, &T| -> Ordering);
|
||||
|
@ -2395,8 +2395,6 @@ pub trait MutableTotalOrdVector<T> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::vec;
|
||||
///
|
||||
/// let mut v = [-5, 4, 1, -3, 2];
|
||||
///
|
||||
/// v.sort();
|
||||
|
|
Loading…
Reference in New Issue