Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I parse/save header/comment correctly? #53

Closed
re-ovo opened this issue Feb 6, 2022 · 6 comments
Closed

How can I parse/save header/comment correctly? #53

re-ovo opened this issue Feb 6, 2022 · 6 comments

Comments

@re-ovo
Copy link

re-ovo commented Feb 6, 2022

Suppose I have a yaml config:

# Example Config
# Generated by {version}

# check update
check_update: true

# another option
option: 1

yaml.option().header() will return:

# Example Config
# Generated by {version}

# check update

This is obviously not what I need 🤔

yaml.getComment("check_update") also returns

# Example Config
# Generated by {version}

# check update

Is there any way to separate them?

@re-ovo
Copy link
Author

re-ovo commented Feb 6, 2022

Also, when I get/set a comment, the empty comment lines and blank lines are removed, is there any way to keep it?

For example:

after use

  yaml.setComment("option", "New Comment")

the config will become:

# Example Config
# Generated by {version}

# check update
check_update: true
# New Comment
option: 1

Apparently, the blank line above New Comment was removed.

Also, it also strips my comment formatting, for example:

############### Example #####################
#
# Test
#
###########################################

it will become:

# Example
# Test

@re-ovo re-ovo changed the title How can I parse/save header correctly? How can I parse/save header/comment correctly? Feb 6, 2022
@Carleslc
Copy link
Owner

Carleslc commented Feb 6, 2022

Currently, the header is considered to be the block comment of the first entry (root), without stripping #. But I guess you need the header to be something like all comments before the first blank line.

You can get the header you want with something like:

yaml.options().header().split("\n\n")[0]

The current header behaviour is mostly the same as the original Bukkit YamlConfiguration. But maybe some rework can be done to achieve this most intuitive behaviour.

@re-ovo
Copy link
Author

re-ovo commented Feb 6, 2022

Currently, the header is considered to be the block comment of the first entry (root), without stripping #. But I guess you need the header to be something like all comments before the first line without a comment prefix #.

You can get the header you want with something like:

yaml.options().header().split("\n(?!#)")[0]

The current header behaviour is mostly the same as the original Bukkit YamlConfiguration. But maybe some rework can be done to achieve this most intuitive behaviour.

thanks, how about the comment issue?

@Carleslc
Copy link
Owner

Carleslc commented Feb 6, 2022

I think it is not possible at the moment to add blank lines along with a comment programmatically. Current blank lines that exist in the file will be preserved untouched, but if you use setComment to add comments the formatting is still something to work on.

Currently, the formatted comments like the one you provide are supposed to be written on the default file manually and not programmatically using setComment method, as they will not be modified.

You can set blank lines as a comment with yaml.setComment("option", "\n"), but if you include the \n character along with text:

yaml.setComment("option", "\nNew Comment");

The output will be:

# Example Config
# Generated by {version}

# check update
check_update: true
#
# New Comment
option: 1

If the comment begins with a \n it would need to be a blank line to achieve what you're trying to do. It is a presentation detail, but given that comments need some fixes as stated in #42 then probably this will be added too.

Currently adding a \n character in a comment is to write multi-line comments (#39):

yaml.setComment("option", "One line\nAnother line");
# Example Config
# Generated by {version}

# check update
check_update: true
# One line
# Another line
option: 1

getComment will give you those comments without the # character, and this is ok for the comment prefixes above because they have no real meaning in the comment content, but if the text contains # then they would need to be preserved, and currently they are stripped away. It is a known bug and this is something that will change in the next release.

@Carleslc Carleslc added this to Next release (1.7.4) in Roadmap Feb 6, 2022
@Carleslc Carleslc removed this from No planned release in Roadmap Mar 18, 2022
@Carleslc
Copy link
Owner

The 1.8 release includes a comment formatting feature useful to control how you want to format and retrieve comments.
Also, the header behaviour changed, and now it is separated from the first key comment by the first blank line found.

This is how to do what you want after upgrading:

// Create YamlFile with relative path
final YamlFile yamlFile = new YamlFile("issue-53.yml");

// Load file with comments
try {
    yamlFile.createOrLoadWithComments();
} catch (IOException e) {
    e.printStackTrace();
}

// Set header format
yamlFile.options().headerFormatter()
        .prefixFirst("############### Example #####################\n#")
        .suffixLast("\n#\n#############################################");

// Set header
yamlFile.options().header("Example Config\nGenerated by {version}");

// Set comment formatter
// DEFAULT (unset) does not add any blank line
// PRETTY will add a blank line above comments at root keys (those with indent 0)
yamlFile.setCommentFormat(YamlCommentFormat.PRETTY);

// Add values along with comments using the alternative API (path method)
yamlFile.path("check_update").set(true).comment("check update");

yamlFile.path("option").set(1).comment("another option");

// Get header
System.out.println("Header without format: \n\n" + yamlFile.options().header());
System.out.println();
System.out.println("Header with format: \n\n" + yamlFile.getHeader());
System.out.println();

// Get first comment
System.out.println("check_update comment: " + yamlFile.getComment("check_update"));

// Save file
try {
    yamlFile.save();
} catch (IOException e) {
    e.printStackTrace();
}

Output

Header without format: 

Example Config
Generated by {version}

Header with format: 

############### Example #####################
#
# Example Config
# Generated by {version}
#
#############################################

check_update comment: check update

issue-53.yml

############### Example #####################
#
# Example Config
# Generated by {version}
#
#############################################

# check update
check_update: true

# another option
option: 1

Another way to set blank lines (explicitly):

// Create YamlFile with relative path
final YamlFile yamlFile = new YamlFile("issue-53-2.yml");

// Load file with comments
try {
    yamlFile.createOrLoadWithComments();
} catch (IOException e) {
    e.printStackTrace();
}

// If no comment format is set, it is equivalent to:
// yamlFile.setCommentFormat(YamlCommentFormat.DEFAULT);

// Add some values
yamlFile.set("option-1", 1);
yamlFile.set("option-2", 2);
yamlFile.set("nested.option-3", 3);
yamlFile.set("nested.option-4", 4);

// This does not add any blank line (DEFAULT format)
yamlFile.setComment("option-1", "DEFAULT Comment");

// If each comment line is prefixed with # then the default formatter is ignored (RAW format)
yamlFile.setComment("option-2", "\n# RAW Comment");

// Add a blank line without comment
yamlFile.setBlankLine("nested");

// This is a multiline comment, both lines with # prefix (DEFAULT format)
yamlFile.setComment("nested.option-3", "\nDEFAULT Comment with new line");

// This will add a blank line above (BLANK_LINE format)
yamlFile.setComment("nested.option-4", "BLANK_LINE Comment", YamlCommentFormat.BLANK_LINE);

// Save file
try {
    yamlFile.save();
} catch (IOException e) {
    e.printStackTrace();
}

issue-53-2.yml

# DEFAULT Comment
option-1: 1

# RAW Comment
option-2: 2

nested:
  # 
  # DEFAULT Comment with new line
  option-3: 3
  
  # BLANK_LINE Comment
  option-4: 4

More information:

Another example with custom comment formatting with custom prefix and suffix:

@Carleslc
Copy link
Owner

I'm closing this issue as I think is resolved. If you have any question or encounter a related problem with this issue feel free to ask or reopen it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants