Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions cli/src/commands/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ pub fn fmt() -> Command {
)
}

pub fn exec_fmt(args: &ArgMatches, main_config: FormatConfig) -> anyhow::Result<()> {
pub fn exec_fmt(
args: &ArgMatches,
main_config: FormatConfig,
) -> anyhow::Result<()> {
let files = args.get_many::<PathBuf>("FILE").unwrap();
let check = args.get_flag("check");
let config_file = args.get_one::<PathBuf>("config");
Expand All @@ -40,7 +43,8 @@ pub fn exec_fmt(args: &ArgMatches, main_config: FormatConfig) -> anyhow::Result<
.align_metadata(config.meta.align_values)
.align_patterns(config.patterns.align_values)
.indent_section_headers(config.rule.indent_section_headers)
.indent_section_contents(config.rule.indent_section_contents);
.indent_section_contents(config.rule.indent_section_contents)
.indent_spaces(config.rule.indent_spaces);
let mut changed = false;

for file in files {
Expand Down
86 changes: 85 additions & 1 deletion docs/YARA-X Config Guide.md
Original file line number Diff line number Diff line change
@@ -1 +1,85 @@
# XXX: Add docs on how config file works.
YARA-X Config Guide
===================

YARA-X uses a configuration file for controlling the behavior of different
commands. It currently supports the fmt command, but others will be added in the
future.

The `yr` command looks in `${HOME}/.yara-x.toml` when starting up. If that file
does not exist the default values are used.

An example `.yara-x.toml` file is below, with comments that explain each option.
This is the definitive list of supported configuration options, and will be
updated as more are added.

```toml
# Config file for YARA-X.

# Any options that are not valid are ignored. However, valid keys with an
# invalid type will cause a parsing error. For example, if you set
# rule.indent_spaces to false, it will result in a parsing error.
pants = false # Invalid keys are ignored.

# The configuration of the "fmt" subcommand can be controlled by options in the
# "fmt" section. Each line is a key-value pair where the key uses a dot notation
# to deliniate different options. The "rule" namespace are for options that
# apply to the rule as a whole, while the "meta" and "patterns" namespaces are
# for options that only apply to those sections in a rule.
[fmt]
# Indent section headers so that:
#
# rule a {
# condition:
# true
# }
#
# Becomes:
#
# rule a {
# condition:
# true
# }
rule.indent_section_headers = true

# Indent section contents so that:
# rule a {
# condition:
# true
# }
#
# Becomes:
#
# rule a {
# condition:
# true
# }
rule.indent_section_contents = true

# Number of spaces to use for indentation. Setting this to 0 will use one tab
# character per level of indentation. To disable indentation entirely use
# rule.indent_section_headers and rule.indent_section_contents
rule.indent_spaces = 2

# Align metadata values so that:
#
# rule a {
# meta:
# key = "a"
# long_key = "b"
# }
#
# Becomes:
#
# rule a {
# meta:
# key = "a"
# long_key = "b"
# }
#
# Note that alignment is done with spaces, regardless of rule.indent_spaces
# setting.
meta.align_values = false

# Same as meta.align_values but applies to patterns.
patterns.align_values = false
```
21 changes: 16 additions & 5 deletions fmt/src/indentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,21 @@ where
{
input: T,
indent_level: i16,
num_spaces: u8,
output_buffer: VecDeque<Token<'a>>,
}

impl<'a, T> AddIndentationSpaces<'a, T>
where
T: TokenStream<'a>,
{
pub fn new(input: T) -> Self {
Self { input, indent_level: 0, output_buffer: VecDeque::new() }
pub fn new(input: T, num_spaces: u8) -> Self {
Self {
input,
indent_level: 0,
num_spaces: num_spaces,
output_buffer: VecDeque::new(),
}
}
}

Expand Down Expand Up @@ -52,9 +58,14 @@ where
Token::Newline => {
self.output_buffer.push_back(Token::Newline);
for _ in 0..self.indent_level {
// Indent with two spaces per level
self.output_buffer.push_back(Token::Whitespace);
self.output_buffer.push_back(Token::Whitespace);
if self.num_spaces == 0 {
self.output_buffer.push_back(Token::Tab);
} else {
for _ in 0..self.num_spaces {
self.output_buffer
.push_back(Token::Whitespace);
}
}
}
return self.output_buffer.pop_front();
}
Expand Down
14 changes: 12 additions & 2 deletions fmt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ pub struct Formatter {
align_patterns: bool,
indent_section_headers: bool,
indent_section_contents: bool,
indent_spaces: u8,
}

impl Default for Formatter {
Expand All @@ -84,6 +85,7 @@ impl Formatter {
align_patterns: true,
indent_section_headers: true,
indent_section_contents: true,
indent_spaces: 2,
}
}

Expand Down Expand Up @@ -223,6 +225,14 @@ impl Formatter {
self
}

/// Number of spaces to indent, if indenting at all. Set to 0 to use tabs.
///
/// The default is `2`.
pub fn indent_spaces(mut self, n: u8) -> Self {
self.indent_spaces = n;
self
}

/// Reads YARA source code from `input` and write it into `output` after
/// formatting.
///
Expand Down Expand Up @@ -556,7 +566,7 @@ impl Formatter {
let tokens = FormatHexPatterns::new(tokens);

let tokens: Box<dyn Iterator<Item = Token<'a>>> =
if self.indent_section_headers{
if self.indent_section_headers {
Box::new(Self::indent_body(tokens))
} else {
Box::new(tokens)
Expand Down Expand Up @@ -619,7 +629,7 @@ impl Formatter {
processor::actions::copy,
);*/

let tokens = AddIndentationSpaces::new(tokens);
let tokens = AddIndentationSpaces::new(tokens, self.indent_spaces);
let tokens = RemoveTrailingSpaces::new(tokens);

tokens
Expand Down
5 changes: 5 additions & 0 deletions fmt/src/tokens/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ pub(crate) enum Token<'a> {
// Non-control tokens
//
Whitespace,
#[allow(dead_code)]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@plusvic I'm not sure this is the right way to do this.

Tab,
Comment(&'a [u8]),

BlockComment(Vec<Vec<u8>>),
Expand Down Expand Up @@ -251,6 +253,7 @@ impl<'a> Token<'a> {
}
Token::Indentation(..) => categories::BaseCategory::Indentation,
Token::Whitespace => categories::BaseCategory::Whitespace,
Token::Tab => categories::BaseCategory::Whitespace,
Token::Comment(..)
| Token::BlockComment(..)
| Token::TailComment(..)
Expand Down Expand Up @@ -291,6 +294,7 @@ impl<'a> Token<'a> {
pub fn as_bytes(&self) -> &'a [u8] {
match self {
Token::Whitespace => b" ",
Token::Tab => b"\t",
Token::Newline => b"\n",
Token::Identifier(s)
| Token::Keyword(s)
Expand Down Expand Up @@ -420,6 +424,7 @@ pub(crate) trait TokenStream<'a>: Iterator<Item = Token<'a>> {
col_num = 0;
}
Token::Whitespace
| Token::Tab
| Token::Comment(_)
| Token::Identifier(_)
| Token::Keyword(_)
Expand Down
3 changes: 3 additions & 0 deletions lib/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ pub struct Rule {
pub indent_section_headers: bool,
/// Indent section contents one level past section headers.
pub indent_section_contents: bool,
/// Number of spaces for indent. Set to 0 to use tabs.
pub indent_spaces: u8,
}

/// Meta specific formatting information.
Expand All @@ -53,6 +55,7 @@ impl Default for Config {
rule: Rule {
indent_section_headers: true,
indent_section_contents: true,
indent_spaces: 2,
},
meta: Meta { align_values: true },
patterns: Patterns { align_values: true },
Expand Down
Loading