Repository: rust-lang-nursery/fmt-rfcs
Branch: main
Commit: 52c808b12a10
Files: 10
Total size: 60.0 KB
Directory structure:
gitextract_0pojgh9k/
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── charter.md
├── example/
│ ├── lists-elided.rs
│ ├── lists.rs
│ └── rustfmt.toml
├── nightly-style-procedure.md
├── team-policy.md
└── triagebot.toml
================================================
FILE CONTENTS
================================================
================================================
FILE: LICENSE-APACHE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
================================================
FILE: LICENSE-MIT
================================================
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
# Rust style team repository
This is the home of the [Rust style team](https://www.rust-lang.org/governance/teams/lang#Style%20team). The style team is responsible for
determining the default Rust style, including styling for new language
constructs, as well as evolving the Rust style over time.
The [Rust style
guide](https://github.com/rust-lang/rust/tree/HEAD/src/doc/style-guide/src)
lives in the `rust-lang/rust` repository. In particular, see the [guiding
principles](https://github.com/rust-lang/rust/blob/HEAD/src/doc/style-guide/src/principles.md)
of the Rust style.
This repository includes:
- The [charter](charter.md) for the style team.
- The [policy](team-policy.md) for the style team, including the [handling of
style for nightly language constructs](nightly-style-procedure.md).
## Code of Conduct
All interactions on this repository (whether on issues, PRs, or elsewhere), as
in other parts of the Rust project, are governed by the [Rust Code of
Conduct](https://www.rust-lang.org/policies/code-of-conduct).
## License
[License]: #license
This repository is licensed under either of:
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
at your option.
### Contributions
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.
================================================
FILE: charter.md
================================================
# Style Team
## Aims: Evolving the Rust Style over time
1. Defining the style for new Rust constructs
2. Evolving the existing style over the course of Rust editions (without breaking backwards compatibility)
3. Defining mechanisms to evolve the Rust style while taking backwards compatibility into account, such as via Rust editions or similar mechanisms
## Domains
1. [Style Guide](https://github.com/rust-lang/rust/tree/HEAD/src/doc/style-guide/src)
2. [T-style team repo](https://github.com/rust-lang/style-team/)
3. [#T-style](https://rust-lang.zulipchat.com/#narrow/stream/346005-t-style) Zulip stream
4. [#T-style/private](https://rust-lang.zulipchat.com/#narrow/stream/353175-t-style.2Fprivate) Zulip stream
5. `rust-lang` issues with the `T-style` or `I-style-nominated` labels
## Membership
The active membership of the style team can be found on [rust-lang.org/governance](https://github.com/rust-lang/team/blob/HEAD/teams/style.toml).
The Rust style team shall have at least 3 members and at most 8. If the team has fewer than 3 members it shall seek new members as its primary focus.
Members of the style team are nominated by existing members. All existing members of the team must affirmatively agree to the addition of a member, with zero objections; if there is any objection to a nomination, the new member will not be added. In addition, the team lead or another team member will check with the moderation team regarding any person nominated for membership, to provide an avenue for awareness of concerns or red flags.
### Becoming a member of T-Style
Contributors who believe they'd be a good fit for the style team are encouraged to request an invite[^1] to the team, by reaching out via Zulip private message to one or more team members. The style team will consider all such requests as as a proposal to become a team member and provide clear feedback to the contributor if there are any objections so that any issues may be resolved and the contributor can apply again in the future. The style team will not consider having previously been rejected as a basis for future rejections.
### Team Member Characteristics
The style team is committed to building a diverse and capable team comprising individuals who possess the following characteristics:
1. Representation and Perspectives: The style team values representation from various parts of the Rust organization and ecosystem. We aim to include members with many different perspectives on the Rust language and ecosystem, to ensure that the Rust style works well for a wide variety of Rust users.
2. Familiarity with Rust: Prospective members should have a general familiarity with Rust, including a solid understanding of its constructs, how they interact, and the overall language ecosystem. This knowledge is crucial for making informed decisions regarding style and formatting guidelines.
3. Interest in Rust Style: Members should have a genuine interest in Rust style and a willingness to contribute to the team's efforts. It is important that members are not solely focused on advocating for their personal style preferences but are dedicated to promoting a collective and consensus-based approach.
4. Effective Collaboration Skills: Successful candidates will have a proven track record of effective collaboration, showcasing their ability to work together with others, consider diverse perspectives, navigate conflicts, and address emotional challenges in a constructive manner.
5. Effective Communication in Charged Conversations: Members will need to carefully navigate charged conversations and evocative feedback, and respond constructively and with empathy, to each other and to the community. Members should be able to handle passionate discussions about code style, recognize miscommunication and misunderstandings, and promote empathy and listening.
6. Familiarity with Rust Project: Members should be familiar with the Rust project's structure, culture, and expectations upon maintainers. This knowledge helps members navigate the ecosystem more effectively, and align their style decisions with the project's broader goals.
7. Consent to Principles and Aims: Members are expected to align with and consent to the principles and aims of the style team, as outlined in the [Rust style guide principles](https://github.com/rust-lang/rust/blob/master/src/doc/style-guide/src/principles.md) and the style team's [charter](https://github.com/rust-lang/style-team/blob/style-policy/charter.md).
8. Pragmatic Approach: Members should prioritize pragmatism over dogmatism, even when dealing with style and formatting aspects they feel particularly strongly about. The ability to make practical and reasonable decisions that benefit the community at large is essential.
9. Openness to Change and Learning: Members should demonstrate a willingness to seek out and receive new information, introspect on their underlying values, change their opinions based on evidence and rationale, and adapt their perspectives accordingly.
10. Interest in Language and Syntax: Members should show interest in tracking changes to the Rust language and syntax. Keeping up-to-date with the latest developments helps inform style decisions.
11. Ability to weigh subjective decisions, and seek out "better" rather than "perfect": We need a default Rust style, and even in the face of conflicting requirements we still need to make a decision. Style team decisions will attempt to best satisfy most members of the Rust community, but can never be perfect. Members will need to keep this in mind and help the style team make the best consent-based decisions it can.
[^1]: We suggest reaching out via zulip DM to one of the current team members, and contacting the lead by default if you're unsure who to reach out to.
================================================
FILE: example/lists-elided.rs
================================================
// Copyright 2015 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::cmp;
use std::iter::Peekable;
use syntax::codemap::{self, CodeMap, BytePos};
use Indent;
use comment::{FindUncommented, rewrite_comment, find_comment_end};
use config::Config;
/// Formatting tactic for lists. This will be cast down to a
/// DefinitiveListTactic depending on the number and length of the items and
/// their comments.
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum ListTactic {
// One item per row.
Vertical,
// All items on one row.
Horizontal,
// Try Horizontal layout, if that fails then vertical.
HorizontalVertical,
// HorizontalVertical with a soft limit of n characters.
LimitedHorizontalVertical(usize),
// Pack as many items as possible per row over (possibly) many rows.
Mixed,
}
impl_enum_decodable!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed);
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum SeparatorTactic {
Always,
Never,
Vertical,
}
impl_enum_decodable!(SeparatorTactic, Always, Never, Vertical);
impl SeparatorTactic {
pub fn from_bool(b: bool) -> SeparatorTactic {
if b {
SeparatorTactic::Always
} else {
SeparatorTactic::Never
}
}
}
pub struct ListFormatting<'a> {
pub tactic: DefinitiveListTactic,
pub separator: &'a str,
pub trailing_separator: SeparatorTactic,
pub indent: Indent,
pub width: usize,
// Non-expressions, e.g. items, will have a new line at the end of the list.
// Important for comment styles.
pub ends_with_newline: bool,
pub config: &'a Config,
}
pub fn format_fn_args<I>(items: I, width: usize, offset: Indent, config: &Config) -> Option<String>
where
I: Iterator<Item = ListItem>,
{
// ...
}
pub fn format_item_list<I>(
items: I,
width: usize,
offset: Indent,
config: &Config,
) -> Option<String>
where
I: Iterator<Item = ListItem>,
{
list_helper(items, width, offset, config, ListTactic::HorizontalVertical)
}
pub fn list_helper<I>(
items: I,
width: usize,
offset: Indent,
config: &Config,
tactic: ListTactic,
) -> Option<String>
where
I: Iterator<Item = ListItem>,
{
let item_vec: Vec<_> = items.collect();
let tactic = definitive_tactic(&item_vec, tactic, width);
let fmt = ListFormatting {
tactic: tactic,
separator: ",",
trailing_separator: SeparatorTactic::Never,
indent: offset,
width: width,
ends_with_newline: false,
config: config,
};
write_list(&item_vec, &fmt)
}
impl AsRef<ListItem> for ListItem {
fn as_ref(&self) -> &ListItem {
self
}
}
pub struct ListItem {
// None for comments mean that they are not present.
pub pre_comment: Option<String>,
// Item should include attributes and doc comments. None indicates a failed
// rewrite.
pub item: Option<String>,
pub post_comment: Option<String>,
// Whether there is extra whitespace before this item.
pub new_lines: bool,
}
impl ListItem {
pub fn is_multiline(&self) -> bool {
// ...
}
pub fn has_line_pre_comment(&self) -> bool {
self.pre_comment.as_ref().map_or(false, |comment| comment.starts_with("//"))
}
pub fn from_str<S: Into<String>>(s: S) -> ListItem {
ListItem {
pre_comment: None,
item: Some(s.into()),
post_comment: None,
new_lines: false,
}
}
}
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
/// The definitive formatting tactic for lists.
pub enum DefinitiveListTactic {
Vertical,
Horizontal,
Mixed,
}
pub fn definitive_tactic<I, T>(items: I, tactic: ListTactic, width: usize) -> DefinitiveListTactic
where
I: IntoIterator<Item = T> + Clone,
T: AsRef<ListItem>,
{
let pre_line_comments =
items.clone().into_iter().any(|item| item.as_ref().has_line_pre_comment());
let limit = match tactic {
_ if pre_line_comments => return DefinitiveListTactic::Vertical,
ListTactic::Mixed => return DefinitiveListTactic::Mixed,
ListTactic::Horizontal => return DefinitiveListTactic::Horizontal,
ListTactic::Vertical => return DefinitiveListTactic::Vertical,
ListTactic::LimitedHorizontalVertical(limit) => ::std::cmp::min(width, limit),
ListTactic::HorizontalVertical => width,
};
let (sep_count, total_width) = calculate_width(items.clone());
let sep_len = ", ".len(); // FIXME: make more generic?
let total_sep_len = sep_len * sep_count.checked_sub(1).unwrap_or(0);
let real_total = total_width + total_sep_len;
}
// Format a list of commented items into a string.
// TODO: add unit tests
pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option<String>
where
I: IntoIterator<Item = T>,
T: AsRef<ListItem>,
{
let tactic = formatting.tactic;
let sep_len = formatting.separator.len();
// Now that we know how we will layout, we can decide for sure if there
// will be a trailing separator.
let trailing_separator = needs_trailing_separator(formatting.trailing_separator, tactic);
let mut result = String::new();
let mut iter = items.into_iter().enumerate().peekable();
let mut line_len = 0;
let indent_str = &formatting.indent.to_string(formatting.config);
while let Some((i, item)) = iter.next() {
let item = item.as_ref();
let inner_item = try_opt!(item.item.as_ref());
let first = i == 0;
let last = iter.peek().is_none();
let separate = !last || trailing_separator;
let item_sep_len = if separate { sep_len } else { 0 };
// Item string may be multi-line. Its length (used for block comment alignment)
// Should be only the length of the last line.
let item_last_line = if item.is_multiline() {
inner_item.lines().last().unwrap_or("")
} else {
inner_item.as_ref()
};
let mut item_last_line_width = item_last_line.len() + item_sep_len;
if item_last_line.starts_with(indent_str) {
item_last_line_width -= indent_str.len();
}
match tactic {
DefinitiveListTactic::Horizontal if !first => {
result.push(' ');
}
DefinitiveListTactic::Vertical if !first => {
result.push('\n');
result.push_str(indent_str);
}
DefinitiveListTactic::Mixed => {
let total_width = total_item_width(item) + item_sep_len;
// 1 is space between separator and item.
if line_len > 0 && line_len + 1 + total_width > formatting.width {
result.push('\n');
result.push_str(indent_str);
line_len = 0;
}
if line_len > 0 {
result.push(' ');
line_len += 1;
}
line_len += total_width;
}
_ => {}
}
result.push_str(&inner_item[..]);
if separate {
result.push_str(formatting.separator);
}
if !last && tactic == DefinitiveListTactic::Vertical && item.new_lines {
result.push('\n');
}
}
Some(result)
}
pub struct ListItems<'a, I, F1, F2, F3>
where
I: Iterator,
{
codemap: &'a CodeMap,
inner: Peekable<I>,
get_lo: F1,
get_hi: F2,
get_item_string: F3,
prev_span_end: BytePos,
next_span_start: BytePos,
terminator: &'a str,
}
impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
where
I: Iterator<Item = T>,
F1: Fn(&T) -> BytePos,
F2: Fn(&T) -> BytePos,
F3: Fn(&T) -> Option<String>,
{
type Item = ListItem;
fn next(&mut self) -> Option<Self::Item> {
// ...
}
}
// Creates an iterator over a list's items with associated comments.
pub fn itemize_list<'a, T, I, F1, F2, F3>(
codemap: &'a CodeMap,
inner: I,
terminator: &'a str,
get_lo: F1,
get_hi: F2,
get_item_string: F3,
prev_span_end: BytePos,
next_span_start: BytePos,
) -> ListItems<'a, I, F1, F2, F3>
where
I: Iterator<Item = T>,
F1: Fn(&T) -> BytePos,
F2: Fn(&T) -> BytePos,
F3: Fn(&T) -> Option<String>,
{
ListItems {
codemap: codemap,
inner: inner.peekable(),
get_lo: get_lo,
get_hi: get_hi,
get_item_string: get_item_string,
prev_span_end: prev_span_end,
next_span_start: next_span_start,
terminator: terminator,
}
}
fn needs_trailing_separator(
separator_tactic: SeparatorTactic,
list_tactic: DefinitiveListTactic,
) -> bool {
match separator_tactic {
SeparatorTactic::Always => true,
SeparatorTactic::Vertical => list_tactic == DefinitiveListTactic::Vertical,
SeparatorTactic::Never => false,
}
}
/// Returns the count and total width of the list items.
fn calculate_width<I, T>(items: I) -> (usize, usize)
where
I: IntoIterator<Item = T>,
T: AsRef<ListItem>,
{
// ...
}
fn total_item_width(item: &ListItem) -> usize {
// ...
}
fn comment_len(comment: Option<&str>) -> usize {
match comment {
Some(s) => {
let text_len = s.trim().len();
if text_len > 0 {
// We'll put " /*" before and " */" after inline comments.
text_len + 6
} else {
text_len
}
}
None => 0,
}
}
================================================
FILE: example/lists.rs
================================================
// Copyright 2015 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::cmp;
use std::iter::Peekable;
use syntax::codemap::{self, BytePos, CodeMap};
use Indent;
use comment::{find_comment_end, rewrite_comment, FindUncommented};
use config::Config;
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
/// Formatting tactic for lists. This will be cast down to a
/// DefinitiveListTactic depending on the number and length of the items and
/// their comments.
pub enum ListTactic {
// One item per row.
Vertical,
// All items on one row.
Horizontal,
// Try Horizontal layout, if that fails then vertical.
HorizontalVertical,
// HorizontalVertical with a soft limit of n characters.
LimitedHorizontalVertical(usize),
// Pack as many items as possible per row over (possibly) many rows.
Mixed,
}
impl_enum_decodable!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed);
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum SeparatorTactic {
Always,
Never,
Vertical,
}
impl_enum_decodable!(SeparatorTactic, Always, Never, Vertical);
impl SeparatorTactic {
pub fn from_bool(b: bool) -> SeparatorTactic {
if b {
SeparatorTactic::Always
} else {
SeparatorTactic::Never
}
}
}
pub struct ListFormatting<'a> {
pub tactic: DefinitiveListTactic,
pub separator: &'a str,
pub trailing_separator: SeparatorTactic,
pub indent: Indent,
pub width: usize,
// Non-expressions, e.g. items, will have a new line at the end of the list.
// Important for comment styles.
pub ends_with_newline: bool,
pub config: &'a Config,
}
pub fn format_fn_args<I>(items: I, width: usize, offset: Indent, config: &Config) -> Option<String>
where
I: Iterator<Item = ListItem>,
{
list_helper(
items,
width,
offset,
config,
ListTactic::LimitedHorizontalVertical(config.fn_call_width),
)
}
pub fn format_item_list<I>(
items: I,
width: usize,
offset: Indent,
config: &Config,
) -> Option<String>
where
I: Iterator<Item = ListItem>,
{
list_helper(items, width, offset, config, ListTactic::HorizontalVertical)
}
pub fn list_helper<I>(
items: I,
width: usize,
offset: Indent,
config: &Config,
tactic: ListTactic,
) -> Option<String>
where
I: Iterator<Item = ListItem>,
{
let item_vec: Vec<_> = items.collect();
let tactic = definitive_tactic(&item_vec, tactic, width);
let fmt = ListFormatting {
tactic: tactic,
separator: ",",
trailing_separator: SeparatorTactic::Never,
indent: offset,
width: width,
ends_with_newline: false,
config: config,
};
write_list(&item_vec, &fmt)
}
impl AsRef<ListItem> for ListItem {
fn as_ref(&self) -> &ListItem {
self
}
}
pub struct ListItem {
// None for comments mean that they are not present.
pub pre_comment: Option<String>,
// Item should include attributes and doc comments. None indicates a failed
// rewrite.
pub item: Option<String>,
pub post_comment: Option<String>,
// Whether there is extra whitespace before this item.
pub new_lines: bool,
}
impl ListItem {
pub fn is_multiline(&self) -> bool {
self.item.as_ref().map_or(false, |s| s.contains('\n')) || self.pre_comment.is_some() ||
self.post_comment
.as_ref()
.map_or(false, |s| s.contains('\n'))
}
pub fn has_line_pre_comment(&self) -> bool {
self.pre_comment
.as_ref()
.map_or(false, |comment| comment.starts_with("//"))
}
pub fn from_str<S: Into<String>>(s: S) -> ListItem {
ListItem {
pre_comment: None,
item: Some(s.into()),
post_comment: None,
new_lines: false,
}
}
}
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
/// The definitive formatting tactic for lists.
pub enum DefinitiveListTactic {
Vertical,
Horizontal,
Mixed,
}
pub fn definitive_tactic<I, T>(items: I, tactic: ListTactic, width: usize) -> DefinitiveListTactic
where
I: IntoIterator<Item = T> + Clone,
T: AsRef<ListItem>,
{
let pre_line_comments = items
.clone()
.into_iter()
.any(|item| item.as_ref().has_line_pre_comment());
let limit = match tactic {
_ if pre_line_comments => return DefinitiveListTactic::Vertical,
ListTactic::Mixed => return DefinitiveListTactic::Mixed,
ListTactic::Horizontal => return DefinitiveListTactic::Horizontal,
ListTactic::Vertical => return DefinitiveListTactic::Vertical,
ListTactic::LimitedHorizontalVertical(limit) => ::std::cmp::min(width, limit),
ListTactic::HorizontalVertical => width,
};
let (sep_count, total_width) = calculate_width(items.clone());
let sep_len = ", ".len(); // FIXME: make more generic?
let total_sep_len = sep_len * sep_count.checked_sub(1).unwrap_or(0);
let real_total = total_width + total_sep_len;
if real_total <= limit && !pre_line_comments &&
!items.into_iter().any(|item| item.as_ref().is_multiline())
{
DefinitiveListTactic::Horizontal
} else {
DefinitiveListTactic::Vertical
}
}
// Format a list of commented items into a string.
// TODO: add unit tests
pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option<String>
where
I: IntoIterator<Item = T>,
T: AsRef<ListItem>,
{
let tactic = formatting.tactic;
let sep_len = formatting.separator.len();
// Now that we know how we will layout, we can decide for sure if there
// will be a trailing separator.
let trailing_separator = needs_trailing_separator(formatting.trailing_separator, tactic);
let mut result = String::new();
let mut iter = items.into_iter().enumerate().peekable();
let mut line_len = 0;
let indent_str = &formatting.indent.to_string(formatting.config);
while let Some((i, item)) = iter.next() {
let item = item.as_ref();
let inner_item = try_opt!(item.item.as_ref());
let first = i == 0;
let last = iter.peek().is_none();
let separate = !last || trailing_separator;
let item_sep_len = if separate { sep_len } else { 0 };
// Item string may be multi-line. Its length (used for block comment alignment)
// Should be only the length of the last line.
let item_last_line = if item.is_multiline() {
inner_item.lines().last().unwrap_or("")
} else {
inner_item.as_ref()
};
let mut item_last_line_width = item_last_line.len() + item_sep_len;
if item_last_line.starts_with(indent_str) {
item_last_line_width -= indent_str.len();
}
match tactic {
DefinitiveListTactic::Horizontal if !first => {
result.push(' ');
}
DefinitiveListTactic::Vertical if !first => {
result.push('\n');
result.push_str(indent_str);
}
DefinitiveListTactic::Mixed => {
let total_width = total_item_width(item) + item_sep_len;
// 1 is space between separator and item.
if line_len > 0 && line_len + 1 + total_width > formatting.width {
result.push('\n');
result.push_str(indent_str);
line_len = 0;
}
if line_len > 0 {
result.push(' ');
line_len += 1;
}
line_len += total_width;
}
_ => {}
}
// Pre-comments
if let Some(ref comment) = item.pre_comment {
// Block style in non-vertical mode.
let block_mode = tactic != DefinitiveListTactic::Vertical;
// Width restriction is only relevant in vertical mode.
let max_width = formatting.width;
let comment = try_opt!(rewrite_comment(
comment,
block_mode,
max_width,
formatting.indent,
formatting.config,
),);
result.push_str(&comment);
if tactic == DefinitiveListTactic::Vertical {
result.push('\n');
result.push_str(indent_str);
} else {
result.push(' ');
}
}
result.push_str(&inner_item[..]);
// Post-comments
if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() {
let comment = item.post_comment.as_ref().unwrap();
let formatted_comment = try_opt!(rewrite_comment(
comment,
true,
formatting.width,
Indent::empty(),
formatting.config,
),);
result.push(' ');
result.push_str(&formatted_comment);
}
if separate {
result.push_str(formatting.separator);
}
if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() {
// 1 = space between item and comment.
let width = formatting
.width
.checked_sub(item_last_line_width + 1)
.unwrap_or(1);
let mut offset = formatting.indent;
offset.alignment += item_last_line_width + 1;
let comment = item.post_comment.as_ref().unwrap();
debug!("Width = {}, offset = {:?}", width, offset);
// Use block-style only for the last item or multiline comments.
let block_style = !formatting.ends_with_newline && last ||
comment.trim().contains('\n') ||
comment.trim().len() > width;
let formatted_comment = try_opt!(rewrite_comment(
comment,
block_style,
width,
offset,
formatting.config
));
result.push(' ');
result.push_str(&formatted_comment);
}
if !last && tactic == DefinitiveListTactic::Vertical && item.new_lines {
result.push('\n');
}
}
Some(result)
}
pub struct ListItems<'a, I, F1, F2, F3>
where
I: Iterator,
{
codemap: &'a CodeMap,
inner: Peekable<I>,
get_lo: F1,
get_hi: F2,
get_item_string: F3,
prev_span_end: BytePos,
next_span_start: BytePos,
terminator: &'a str,
}
impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
where
I: Iterator<Item = T>,
F1: Fn(&T) -> BytePos,
F2: Fn(&T) -> BytePos,
F3: Fn(&T) -> Option<String>,
{
type Item = ListItem;
fn next(&mut self) -> Option<Self::Item> {
let white_space: &[_] = &[' ', '\t'];
self.inner.next().map(|item| {
let mut new_lines = false;
// Pre-comment
let pre_snippet = self.codemap
.span_to_snippet(codemap::mk_sp(self.prev_span_end, (self.get_lo)(&item)))
.unwrap();
let trimmed_pre_snippet = pre_snippet.trim();
let pre_comment = if !trimmed_pre_snippet.is_empty() {
Some(trimmed_pre_snippet.to_owned())
} else {
None
};
// Post-comment
let next_start = match self.inner.peek() {
Some(next_item) => (self.get_lo)(next_item),
None => self.next_span_start,
};
let post_snippet = self.codemap
.span_to_snippet(codemap::mk_sp((self.get_hi)(&item), next_start))
.unwrap();
let comment_end = match self.inner.peek() {
Some(..) => {
let block_open_index = post_snippet.find("/*");
let newline_index = post_snippet.find('\n');
let separator_index = post_snippet.find_uncommented(",").unwrap();
match (block_open_index, newline_index) {
// Separator before comment, with the next item on same line.
// Comment belongs to next item.
(Some(i), None) if i > separator_index => separator_index + 1,
// Block-style post-comment before the separator.
(Some(i), None) => cmp::max(
find_comment_end(&post_snippet[i..]).unwrap() + i,
separator_index + 1,
),
// Block-style post-comment. Either before or after the separator.
(Some(i), Some(j)) if i < j => cmp::max(
find_comment_end(&post_snippet[i..]).unwrap() + i,
separator_index + 1,
),
// Potential *single* line comment.
(_, Some(j)) if j > separator_index => j + 1,
_ => post_snippet.len(),
}
}
None => post_snippet
.find_uncommented(self.terminator)
.unwrap_or(post_snippet.len()),
};
if !post_snippet.is_empty() && comment_end > 0 {
// Account for extra whitespace between items. This is fiddly
// because of the way we divide pre- and post- comments.
// Everything from the separator to the next item.
let test_snippet = &post_snippet[comment_end - 1..];
let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len());
// From the end of the first line of comments.
let test_snippet = &test_snippet[first_newline..];
let first = test_snippet
.find(|c: char| !c.is_whitespace())
.unwrap_or(test_snippet.len());
// From the end of the first line of comments to the next non-whitespace char.
let test_snippet = &test_snippet[..first];
if test_snippet.chars().filter(|c| c == &'\n').count() > 1 {
// There were multiple line breaks which got trimmed to nothing.
new_lines = true;
}
}
// Cleanup post-comment: strip separators and whitespace.
self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32);
let post_snippet = post_snippet[..comment_end].trim();
let post_snippet_trimmed = if post_snippet.starts_with(',') {
post_snippet[1..].trim_matches(white_space)
} else if post_snippet.ends_with(',') {
post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space)
} else {
post_snippet
};
let post_comment = if !post_snippet_trimmed.is_empty() {
Some(post_snippet_trimmed.to_owned())
} else {
None
};
ListItem {
pre_comment: pre_comment,
item: (self.get_item_string)(&item),
post_comment: post_comment,
new_lines: new_lines,
}
})
}
}
// Creates an iterator over a list's items with associated comments.
pub fn itemize_list<'a, T, I, F1, F2, F3>(
codemap: &'a CodeMap,
inner: I,
terminator: &'a str,
get_lo: F1,
get_hi: F2,
get_item_string: F3,
prev_span_end: BytePos,
next_span_start: BytePos,
) -> ListItems<'a, I, F1, F2, F3>
where
I: Iterator<Item = T>,
F1: Fn(&T) -> BytePos,
F2: Fn(&T) -> BytePos,
F3: Fn(&T) -> Option<String>,
{
ListItems {
codemap: codemap,
inner: inner.peekable(),
get_lo: get_lo,
get_hi: get_hi,
get_item_string: get_item_string,
prev_span_end: prev_span_end,
next_span_start: next_span_start,
terminator: terminator,
}
}
fn needs_trailing_separator(
separator_tactic: SeparatorTactic,
list_tactic: DefinitiveListTactic,
) -> bool {
match separator_tactic {
SeparatorTactic::Always => true,
SeparatorTactic::Vertical => list_tactic == DefinitiveListTactic::Vertical,
SeparatorTactic::Never => false,
}
}
/// Returns the count and total width of the list items.
fn calculate_width<I, T>(items: I) -> (usize, usize)
where
I: IntoIterator<Item = T>,
T: AsRef<ListItem>,
{
items
.into_iter()
.map(|item| total_item_width(item.as_ref()))
.fold((0, 0), |acc, l| (acc.0 + 1, acc.1 + l))
}
fn total_item_width(item: &ListItem) -> usize {
comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) +
comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) +
item.item.as_ref().map_or(0, |str| str.len())
}
fn comment_len(comment: Option<&str>) -> usize {
match comment {
Some(s) => {
let text_len = s.trim().len();
if text_len > 0 {
// We'll put " /*" before and " */" after inline comments.
text_len + 6
} else {
text_len
}
}
None => 0,
}
}
================================================
FILE: example/rustfmt.toml
================================================
fn_args_layout = "Block"
array_layout = "Block"
control_style = "Rfc"
where_style = "Rfc"
generics_indent = "Block"
fn_call_style = "Block"
================================================
FILE: nightly-style-procedure.md
================================================
The style guide may or may not prescribe formatting behavior for nightly syntax
in the "nightly" chapter in preparation for a feature's eventual stabilization
or to reflect actual the behavior implemented by rustfmt around nightly syntax.
This behavior is not binding until the feature is stabilized and the text is moved
into the appropriate section of the style guide.
Initial PR(s) implementing new syntax filed against rust-lang/rust should
generally leave the rustfmt subtree untouched. In cases that that need to
modify rustfmt (for example, to fix compiler errors that come from adding
new variants to AST representation), they should modify rustfmt in such a
way to keep existing formatting verbatim.
Rustfmt is allowed to implement nightly-only formatting behavior without that
syntax being specified by the style guide. The initial authors of PRs
implementing new features in rust-lang/rust are encouraged, but not
required, to open a PR against
[rustfmt](https://github.com/rust-lang/rustfmt) suggesting an initial
formatting behavior, or formatting may later be implemented as a PR by anyone,
pending approval of the implementation from T-rustfmt. T-style should be
notified to approve the interim style proposed by these PRs, but this decision
is not binding and may be revisited until the feature is stabilized and the
formatting is codified in the style guide.
Much like breaking nightly feature changes in the Rust compiler, any changes
to formatting behavior for nightly syntax should be made cautiously and with
thorough consideration to avoid churn. Changes should not be done unnecessarily,
and should take into account the feature's adoption
and readiness for stabilization. However, changes may be done until the feature
is stabilized for various reasons: new understanding of the feature's usage in
the language, recommendation from T-style, or changes in the implementation of
the feature.
Feature stabilization should be blocked on confirmation and codification of
formatting behavior. At this point, T-style may also propose alternative
formatting at the time of stabilization, with any breaking changes weighted
according to the breaking changes principle stated above.
================================================
FILE: team-policy.md
================================================
# Style Team Policy Document
This is a living document tracking the active policies of the style team. It is intended to fill a similar role to the books that many[^1] teams[^2] maintain[^3] independently[^4]. If in the future Rust establishes central linking/indexing/aggregating of policies, these will need to appear there.
* **Original RFC**: https://rust-lang.github.io/rfcs/3309-style-team.html
* **Charter**: https://github.com/rust-lang/style-team/blob/HEAD/charter.md
## Style Guide Evolution
The Rust style guide will generally match the latest version of the Rust style; the style team does not plan to maintain multiple branches of the style guide for different editions, in part because formatting for new constructs will apply to any edition supporting those constructs.
Whenever possible, style decisions should be made before a new construct is stabilized. However, style decisions shall not be considered a blocker for stabilization.
## Policy Review Process
To maintain the effectiveness and relevance of our policies, the style team implements a policy review process. The following guidelines outline how we conduct policy reviews:
1. **Associated Review Dates**: Each policy should have a designated review date documented alongside the policy. These review dates are also added to the team's backlog for easy tracking and planning.
2. **Consideration Factors**: When selecting review dates for policies, we consider several factors. These include:
1. **Confidence Level**: If a policy has recently changed or is relatively new, we opt for a shorter review period. This allows us to course correct quickly if needed.
2. **Stability and Effectiveness**: Policies that have remained unchanged for a considerable period and have proven effective can have longer review periods. This prevents unnecessary time spent on policies that are working well.
3. **Integration into Regular Meetings**: Policy reviews are treated as regular agenda items during our team meetings. They are discussed and evaluated alongside other topics of importance.
4. Review Process: Policy reviews should use a discussion approach that encourages each team member to provide feedback regarding the policy under review and creates a constructive environment where everyone is heard equally. Our current process is a *round*, in which each person is heard once before anyone responds or chimes in a second time. We start with the prompt, "How effective has this policy been in your experience? Is it serving its intended purpose? How has it worked well, and how can it be improved? Are there other issues with the policy that we should consider?".
5. **Regular Review Cadence**: We review our policies regularly to identify any issues before they escalate into urgent problems proactively. By conducting these reviews systematically, we ensure that our policies remain up-to-date and aligned with our evolving needs.
1. **Default disposition**: In organizations without a policy review process, policies often remain in effect by default until explicitly rescinded. The policy review process partly reverses that default disposition: policies require regular review and must be renewed to remain in effect. (Such review and renewal still consider all of these other factors, such as the degree of previously established confidence in the policy and its stability over time.)
By adhering to this policy review process, we aim to maintain a high standard of quality and relevance in our style team policies.
## Operational Roles
The style team has various operational roles to delegate related and ongoing work to specific individuals, to clarify on our operations, and to coordinate sharing feedback with the members in those roles to enable iterative self improvement.
### Operational Lead
* Current Holder: [@calebcartwright](https://github.com/calebcartwright)
* Next Feedback Date: TODO
In order to stay in touch with where we want to be heading in the future, we need leadership. A team leader is paying attention to the team’s operations in relation to the team’s aim. What needs to be done, who agreed to do it. What is in the future to decide?
Responsibilities:
* Pays attention to the operation of the team
* Pays attention to the team members
* Reports wider context to the team
### Facilitator
* Current Holder: [@yaahc](https://github.com/yaahc)
* Next Feedback Date: Wednesday 2023-02-01
In order to be present with each other, we need a good facilitator. The facilitator runs meetings according to the format of meetings and decision making adopted by the group. Leader and facilitator are separate roles because facilitation and overseeing operations are different skill sets. They can be held by the same individual.
Responsibilities:
* Facilitates team meetings.
* Pays attention to equivalence[^5] during meetings.
* Supports planning of the agenda.
* Distinguishes facilitator voice from team member voice.
### Scribe
* Current Holder: [@calebcartwright](https://github.com/calebcartwright)
* Next Feedback Date: TODO
In order to manage continuity with the team’s past, we need to have written records. The scribe manages the notes during the meeting, makes sure the minutes are distributed and accessible.
Responsibilities:
* Makes sure meeting minutes are taken, approved, and stored.
* Keeps track of all documents of the team.
* Default interpreter of meeting minutes in cases of disagreement.
* Supports planning the agenda from the backlog.
* Tracking when policies and roles are due for review.
## Meetings
The style team meets weekly on Wednesdays at 12:30pm PST [(everytimezone link)](https://everytimezone.com/s/3f88a253) for a weekly video sync. Agendas are posted in the #T-style zulip stream.
Unless otherwise noted, all of our meetings are public and open for anyone to attend. You will find the timing and event details on our [style team calendar](https://calendar.google.com/calendar/embed?src=d0564ed914a41cf4915bd5ebe6e2e4ec0ee1293fdc1d09d6f5bdb27d4f91c083%40group.calendar.google.com&ctz=America%2FLos_Angeles). We publish notes and minutes in written form in this github repository.
### Agenda, Backlog, and Minutes
The style team stores its agendas, backlog, and meeting minutes in a single live hackmd document (rotating as necessary when the documents reach their length limit).
The agenda should be prepared in advanced of each meeting by the facilitator with the assistance of the scribe and the lead. The lead is responsible for looking forward and adding agenda items such as new requests from other teams and users or new priorities and goals. The scribe is responsible for looking backwards and adding agenda items from existing work such as items from the backlog or policies that are due for review. The agenda proposal is then presented at the beginning of each meeting by the facilitator for the rest of the team to consent or object too.
Consent not needed to add to items to the backlog, anybody is welcome to add items to the backlog, but consent needed to move from backlog to agenda (since agendas themselves require consent). An item being present on the backlog does not represent a commitment by the style team.
#### Interrupting the Agenda
The style team acknowledges that urgent needs may arise during the meeting. To address these needs, participants may interrupt the meeting by speaking up and immediately saying "Point of Order." This signals to the meeting facilitator and other participants that the following point is not an out-of-order interruption but rather an urgent need that must take priority. This tool is designed for meta-level concerns that take priority over the current discussion, such as the scribe interrupting the meeting to address issues preventing the recording of minutes (and stopping the discussion until they can resume recording minutes), or a team member interrupting a discussion to raise questions of time bounds or team scope.
The meeting facilitator will then pause the current discussion, allow the participant to raise the point of order to state their concern and allow the team to address that point of order. After resolving the urgent matter, the facilitator will resume the previous discussion or return to the agenda. This policy is intended to ensure that the team can address urgent issues promptly without unnecessarily interrupting the flow of the meeting.
#### Inform / Explore / Decide agenda item classification
Agenda items are labeled according to their desired outcome. There are three possible outcomes for any given agenda item, inform, explore, or decide. Each of these outcomes builds upon the previous outcomes. In order to explore an item it must first be understood, and in order to make a decision one must both understand and explore the item first. Inform is used for things such as status updates, and usually involves first a report, followed by a round of clarifying questions. Explore is used for situations where one would like feedback on a potential issue or proposal, and usually involves reaction rounds. Decide is used when the team must reach a decision as a group, and it is usually achieved via a consensus round.
We identify the desired outcome in advance to avoid aimless discussions with unclear goals. The desired outcome can change during discussion as new information becomes available. It is the facilitator's responsibility to notice when this happens and formally make the change in the desired outcome with consent from the rest of the team. Extra clarity can be gained if, for every agenda item, we end by measuring whether we have achieved the desired outcome. Facilitators can make it a habit to pause before moving to a new agenda item by assessing whether the desired outcome has been achieved and by asking the scribe to read out loud what has been written in the notes.
The agenda backlog and minutes document is structured according to the following template:
```md
# T-style Minutes
Meeting Link:
## Action Items
### Pending
* owner: bullet point list of items that are in progress and assigned to a specific person
### Completed
- [ ] owner: check list of items that are completed or assumed to be complete
- [x] owner: items are checked off once they've been reviewed in a meeting, confirmed complete, and given any relevant final status updates.
- [x] owner: after a meeting the items that were checked off are moved into the `#### Completed Action Items` section of the meeting they were reviewed in by the scribe
### Granularity
Action items should not generally list individual feedback/response comments within GitHub threads. An action item should generally be at the level of a GitHub PR, and people can look at the GitHub PR to find out its current status. That status may affect whether the action item is blocked, or who needs to look at it, or whether there are aspects of the action item to discuss in a meeting.
## Backlog
* Bullet point list of items that have not been started or assigned yet
## Next Meeting Date
### Attendance
### Agenda
* (inform) bullet point list of proposed agenda items (labeled either inform, explore, or decide)
* Review Action Items
* Meeting Check-out
* Do not record in minutes, exceptions can be made with consent of team
### Minutes
#### Individual Agenda Items
Notes related to the given agenda item
#### Completed Action Items
## Previous Meeting Dates <repeats>
```
### Meeting Check-out
The style team wraps up the content part of our meetings 5-10 minutes before team members have to leave to make room for regular meeting evaluations. Meeting evaluations are an integral part of every meeting. We end the meeting with one or two rounds on:
* “What worked well in the meeting?”
* “What could be improved in future meetings?”
* “Is there anything you are carrying out of the meeting that you’d like to get off your chest now?”
Meeting evaluations are an opportunity to learn from our meetings. We can either talk about content, process, or interpersonal dynamics. We utilize meeting evaluations to help ourselves inhabit a growth mindset. Our goal is to have meetings which are well-run, refreshing, connecting, and energizing. We achieve this goal by giving space for people to speak up about both the positive and negative aspects of how we're working together so that we can prioritize continuous improvement and positive connections.
Meeting check-outs are considered private and internal to the style team and are not recorded as part of our minutes. Exceptions to this can be made via an operational consent decision by the team, and are often useful in cases such as when new backlog or action items come up during the check-out.
[Style Guide]: https://github.com/rust-lang/rust/tree/HEAD/src/doc/style-guide/src
[#T-style]: https://rust-lang.zulipchat.com/#narrow/stream/346005-t-style
[^1]: https://rust-lang.github.io/compiler-team/
[^2]: https://lang-team.rust-lang.org/
[^3]: https://std-dev-guide.rust-lang.org/
[^4]: https://rust-lang.github.io/types-team/
[^5]: Equality, making sure everyone's voices and feedback are receiving equitable attention.
================================================
FILE: triagebot.toml
================================================
[assign]
warn_non_default_branch = true
[assign.owners]
"*" = "style"
gitextract_0pojgh9k/ ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── charter.md ├── example/ │ ├── lists-elided.rs │ ├── lists.rs │ └── rustfmt.toml ├── nightly-style-procedure.md ├── team-policy.md └── triagebot.toml
SYMBOL INDEX (46 symbols across 2 files)
FILE: example/lists-elided.rs
type ListTactic (line 24) | pub enum ListTactic {
type SeparatorTactic (line 40) | pub enum SeparatorTactic {
method from_bool (line 49) | pub fn from_bool(b: bool) -> SeparatorTactic {
type ListFormatting (line 58) | pub struct ListFormatting<'a> {
function format_fn_args (line 70) | pub fn format_fn_args<I>(items: I, width: usize, offset: Indent, config:...
function format_item_list (line 77) | pub fn format_item_list<I>(
function list_helper (line 89) | pub fn list_helper<I>(
type ListItem (line 120) | pub struct ListItem {
method as_ref (line 115) | fn as_ref(&self) -> &ListItem {
method is_multiline (line 132) | pub fn is_multiline(&self) -> bool {
method has_line_pre_comment (line 136) | pub fn has_line_pre_comment(&self) -> bool {
method from_str (line 140) | pub fn from_str<S: Into<String>>(s: S) -> ListItem {
type DefinitiveListTactic (line 152) | pub enum DefinitiveListTactic {
function definitive_tactic (line 158) | pub fn definitive_tactic<I, T>(items: I, tactic: ListTactic, width: usiz...
function write_list (line 183) | pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option...
type ListItems (line 261) | pub struct ListItems<'a, I, F1, F2, F3>
type Item (line 282) | type Item = ListItem;
method next (line 284) | fn next(&mut self) -> Option<Self::Item> {
function itemize_list (line 290) | pub fn itemize_list<'a, T, I, F1, F2, F3>(
function needs_trailing_separator (line 318) | fn needs_trailing_separator(
function calculate_width (line 330) | fn calculate_width<I, T>(items: I) -> (usize, usize)
function total_item_width (line 338) | fn total_item_width(item: &ListItem) -> usize {
function comment_len (line 342) | fn comment_len(comment: Option<&str>) -> usize {
FILE: example/lists.rs
type ListTactic (line 24) | pub enum ListTactic {
type SeparatorTactic (line 40) | pub enum SeparatorTactic {
method from_bool (line 49) | pub fn from_bool(b: bool) -> SeparatorTactic {
type ListFormatting (line 58) | pub struct ListFormatting<'a> {
function format_fn_args (line 70) | pub fn format_fn_args<I>(items: I, width: usize, offset: Indent, config:...
function format_item_list (line 83) | pub fn format_item_list<I>(
function list_helper (line 95) | pub fn list_helper<I>(
type ListItem (line 126) | pub struct ListItem {
method as_ref (line 121) | fn as_ref(&self) -> &ListItem {
method is_multiline (line 138) | pub fn is_multiline(&self) -> bool {
method has_line_pre_comment (line 145) | pub fn has_line_pre_comment(&self) -> bool {
method from_str (line 151) | pub fn from_str<S: Into<String>>(s: S) -> ListItem {
type DefinitiveListTactic (line 163) | pub enum DefinitiveListTactic {
function definitive_tactic (line 169) | pub fn definitive_tactic<I, T>(items: I, tactic: ListTactic, width: usiz...
function write_list (line 204) | pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option...
type ListItems (line 348) | pub struct ListItems<'a, I, F1, F2, F3>
type Item (line 369) | type Item = ListItem;
method next (line 371) | fn next(&mut self) -> Option<Self::Item> {
function itemize_list (line 476) | pub fn itemize_list<'a, T, I, F1, F2, F3>(
function needs_trailing_separator (line 504) | fn needs_trailing_separator(
function calculate_width (line 516) | fn calculate_width<I, T>(items: I) -> (usize, usize)
function total_item_width (line 527) | fn total_item_width(item: &ListItem) -> usize {
function comment_len (line 533) | fn comment_len(comment: Option<&str>) -> usize {
Condensed preview — 10 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (63K chars).
[
{
"path": "LICENSE-APACHE",
"chars": 9723,
"preview": " Apache License\n Version 2.0, January 2004\n http"
},
{
"path": "LICENSE-MIT",
"chars": 1023,
"preview": "Permission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentati"
},
{
"path": "README.md",
"chars": 1574,
"preview": "# Rust style team repository\n\nThis is the home of the [Rust style team](https://www.rust-lang.org/governance/teams/lang#"
},
{
"path": "charter.md",
"chars": 5794,
"preview": "# Style Team\n\n## Aims: Evolving the Rust Style over time\n\n1. Defining the style for new Rust constructs\n2. Evolving the "
},
{
"path": "example/lists-elided.rs",
"chars": 10010,
"preview": "// Copyright 2015 The Rust Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distribution"
},
{
"path": "example/lists.rs",
"chars": 17797,
"preview": "// Copyright 2015 The Rust Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distribution"
},
{
"path": "example/rustfmt.toml",
"chars": 140,
"preview": "fn_args_layout = \"Block\"\narray_layout = \"Block\"\ncontrol_style = \"Rfc\"\nwhere_style = \"Rfc\"\ngenerics_indent = \"Block\"\nfn_c"
},
{
"path": "nightly-style-procedure.md",
"chars": 2202,
"preview": "The style guide may or may not prescribe formatting behavior for nightly syntax\nin the \"nightly\" chapter in preparation "
},
{
"path": "team-policy.md",
"chars": 13152,
"preview": "# Style Team Policy Document\n\nThis is a living document tracking the active policies of the style team. It is intended t"
},
{
"path": "triagebot.toml",
"chars": 71,
"preview": "[assign]\nwarn_non_default_branch = true\n\n[assign.owners]\n\"*\" = \"style\"\n"
}
]
About this extraction
This page contains the full source code of the rust-lang-nursery/fmt-rfcs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 10 files (60.0 KB), approximately 13.7k tokens, and a symbol index with 46 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.