0

Given the following configuration file:

    shape {
        visible: true
        type: rectangle
        ...
    }
    
    shape {
        type: circle
        visible: isRound === "true"
        ...
    }
    
    shape {
        // comment: "visible" not set, default "true" 
    }

How to set using bash all the values for visible key (property) to false, without touching the comments, but keeping the old value as a comment? The new content should be:

    shape {
        visible: false
        type: rectangle
        ...
    }
    
    shape {
        type: circle
        visible: false // visible: isRound === "true"
        // ideally, above, the old value is kept as a comment...
        ...
    }
    
    shape {
        visible: false
        // comment: "visible" not set, default "true" 
    }

The file is not just a list of shape structures, may contain other entries too. This should be QML compliant.

awk shows:

awk --version
GNU Awk 5.2.1, API 3.2
Copyright (C) 1989, 1991-2022 Free Software Foundation.

Edit

I think I can use this PCRE regex:

(\s*shape\s*\{\n)(\s*)(.*?)(visible\:.*\n?)?(.*?)(\n\s*\})

with replace expression as:

$1$2visible: false // $4\n$2$5$6

or

\1\2visible: false // \4\n\2\5\6

but I need a tool to apply it. It is not perfect, still needs to not comment twice.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
mike
  • 123
  • 6
  • Please, add expected output – Gilles Quénot Feb 19 '23 at 15:44
  • And tell us if you need to not replace what is in comments `//` and `/* */` – Gilles Quénot Feb 19 '23 at 15:57
  • It would have been interesting to have the example output since the beginning =) – Gilles Quénot Feb 19 '23 at 16:04
  • Well, I try to put it simple. My apologies if I have mislead. – mike Feb 19 '23 at 16:08
  • You should specify which kind of language is it, looks like `CSS`. If then, add the proper tag by editing your post. – Gilles Quénot Feb 19 '23 at 21:24
  • You say that tho output should be valid QML. Given that the _input_ is not valid QML, are you expecting an answer that _corrects_ the given file? If the input is valid QML, have you attempted to use the `qml` utility in Qt5 to do these modifications? – Kusalananda Feb 26 '23 at 11:35
  • It is a snapshot of it, indeed those would be contained in an `Container {}` construct, I do not intend to develop something, just set some values as OS admin at some point. – mike Feb 26 '23 at 12:41

2 Answers2

2

I'd use perl for this kind of thing:

perl -0777 -pe '
  s{shape\s*\{.*?\}}{
    $& =~ s{(//.*)|\b(visible:\s*+)(?!true\s*$).*}{$1 ? $1 : "${2}true // $&"}gmre
  }gse' your-file
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
1
awk -v key='visible:' -v value='false' '
    /{/ {
        found=0 # reset flag
    }
    $1==key {
        found=1 # set flag
        
        # change true to value
        if ($2=="true") { sub($2, value, $0) }

        # if not value, replace property with key-value and comment
        else if ($2!=value) { sub($1, $1 " " value " // " $1, $0) }
    }
    /}/ && !found {
        # get indentation of }
        indent=$0; sub(/}.*/, "", indent)
        
        # insert property
        print indent indent key " " value
    }
    { print }
' file

There must not be any other opening { or closing } in your properties/comments or the insertion won't work. They must also occur on separate lines.

A missing property is inserted before the closing } and the indentation is set to two times the indentation of }. I'm not sure if this will be always correct or how to determine it (two tabs?).

If a property already has the right value, it is left untouched.

If you don't want to repeat the property name in comments, change the command to sub($1, $1 " " value " //", $0). The result would be visible: false // isRound === "true".

Output:

    shape {
        visible: false
        type: rectangle
        ...
    }
    
    shape {
        type: circle
        visible: false // visible: isRound === "true"
        ...
    }
    
    shape {
        // comment: "visible" not set, default "true" 
        visible: false
    }
Freddy
  • 25,172
  • 1
  • 21
  • 60
  • Consider this inline CSS example: `div .class{ property: 1; visible: false }` it will fails – Gilles Quénot Feb 19 '23 at 20:12
  • I don't know what kind of "configuration file" this is, but it's not CSS (no `;` and `//` comments are not allowed). I only fear the config is nested. – Freddy Feb 19 '23 at 20:22
  • This code is absolutely valid `CSS`. See https://www.w3schools.com/CSS/css_howto.asp And `//` and `;` are allowed for sure – Gilles Quénot Feb 19 '23 at 20:32
  • @GillesQuénot OPs "configuration file" has no semicolons, it would be broken CSS. And `//`-style comments are not allowed in CSS (see [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/CSS/Comments), or [here](https://www.w3.org/TR/css-syntax-3/#comment-diagram)). – Freddy Feb 19 '23 at 21:00
  • So OP CSS and what you edit with `awk` is broken so(?). There's `//` both in answer and question – Gilles Quénot Feb 19 '23 at 21:11
  • @GillesQuénot Again, I don't know what kind of input that is. Ask OP. – Freddy Feb 19 '23 at 21:20
  • Think the syntax is QML. – mike Feb 26 '23 at 10:12
  • The above works to add in any section, regardless it is `shape` or not. – mike Mar 02 '23 at 18:40