├── FAQs_And_FUQs.md ├── LICENSE.md ├── CHANGELOG.md ├── README.md └── tasker_config_utils /FAQs_And_FUQs.md: -------------------------------------------------------------------------------- 1 | ### Frequently Asked Questions(FAQs) 2 | 3 | `-` 4 | ## 5 | 6 | 7 | ### Frequently Unasked Questions(FUQs) 8 | 9 | `-` 10 | ## 11 | 12 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019, agnostic-apollo, auth={ type=`scrypt-kdf`, key=`xY%I5l>AxK+n@o.]cjUp8&s2.NyFBr=&]PoMxQ5B-W(T)e+d(lDT*I7u=jjFK-UA-IA-BA` } 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | **Version Number Format:** `major.minor.patch` 6 | **Release Date Format:** `yyyy-mm-dd` 7 | 8 | **Types of Changes:** 9 | - **Added** for new features. 10 | - **Changed** for changes in existing functionality. 11 | - **Deprecated** for soon-to-be removed features. 12 | - **Removed** for now removed features. 13 | - **Fixed** for any bug fixes. 14 | - **Security** in case of vulnerabilities. 15 | ## 16 | 17 | 18 | ## [Unreleased] 19 | 20 | `-` 21 | 22 | 23 | ## [0.5.0] - 2020-11-11 24 | 25 | ### Added 26 | - Added support for creating `.sha256sums` file for config xml and info files for `generate_config_info` command using `-m` and `--sha256sums_file` options. This will allow for integrity verification of the config info file as well, specially since it now contains code description. 27 | 28 | ### Removed 29 | - Removed `sha256sums` tag from config info file for `generate_config_info` command if `-m` is not passed. 30 | 31 | 32 | ## [0.4.0] - 2020-11-09 33 | 34 | ### Added 35 | - Added support for text and code descriptions for `generate_config_info` command using `--text_description` and `--code_description` options. 36 | 37 | 38 | ## [0.3.0] - 2020-11-06 39 | 40 | ### Added 41 | - Added support for printing entire nodes instead of just tags for `extract_tag` command with `-n` and `--nodes_print_command` options. 42 | - Added support to add `tasker_config_utils` script signature at end of output file for `generate_config_info` command with the `-s` option. 43 | 44 | ### Changed 45 | - Changed `generate_config_info` default behaviour of for task help anchor labels.The labels must be in markdown from now on and will not be put in a code block unless `-c` is passed. 46 | 47 | ### Removed 48 | - Removed separate `Comments` and `Control` section from output of `generate_config_info` command. The help anchor labels should preferably format any sections themselves in markdown. 49 | 50 | 51 | ## [0.2.2] - 2020-09-10 52 | 53 | ### Added 54 | - Added separate `Control` section to output of `generate_config_info` command. 55 | 56 | 57 | ## [0.2.1] - 2020-05-20 58 | 59 | ### Changed 60 | - Changed timestamp to UTC for `generate_config_info` command. 61 | 62 | 63 | ## [0.2.0] - 2020-04-13 64 | 65 | ### Added 66 | - Added sha256sum to output of `generate_config_info` command. 67 | 68 | 69 | ## [0.1.0] - 2020-01-13 70 | 71 | `-` 72 | ## 73 | 74 | 75 | [unreleased]: https://github.com/Taskomater/tasker_config_utils/compare/v0.5.0...HEAD 76 | [0.5.0]: https://github.com/Taskomater/tasker_config_utils/compare/v0.4.0...v0.5.0 77 | [0.4.0]: https://github.com/Taskomater/tasker_config_utils/compare/v0.3.0...v0.4.0 78 | [0.3.0]: https://github.com/Taskomater/tasker_config_utils/compare/v0.2.2...v0.3.0 79 | [0.2.2]: https://github.com/Taskomater/tasker_config_utils/compare/v0.2.1...v0.2.2 80 | [0.2.1]: https://github.com/Taskomater/tasker_config_utils/compare/v0.2.0...v0.2.1 81 | [0.2.0]: https://github.com/Taskomater/tasker_config_utils/compare/v0.1.0...v0.2.0 82 | [0.1.0]: https://github.com/Taskomater/tasker_config_utils/releases/tag/v0.1.0 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tasker_config_utils 2 | 3 | This is a project that provides bash util script(s) to extract information and modify [Tasker App] XML files. Check [Tasker XML Info] for more info on how Tasker App XML files work. 4 | ## 5 | 6 | 7 | ### Contents 8 | - [Compatibility](#Compatibility) 9 | - [Dependencies](#Dependencies) 10 | - [Downloads](#Downloads) 11 | - [Install Instructions For Termux In Android](#Install-Instructions-For-Termux-In-Android) 12 | - [tasker_config_utils Script Usage](#tasker_config_utils-Script-Usage) 13 | - [Current Features](#Current-Features) 14 | - [Planned Features](#Planned-Features) 15 | - [Issues](#Issues) 16 | - [Worthy Of Note](#Worthy-Of-Note) 17 | - [FAQs And FUQs](#FAQs-And-FUQs) 18 | - [Changelog](#Changelog) 19 | - [Contributions](#Contributions) 20 | ## 21 | 22 | 23 | ### Compatibility 24 | 25 | - Android using [Termux App]. 26 | - Linux distros. 27 | - Windows using [cygwin]. 28 | ## 29 | 30 | 31 | ### Dependencies 32 | 33 | - Android users should install [Termux App]. 34 | - Windows users should install [cygwin] and use cygwin shell to run scripts. 35 | - `GNU` variant of `sed` should be installed in your system. 36 | - Termux (non-root shell): `apt install sed` 37 | - Linux distros: `sudo apt install sed` 38 | - Windows: It should ideally be installed by default with cygwin. If not, then run cygwin installer and search package and install. 39 | ## 40 | 41 | 42 | ### Downloads 43 | 44 | Latest version is `v0.5.0`. 45 | 46 | - [GitHub releases](https://github.com/Taskomater/tasker_config_utils/releases). 47 | ## 48 | 49 | 50 | ### Install Instructions For Termux In Android 51 | 52 | The `tasker_config_utils` file should be placed in termux `bin` directory `/data/data/com.termux/files/usr/bin`. 53 | It should have `termux` `uid:gid` ownership and have executable `700` permission before it can be run directly without `bash`. 54 | 55 | 1. Download the `tasker_config_utils` file. 56 | 57 | - Download to termux bin directory directly from github using `curl` using a non-root termux shell. 58 | - Latest release: 59 | 60 | `curl -L 'https://github.com/Taskomater/tasker_config_utils/releases/latest/download/tasker_config_utils' -o "/data/data/com.termux/files/usr/bin/tasker_config_utils"` 61 | 62 | - Specific release: 63 | 64 | `curl -L 'https://github.com/Taskomater/tasker_config_utils/releases/download/v0.1.0/tasker_config_utils' -o "/data/data/com.termux/files/usr/bin/tasker_config_utils"` 65 | 66 | - Master Branch *may be unstable*: 67 | 68 | `curl -L 'https://github.com/Taskomater/tasker_config_utils/raw/master/tasker_config_utils' -o "/data/data/com.termux/files/usr/bin/tasker_config_utils"` 69 | 70 | - Download `tasker_config_utils` file manually from github to the android download directory and then copy it to termux bin directory. 71 | 72 | You can download the `tasker_config_utils` file from a github release from the `Assets` dropdown menu. 73 | 74 | You can also download it from a specific github branch/tag by opening the `tasker_config_utils` file from the `Code` section. 75 | Right-click or hold the `Raw` button at the top and select `Download/Save link`. 76 | 77 | Then copy the file to termux bin directory using `cat` command below or use a root file browser to manually place it. 78 | 79 | `cat "/storage/emulated/0/Download/tasker_config_utils" > "/data/data/com.termux/files/usr/bin/tasker_config_utils"` 80 | 81 | 2. Set `termux` ownership executable permissions. 82 | 83 | - If you used a `curl` or `cat` to copy the file, then use a non-root termux shell to set ownership and permissions with `chown` and `chmod` commands respectively: 84 | 85 | `export termux_bin_path="/data/data/com.termux/files/usr/bin"; export owner="$(stat -c "%u" "$termux_bin_path")"; chown "$owner:$owner" "$termux_bin_path/tasker_config_utils" && chmod 700 "$termux_bin_path/tasker_config_utils";` 86 | 87 | - If you used a root file browser to copy the file, then use `su` to start a root shell to set ownership and permissions with `chown` and `chmod` commands respectively: 88 | 89 | `export termux_bin_path="/data/data/com.termux/files/usr/bin"; export owner="$(stat -c "%u" "$termux_bin_path")"; su -c "chown \"$owner:$owner\" \"$termux_bin_path/tasker_config_utils\" && chmod 700 \"$termux_bin_path/tasker_config_utils\"";` 90 | 91 | - Or manually set them with your root file browser. You can find `termux` `uid` and `gid` by running the command `id -u` in a non-root termux shell or by checking the properties of the termux `bin` directory from your root file browser. 92 | ## 93 | 94 | 95 | ### tasker_config_utils Script Usage 96 | 97 | You may optionally run the script placed in the current directory without setting the ownership and permission by running the command `bash tasker_config_utils`. 98 | If you are not running the script in termux, set the shebang of the script correctly (the first line of the script). 99 | 100 | Any full exported tasker config passed to the script must have been generated using the `Data->Backup` Tasker menu option or the `Data Backup` action. The script will not work with `autobackups` since those contain XML nodes that are collapsed to a single line with no indentations. If you have an `autobackup`, then import that into Tasker and export a backup manually again with one of the ways mentioned earlier. This does not apply for exported project, task, profile or scene files. 101 | 102 | - **`tasker_config_utils`** 103 | 104 | ##### Help: 105 | 106 | ``` 107 | Usage: 108 | tasker_config_utils [ -h | --help ] 109 | tasker_config_utils [ --version ] 110 | tasker_config_utils command [command_options] 111 | 112 | 113 | Available commands: 114 | extract_tag extract tags from tasker config XML file 115 | convert_project convert project into a non-standalone project 116 | generate_config_info generate a markdown config info file for a 117 | given tasker config XML file 118 | 119 | 120 | Use "tasker_config_utils command [ -h | --help ]" for more help about 121 | a command. 122 | ``` 123 | ## 124 | 125 | 126 | - **`tasker_config_utils extract_tag`** 127 | 128 | **`tasker_config_utils extract_tag`** command is used to extract tags of nodes from a tasker config file. 129 | 130 | ##### Help: 131 | 132 | ``` 133 | tasker_config_utils extract_tag command is used to extract tags of 134 | nodes from a tasker config XML file. 135 | 136 | 137 | Usage: 138 | tasker_config_utils extract_tag [command_options] tasker_config 139 | 140 | 141 | Available command_options: 142 | [ -h | --help ] display this help screen 143 | [ -v | -vv ] set verbose level to 1 or 2 144 | [ -a ] extract Project node tag 145 | [ -e ] extract tags from entire node 146 | [ -n ] print entire extracted nodes 147 | [ -p ] extract Profile node tag 148 | [ -s ] extract Task node tag 149 | [ -t ] extract Scene node tag 150 | [ --nodes_print_command= ] 151 | extracted nodes print sed command to 152 | be used with '-n' option 153 | [ --node= ] 154 | node to extract 155 | [ --tag= ] 156 | tag to extract 157 | [ --pre_tag= ] 158 | pre tag sed regex to match while 159 | extracting tag 160 | [ --post_tag= ] 161 | post tag sed regex to match while 162 | extracting tag 163 | 164 | 165 | tasker_config should be the path to a Tasker "Data Backup" XML 166 | file. It must be an exported "Data Backup" and not an auto backup. 167 | 168 | The options '-a', '-p', '-s', '-t' and '--node' set the 169 | extraction_node of the extract_tag command. One of them must 170 | be passed. 171 | 172 | For the option '-a', the default tag is 'name'. For all others, 173 | the default tag is 'nme'. 174 | 175 | By default tags will only be extracted from the node itself and not 176 | any of its sub nodes. Multi-line tags can be extracted. However, 177 | this only allows the first tag of the same type to be extracted 178 | from each node. 179 | 180 | The '-e' option can be passed to extract tags from the node and its 181 | sub nodes. Only single line tags can be extracted. However, this 182 | allows multiple tags of the same type to be extracted from each node. 183 | 184 | The '-n' option will print the entire extracted nodes instead of just 185 | printing the tag. The print mode used by sed can be set using 186 | '--nodes_print_command', it defaults to "p". 187 | 188 | If you are passing '--tag', '--pre_tag' or '--post_tag' options with 189 | the '-e' option, it might be helpful to pass '-vv' for verbose mode 190 | so that the matching nodes can also be printed on the console in 191 | addition to the extracted tag values or use the '-n' option to just 192 | print entire nodes instead of just tags. 193 | 194 | Set verbose level to 1 or 2 to get more info when running 195 | tasker_config_utils extract_tag command. 196 | ``` 197 | 198 | ##### Examples: 199 | 200 | - Extract all profile names. 201 | `tasker_config_utils extract_tag -p "config.xml"` 202 | 203 | - Extract all scene names. 204 | `tasker_config_utils extract_tag -s "config.xml"` 205 | 206 | - Extract all task names. 207 | `tasker_config_utils extract_tag -t "config.xml"` 208 | 209 | - Extract all project names. 210 | `tasker_config_utils extract_tag -a "config.xml"` 211 | 212 | - Extract all task names with "Run Both Together" collision handling. 213 | `tasker_config_utils extract_tag -t --post_tag='2<\/rty>' "config.xml"` 214 | 215 | - Extract all scene names from the project "Base". 216 | `tasker_config_utils extract_tag -a --pre_tag='Base<\/name>' --tag=scenes "config.xml"` 217 | 218 | - Extract all profile, scene and task names from tasker_config. 219 | `tasker_config="config.xml"; echo -e "Profiles:"; tasker_config_utils extract_tag -p "$tasker_config"; echo -e "\nScenes:"; tasker_config_utils extract_tag -s "$tasker_config"; echo -e "\nTasks:"; tasker_config_utils extract_tag -t "$tasker_config";` 220 | 221 | - Extract all task labels, then pipe output to sed to convert XML special characters to ascii. 222 | `tasker_config_utils extract_tag --node='Action' --tag='label' "config.xml" | sed -e 's/&/\&/g' -e 's/<//g'` 223 | 224 | - Extract all task "Anchor" action labels, then pipe output to sed to convert XML special characters to ascii. 225 | `tasker_config_utils extract_tag --node='Action' --pre_tag='300<\/code>' --tag='label' "config.xml" | sed -e 's/&/\&/g' -e 's/<//g'` 226 | 227 | - Extract all task "Anchor" action labels that are first action (act0) of tasks, then pipe output to sed to convert XML special characters to ascii. 228 | `tasker_config_utils extract_tag --node='Action' --pre_tag='sr="act0".*300<\/code>' --tag='label' "config.xml" | sed -e 's/&/\&/g' -e 's/<//g'` 229 | 230 | - Extract all scene tap events anonymous task ids. 231 | `tasker_config_utils extract_tag -s -e --tag='itemclickTask' "config.xml"` 232 | 233 | - Extract all scene anonymous task ids. 234 | `tasker_config_utils extract_tag -s -e --tag='[a-zA-Z0-9]+Task' "config.xml"` 235 | 236 | - Extract profile id of profile using entry task with task id 666 and also print the matching profile nodes. 237 | `tasker_config_utils extract_tag -p -e --tag="id" --post_tag='666<\/mid0>' -vv "config.xml"` 238 | 239 | - Extract all "Java Function" action nodes. 240 | `tasker_config_utils extract_tag -en --node="Action" --tag="-" --post_tag='664<\/code>' "config.xml"` 241 | 242 | - Extract all "Java Function" action nodes and print ending line number. 243 | `tasker_config_utils extract_tag -en --node="Action" --tag="-" --post_tag='664<\/code>' --nodes_print_command='{s/(.*)/\1\n\n/;{=;p;}}' "config.xml"` 244 | ## 245 | 246 | 247 | - **`tasker_config_utils convert_project`** 248 | 249 | **`tasker_config_utils convert_project`** command is used to convert a project into a non-standalone project so that it does not have profiles, scenes and tasks that were originally not in the project in the tasker config. The details on how this works is in the function header of the script. 250 | 251 | The reason why this is needed is because of some issues in the export `Project` XML design. The problem is that say you have 3 projects. project 1 and 2 use common helper profiles, tasks and scenes which are all defined in project 3. Now if you export project 1 and 2 and share it with someone. They will only be able to import project 1 and importing project 2 will fail because when they imported project 1 some or all the helper tasks from project 3 were also imported, now they can't import project 2 because Tasker config already contains tasks with the same name. 252 | 253 | Moreover when project 1 is imported, the tasks from project 1 and 3 are mixed inside the same project. This creates a mess and destroys the purpose of separate projects. 254 | 255 | There should be a way to export projects with only tasks, scenes and profiles referenced inside the same project only. This way each project 1, 2 and 3 can be exported separately and imported separately so that there aren't any conflicts when importing. The temporary missing references would not be that big of a problem as long as the projects containing the missing tasks, scenes and profiles are also imported next. 256 | 257 | Moreover, the order of the profiles and tasks in their respective tabs is not saved when sharing projects, at least currently. The order and id of profiles and tasks belonging to a project is saved in its `Project` node of the Tasker config file in the `` and `` tags respectively. When you export a `Project` XML file, the order is the same as the one in the Tasker config file. But when you import the XML file into a different device, the ids are changed for all profiles and tasks so that there is not any conflict with the ids already existing in the Tasker config of the device. Ideally new ids should be assigned in the same order as they exist in the `Project` XML file but there are not currently resulting in loss of sort order. 258 | 259 | It might be helpful if you upvoted the [Tasker Feature Request](https://tasker.helprace.com/i459-project-export-without-including-profiles-tasks-scenes-from-other-projects) for these issues if you think this is something you would like to have so that support for this can be added directly in Tasker and this potentially unsafe XML modification is not needed. João is already aware of this but its not a high priority feature for him currently. 260 | 261 | ##### Help: 262 | 263 | ``` 264 | tasker_config_utils convert_project command is used to convert a 265 | project into a non-standalone project so that it does not have 266 | profiles, scenes and tasks that were originally not in the project 267 | in the tasker_config. tasker_config must be an exported data backup 268 | and not an auto backup. 269 | 270 | 271 | Usage: 272 | tasker_config_utils convert_project [command_options] tasker_config \ 273 | current_exported_tasker_project new_exported_tasker_project \ 274 | project_name 275 | 276 | 277 | Available command_options: 278 | [ -h | --help ] display this help screen 279 | [ -v | -vv ] set verbose level to 1 or 2 280 | 281 | 282 | tasker_config should be the path to a Tasker "Data Backup" XML 283 | file. It must be an exported "Data Backup" and not an auto backup. 284 | 285 | current_exported_tasker_project should be the path to a Tasker 286 | exported "Project" XML file that needs to be converted. It must 287 | have been exported from Tasker with a config that is the same as 288 | the tasker_config file. 289 | 290 | new_exported_tasker_project should be the path to the output 291 | "Project" XML file. 292 | 293 | project_name should be the Tasker project name which was exported 294 | to current_exported_tasker_project. Its project node must exist 295 | inside both the tasker_config and current_exported_tasker_project 296 | files. Its Project node in the current_exported_tasker_project 297 | should also have a 'sr' value of 'proj0'. 298 | 299 | Set verbose level to 1 or 2 to get more info when running 300 | tasker_config_utils convert_project command. 301 | 302 | 303 | Usage Flow: 304 | Create a Tasker "Data Backup". Example: "config.xml". 305 | Export Tasker "Foo Bar" Project. It should by default be exported to 306 | "Foo_Bar.prf.xml". 307 | Place both files in same directory and run following command: 308 | `tasker_config_utils convert_project -v "config.xml" \ 309 | "Foo_Bar.prf.xml" "Foo_Bar-out.prf.xml" "Foo Bar"` 310 | 311 | Optionally use the "Convert Tasker Project File To Non-Standalone 312 | Project File" task from the "TR_Tasker_Config_Utils" project to 313 | convert a project file or use the 314 | "Export Tasker Project XML Files To Android Storage?" task to 315 | automatically export non-standalone projects. 316 | ``` 317 | 318 | ##### Examples: 319 | 320 | - Convert a project file into a non-standalone project file. 321 | `tasker_config_utils convert_project -v "config.xml" "Foo_Bar.prf.xml" "Foo_Bar-out.prf.xml" "Foo Bar"` 322 | ## 323 | 324 | 325 | - **`tasker_config_utils generate_config_info`** 326 | 327 | **`tasker_config_utils generate_config_info`** command is used to generate a markdown config info file for a given Tasker XML file. 328 | 329 | Generated config info file will contain: 330 | 1) *Export info like tasker version and timestamp.* 331 | 2) *Names of all profiles, scenes and tasks in the config or project.* 332 | 3) *Profiles info like their settings, entry and exit tasks, etc.* 333 | 4) *Tasks info like their settings, the label of the first action of the task if its an anchor action as help, etc.* 334 | 335 | More info will be added later. 336 | 337 | ##### Help: 338 | 339 | ``` 340 | tasker_config_utils generate_config_info command is used to generate 341 | a markdown config info file for a given tasker config XML file. 342 | 343 | Generated config info file will contain: 344 | 1) Export info like tasker version and timestamp. 345 | 2) Names of all profiles, scenes and tasks in the project. 346 | 3) Profiles Info like their settings, entry and exit tasks, etc. 347 | 4) Tasks Info like their settings, the label of the first action of 348 | the task if its an anchor action as task help, etc. 349 | 350 | Usage: 351 | tasker_config_utils generate_config_info [command_options] -a \ 352 | exported_tasker_config exported_tasker_config_info 353 | 354 | tasker_config_utils generate_config_info [command_options] -p \ 355 | exported_tasker_config exported_tasker_config_info project_name 356 | 357 | 358 | Available command_options: 359 | [ -h | --help ] display this help screen 360 | [ --help-extra ] display more help about how this command works 361 | [ -v | -vv ] set verbose level to 1 or 2 362 | [ -a ] extract all info 363 | [ -c ] put task help in a code block 364 | [ -m ] create sha256sums file config xml and info files 365 | [ -p ] extract info of a specific project 366 | [ -s ] add script signature at end of config info file 367 | [ --text_description= ] 368 | text description of config 369 | [ --code_description= ] 370 | code description of config 371 | [ --sha256sums_file= ] 372 | path to sha256sums file 373 | 374 | 375 | The options '-a' and '-p' set the generate_config_info_mode of the 376 | generate_config_info command. One of them must be passed. 377 | 378 | The '-a' option sets the generate_config_info_mode to "all" 379 | mode. If this is passed, then exported_tasker_config can be any 380 | type of exported Tasker XML file like a "Data Backup", "Profile", 381 | "Project", "Task" or a "Scene" XML file of which config info needs to 382 | be generated. The info of all profiles, scenes and tasks inside the 383 | file will be generated. This is likely going to take some time 384 | depending on XML file size. 385 | 386 | The '-p' option sets the generate_config_info_mode to "project" 387 | mode. If this is passed, then exported_tasker_config should be 388 | the path to a Tasker exported "Project" XML file of which the 389 | config info needs to be generated. You may optionally pass a 390 | Tasker "Data Backup" XML file instead. Only the info of profiles, 391 | scenes and tasks belonging to the project will be generated. The 392 | project_name should be the Tasker project name which was exported to 393 | current_exported_tasker_config. Its project node must exist inside 394 | the exported_tasker_config file. 395 | 396 | exported_tasker_config_info should be the path to the output project 397 | info markdown file. 398 | 399 | The '-c' option will surround the task help in a code block. By 400 | default the help should be in markdown format. 401 | 402 | The '-s' option will add a script signature containing a link to the 403 | script repo at the end. 404 | 405 | The string passed with the '--text_description' option will be added 406 | under the 'Description' heading at the start. 407 | 408 | The string passed with the '--code_description' option will be added 409 | under the 'Code Description' heading at the end in a markdown code 410 | block. 411 | 412 | The '-m' option will create a sha256sum file for exported_tasker_config 413 | and exported_tasker_config_info files. The sha256sum file will by 414 | default be created in same directory as exported_tasker_config_info 415 | and the same basename except with a '.sha256sums' extension but a path can 416 | be passed with '--sha256sums_file' option. If '-m' is not passed, then 417 | the sha256sums of the exported_tasker_config xml file will be added to 418 | the exported_tasker_config_info file instead. 419 | 420 | Set verbose level to 1 or 2 to get more info when running 421 | tasker_config_utils generate_config_info command. 422 | 423 | 424 | Usage Flow 1: 425 | Create a Tasker "Data Backup". Example: "config.xml". 426 | Run following command: 427 | `tasker_config_utils generate_config_info -v -a "config.xml" \ 428 | "config.md"` 429 | 430 | Usage Flow 2: 431 | Export Tasker "Foo Bar" Project. It should by default be exported to 432 | "Foo_Bar.prf.xml". 433 | Run following command: 434 | `tasker_config_utils generate_config_info -v -p "Foo_Bar.prf.xml" \ 435 | "Foo_Bar-out.prf.md" "Foo Bar"` 436 | 437 | 438 | Optionally use the 439 | "Export Tasker Project XML Files To Android Storage?" and 440 | "Export Tasker Task XML Files To Android Storage?" tasks from the 441 | "TR_Tasker_Config_Utils" project to automatically create config info 442 | files on export. 443 | ``` 444 | 445 | ##### Examples: 446 | 447 | - Generate a markdown config info file for a given tasker config file. 448 | `tasker_config_utils generate_config_info -v -a "config.xml" "config.md"` 449 | 450 | - Generate a markdown config info file of a specific project. 451 | `tasker_config_utils generate_config_info -v -p "Foo_Bar.prf.xml" "Foo_Bar-out.prf.md" "Foo Bar"` 452 | ## 453 | 454 | 455 | ### Current Features 456 | 457 | - Extract tags and nodes from tasker config XML files. 458 | - Convert a project into a non-standalone project. 459 | - Generate a markdown config info file for a given tasker config XML file. 460 | ## 461 | 462 | 463 | ### Planned Features 464 | 465 | - Add more info to the generated markdown config info file. 466 | - Sort profiles, scenes and task nodes. 467 | ## 468 | 469 | 470 | ### Issues 471 | 472 | `-` 473 | ## 474 | 475 | 476 | ### Worthy Of Note 477 | 478 | `-` 479 | ## 480 | 481 | 482 | ### FAQs And FUQs 483 | 484 | Check [FAQs_And_FUQs.md](FAQs_And_FUQs.md) file for the **Frequently Asked Questions(FAQs)** and **Frequently Unasked Questions(FUQs)**. 485 | ## 486 | 487 | 488 | ### Changelog 489 | 490 | Check [CHANGELOG.md](CHANGELOG.md) file for the **Changelog**. 491 | ## 492 | 493 | 494 | ### Contributions 495 | 496 | `-` 497 | ## 498 | 499 | 500 | [Tasker App]: https://play.google.com/store/apps/details?id=net.dinglisch.android.taskerm 501 | [Tasker XML Info]: https://github.com/Taskomater/Tasker-XML-Info 502 | [Termux App]: https://github.com/termux/termux-app 503 | [cygwin]: https://cygwin.com/index.html 504 | -------------------------------------------------------------------------------- /tasker_config_utils: -------------------------------------------------------------------------------- 1 | #!/data/data/com.termux/files/usr/bin/bash 2 | 3 | #replace first line of this script with the following line if using termux 4 | #!/data/data/com.termux/files/usr/bin/bash 5 | 6 | #replace first line of this script with the following line if not using termux like a linux distro 7 | #!/bin/bash 8 | 9 | #title: tasker_config_utils 10 | #description: various tasker config utils 11 | #author: agnostic-apollo 12 | #usage: run "bash tasker_config_utils --help" 13 | #date: 11-Nov-2020 14 | #bash version: 4.0 or higher 15 | #credits: - 16 | #license: MIT License 17 | version=0.5.0 18 | 19 | 20 | 21 | ### Install Instructions For Termux In Android: 22 | 23 | #The `tasker_config_utils` file should be placed in termux `bin` directory `/data/data/com.termux/files/usr/bin`. 24 | #It should have `termux` `uid:gid` ownership and have executable `700` permission before it can be run directly without `bash`. 25 | # 26 | #1. Download the `tasker_config_utils` file. 27 | # 28 | # - Download to termux bin directory directly from github using `curl` using a non-root termux shell. 29 | # - Latest release: 30 | # 31 | # `curl -L 'https://github.com/Taskomater/tasker_config_utils/releases/latest/download/tasker_config_utils' -o "/data/data/com.termux/files/usr/bin/tasker_config_utils"` 32 | # 33 | # - Specific release: 34 | # 35 | # `curl -L 'https://github.com/Taskomater/tasker_config_utils/releases/download/v0.1.0/tasker_config_utils' -o "/data/data/com.termux/files/usr/bin/tasker_config_utils"` 36 | # 37 | # - Master Branch *may be unstable*: 38 | # 39 | # `curl -L 'https://github.com/Taskomater/tasker_config_utils/raw/master/tasker_config_utils' -o "/data/data/com.termux/files/usr/bin/tasker_config_utils"` 40 | # 41 | # - Download `tasker_config_utils` file manually from github to the android download directory and then copy it to termux bin directory. 42 | # 43 | # You can download the `tasker_config_utils` file from a github release from the `Assets` dropdown menu. 44 | # 45 | # You can also download it from a specific github branch/tag by opening the `tasker_config_utils` file from the `Code` section. 46 | # Right-click or hold the `Raw` button at the top and select `Download/Save link`. 47 | # 48 | # Then copy the file to termux bin directory using `cat` command below or use a root file browser to manually place it. 49 | # 50 | # `cat "/storage/emulated/0/Download/tasker_config_utils" > "/data/data/com.termux/files/usr/bin/tasker_config_utils"` 51 | # 52 | #2. Set `termux` ownership executable permissions. 53 | # 54 | # - If you used a `curl` or `cat` to copy the file, then use a non-root termux shell to set ownership and permissions with `chown` and `chmod` commands respectively: 55 | # 56 | # `export termux_bin_path="/data/data/com.termux/files/usr/bin"; export owner="$(stat -c "%u" "$termux_bin_path")"; chown "$owner:$owner" "$termux_bin_path/tasker_config_utils" && chmod 700 "$termux_bin_path/tasker_config_utils";` 57 | # 58 | # - If you used a root file browser to copy the file, then use `su` to start a root shell to set ownership and permissions with `chown` and `chmod` commands respectively: 59 | # 60 | # `export termux_bin_path="/data/data/com.termux/files/usr/bin"; export owner="$(stat -c "%u" "$termux_bin_path")"; su -c "chown \"$owner:$owner\" \"$termux_bin_path/tasker_config_utils\" && chmod 700 \"$termux_bin_path/tasker_config_utils\"";` 61 | # 62 | # - Or manually set them with your root file browser. You can find `termux` `uid` and `gid` by running the command `id -u` in a non-root termux shell or by checking the properties of the termux `bin` directory from your root file browser. 63 | # 64 | #You can run the script placed in the current directory without setting the ownership and permission by running the command `bash tasker_config_utils`. 65 | #If you are not running the script in termux, set the shebang of the script correctly (the first line of the script). 66 | 67 | 68 | 69 | ### Set User Modifiable Variables Start 70 | 71 | 72 | ### Set User Modifiable Variables End 73 | 74 | 75 | ### Set Default Variables Start 76 | #The following variables must not be modified unless you know what you are doing 77 | 78 | command_type="" #default to no command 79 | tasker_config="" #default to none 80 | project_name="" #default to none 81 | 82 | extraction_node="" #default to none 83 | extraction_tag="" #default to none 84 | extract_tags_from_entire_node=0 #default to 0 85 | pre_tag_regex="" #default to none 86 | post_tag_regex="" #default to none 87 | print_entire_extracted_nodes=0 #default to 0 88 | extracted_nodes_print_command="" #default to none 89 | current_exported_tasker_project="" #default to none 90 | new_exported_tasker_project="" #default to none 91 | 92 | exported_tasker_config="" #default to none 93 | exported_tasker_config_info="" #default to none 94 | exported_tasker_config_sha256sums="" #default to none 95 | generate_config_info_mode="" #default to none 96 | put_task_help_in_code_block=0 #default to 0 97 | add_script_signature_to_config_info=0 #default to 0 98 | create_sha256sums_file=0 #default to 0 99 | 100 | tasker_config_utils_verbose_level=0 #default to log level 0 101 | tasker_config_utils_args_verbose_level=0 #set this to "1" manually, if you want to debug arguments received 102 | 103 | #set regexes for validation 104 | valid_number_regex='^[0-9]+$' 105 | valid_absolute_path_regex='^(/[^/]+)+$' 106 | valid_tag='^[a-zA-Z0-9]+$' 107 | valid_comma_separated_number_list_regex='^[0-9]+(,[0-9]+)*$' 108 | valid_comma_separated_name_list_regex='^[][/$*.^+();!_a-zA-Z0-9 -]+(,[][/$*.^+();!_a-zA-Z0-9 -]+)*$' #allow '[]/$*.^+();!_a-zA-Z0-9 -' 109 | 110 | ### Set Default Variables End 111 | 112 | 113 | [[ x"${BASH_SOURCE[0]}" == x"$0" ]] && tasker_config_utils_exit_command="exit" || tasker_config_utils_exit_command="return" 114 | 115 | function tasker_config_utils_log () { local log_level="${1}"; shift; if [[ $tasker_config_utils_verbose_level -ge $log_level ]]; then echo "$@"; fi } 116 | function tasker_config_utils_log_literal () { local log_level="${1}"; shift; if [[ $tasker_config_utils_verbose_level -ge $log_level ]]; then echo -e "$@"; fi } 117 | function tasker_config_utils_log_errors () { echo "$@" 1>&2; } 118 | function tasker_config_utils_log_args () { if [[ $tasker_config_utils_args_verbose_level -ge "1" ]]; then echo "$@"; fi } 119 | function tasker_config_utils_log_arg_errors () { echo "$@" 1>&2; } 120 | 121 | 122 | tasker_config_utils_main() { 123 | 124 | local return_value 125 | 126 | #process the command or options passed to tasker_config_utils 127 | process_tasker_config_utils_parameters "$@" 128 | 129 | tasker_config_utils_make_script_executable_and_add_to_path "$0" 130 | return_value=$? 131 | if [ $return_value -ne 0 ]; then 132 | tasker_config_utils_log_errors "tasker_config_utils_make_script_executable_and_add_to_path failed with exit code $return_value" 133 | $tasker_config_utils_exit_command $return_value 134 | fi 135 | 136 | #run command 137 | if [ -z "$command_type" ]; then 138 | show_tasker_config_utils_help 139 | $tasker_config_utils_exit_command 0 140 | elif [[ "$command_type" != *,* ]] && [[ ",extract_tag,convert_project,generate_config_info," == *",$command_type,"* ]]; then 141 | tasker_config_utils_log_literal 2 "Running $command_type command" 142 | tasker_config_utils_"$command_type" 143 | return_value=$? 144 | else 145 | tasker_config_utils_log_errors "Unknown command type $command_type" 146 | exit_tasker_config_utils_on_error 147 | fi 148 | if [ $return_value -ne 0 ]; then 149 | tasker_config_utils_log_literal 1 "\ntasker_config_utils failed" 150 | else 151 | tasker_config_utils_log_literal 1 "\ntasker_config_utils successful" 152 | fi 153 | 154 | $tasker_config_utils_exit_command $return_value 155 | 156 | } 157 | 158 | tasker_config_utils_extract_tag() { 159 | 160 | local return_value 161 | 162 | tasker_config_utils_log_literal 1 "\nStarting tasker_config_utils_extract_tag" 163 | 164 | #if tasker_config is not set 165 | if [ -z "$tasker_config" ]; then 166 | tasker_config_utils_log_errors "tasker_config is not set which is required by \"tasker_config_utils_extract_tag\" function" 167 | return 1 168 | fi 169 | 170 | #if extraction_node is not set 171 | if [ -z "$extraction_node" ]; then 172 | tasker_config_utils_log_errors "extraction_node is not set which is required by \"tasker_config_utils_extract_tag\" function" 173 | return 1 174 | fi 175 | 176 | #if extract_tags_from_entire_node is not valid 177 | if [[ "$extract_tags_from_entire_node" != "0" ]] && [[ "$extract_tags_from_entire_node" != "1" ]]; then 178 | tasker_config_utils_log_errors "The extract_tags_from_entire_node \"$extract_tags_from_entire_node\" is invalid" 179 | return 1 180 | fi 181 | 182 | #if extraction_tag not set, set default tag 183 | if [ -z "$extraction_tag" ]; then 184 | if [[ "$extraction_node" == "Project" ]]; then 185 | extraction_tag="name" 186 | else 187 | extraction_tag="nme" 188 | fi 189 | fi 190 | 191 | #if extraction_tag is not set to "-", set extraction_tag_regex 192 | if [ "$extraction_tag" != "-" ]; then 193 | extraction_tag_regex='<'"$extraction_tag"'>(.*)<\/'"$extraction_tag"'>' 194 | else 195 | extraction_tag_regex="" 196 | fi 197 | 198 | #if extracted_nodes_print_command not set, set default value 199 | if [ -z "$extracted_nodes_print_command" ]; then 200 | extracted_nodes_print_command="p" 201 | fi 202 | 203 | tasker_config_utils_log 1 "tasker_config = \"$tasker_config\"" 204 | tasker_config_utils_log 1 "extraction_node = \"$extraction_node\"" 205 | tasker_config_utils_log 1 "extraction_tag = \"$extraction_tag\"" 206 | tasker_config_utils_log 1 "extract_tags_from_entire_node = \"$extract_tags_from_entire_node\"" 207 | 208 | #if tasker_config file is not found 209 | if [ ! -f "$tasker_config" ]; then 210 | tasker_config_utils_log_arg_errors "Failed to find tasker_config at \"$tasker_config\"" 211 | return 1 212 | fi 213 | 214 | #if extract_tags_from_entire_node is not enabled 215 | if [[ "$extract_tags_from_entire_node" == "0" ]]; then 216 | 217 | #if extraction_node is "Project", "Profile", "Scene" or "Task" 218 | if [[ "$extraction_node" == "Project" ]] || [[ "$extraction_node" == "Profile" ]] || \ 219 | [[ "$extraction_node" == "Scene" ]] || [[ "$extraction_node" == "Task" ]]; then 220 | # #a line matching the opening tag of the extraction_node 221 | # ^\t<'"$extraction_node"' sr="[^"]*"[^>]*>$ 222 | node_extraction_start_regex='^\t<'"$extraction_node"' sr="[^"]*"[^>]*>$' 223 | 224 | # :a; #create a label called a 225 | # N; #add next line to pattern space 226 | # #if pattern space does not end with 227 | # / 228 | # \n\t 229 | # ( 230 | # #a sr line of a subnode of extraction_node 231 | # (\t<[a-zA-Z0-9]+ sr="[^"]*"[^>]*>$) 232 | # | 233 | # #or the ending tag of the extraction_node 234 | # (<\/'"$extraction_node"'>$) 235 | # )" 236 | # #go to label a; 237 | # /!ba; 238 | node_extraction_end_regex=':a;N;/\n\t((\t<[a-zA-Z0-9]+ sr="[^"]*"[^>]*>$)|(<\/'"$extraction_node"'>$))/!ba;' 239 | else 240 | #same as above other than '[\t]+' and `[\t]*` are added so that deeper nodes can be matched 241 | node_extraction_start_regex='^\t[\t]+<'"$extraction_node"' sr="[^"]*"[^>]*>$' 242 | node_extraction_end_regex=':a;N;/\n\t\t(([\t]+<[a-zA-Z0-9]+ sr="[^"]*"[^>]*>$)|([\t]*<\/'"$extraction_node"'>$))/!ba;' 243 | fi 244 | 245 | tasker_config_utils_log 2 "node_extraction_start_regex = \"$node_extraction_start_regex\"" 246 | tasker_config_utils_log 2 "node_extraction_end_regex = \"$node_extraction_end_regex\"" 247 | 248 | #find all tag values 249 | #use -E for extended regex, and -n to disable printing 250 | #sed -nE ''"$node_extraction_start_regex"'/ #match extraction_node sr line depending on node_extraction_start_regex 251 | # { #if matched start a subscript 252 | # #add next n lines to pattern space depending on node_extraction_end_regex 253 | # '"$node_extraction_end_regex"'; 254 | # #if pattern space matches the pattern ".*'"$pre_tag_regex"'.*'"$extraction_tag_regex"'.*'"$post_tag_regex"'.*", then extract extraction_tag value and print it 255 | # s/.*'"$pre_tag_regex"'.*'"$extraction_tag_regex"'.*'"$post_tag_regex"'.*/\1/p; 256 | # }' 257 | extracted_tag_values="$(sed -nE '/'"$node_extraction_start_regex"'/{'"$node_extraction_end_regex"'s/.*'"$pre_tag_regex"'.*'"$extraction_tag_regex"'.*'"$post_tag_regex"'.*/\1/p;}' "$tasker_config")" 258 | return_value=$? 259 | if [ $return_value -ne 0 ]; then 260 | tasker_config_utils_log_errors "Failed to find $extraction_tag tag values of $extraction_node nodes from tasker_config" 261 | return $return_value 262 | fi 263 | 264 | #if extracted_tag_values is set 265 | if [ ! -z "$extracted_tag_values" ]; then 266 | #print extracted_tag_values to stdout 267 | echo "$extracted_tag_values" 268 | else 269 | : 270 | fi 271 | else 272 | 273 | #if extraction_node is "Project", "Profile", "Scene" or "Task" 274 | if [[ "$extraction_node" == "Project" ]] || [[ "$extraction_node" == "Profile" ]] || \ 275 | [[ "$extraction_node" == "Scene" ]] || [[ "$extraction_node" == "Task" ]]; then 276 | # #a line matching the opening tag of the extraction_node 277 | # ^\t<'"$extraction_node"' sr="[^"]*"[^>]*>$ 278 | node_extraction_start_regex='^\t<'"$extraction_node"' sr="[^"]*"[^>]*>$' 279 | 280 | # :a; #create a label called a 281 | # N; #add next line to pattern space 282 | # #if pattern space does not end with 283 | # / 284 | # #the ending tag of the extraction_node 285 | # \n\t<\/'"$extraction_node"'>$ 286 | # #go to label a; 287 | # /!ba; 288 | node_extraction_end_regex=':a;N;/\n\t<\/'"$extraction_node"'>$/!ba;' 289 | else 290 | #same as above other than '[\t]+' is added so that deeper nodes can be matched 291 | node_extraction_start_regex='^\t[\t]+<'"$extraction_node"' sr="[^"]*"[^>]*>$' 292 | node_extraction_end_regex=':a;N;/\n\t[\t]+<\/'"$extraction_node"'>$/!ba;' 293 | fi 294 | 295 | tasker_config_utils_log 2 "node_extraction_start_regex = \"$node_extraction_start_regex\"" 296 | tasker_config_utils_log 2 "node_extraction_end_regex = \"$node_extraction_end_regex\"" 297 | 298 | #extract node 299 | #use -E for extended regex, and -n to disable printing 300 | #sed -nE '/'"$node_extraction_start_regex"'/ #match extraction_node sr line depending on node_extraction_start_regex 301 | # { #if matched start a subscript 302 | # #add next n lines to pattern space depending on node_extraction_end_regex 303 | # '"$node_extraction_end_regex"'; 304 | # #if pattern space matches the pattern ".*'"$pre_tag_regex"'.*'"$extraction_tag_regex"'.*'"$post_tag_regex"'.*", then extract extraction_tag value and print it 305 | # s/.*'"$pre_tag_regex"'.*'"$extraction_tag_regex"'.*'"$post_tag_regex"'.*/\1/p; 306 | # }' 307 | extracted_nodes="$(sed -nE '/'"$node_extraction_start_regex"'/{'"$node_extraction_end_regex"'/.*'"$pre_tag_regex"'.*'"$extraction_tag_regex"'.*'"$post_tag_regex"'.*/'"$extracted_nodes_print_command"'}' "$tasker_config")" 308 | return_value=$? 309 | if [ $return_value -ne 0 ]; then 310 | tasker_config_utils_log_errors "Failed to extract $extraction_node nodes from tasker_config" 311 | return $return_value 312 | fi 313 | 314 | tasker_config_utils_log_literal 2 "\n\nextracted_nodes:" 315 | tasker_config_utils_log_literal 2 "\`\`\`" 316 | [ ! -z "$extracted_nodes" ] && tasker_config_utils_log 2 "$extracted_nodes" 317 | tasker_config_utils_log_literal 2 "\`\`\`\n\n" 318 | 319 | #find all tag values 320 | extracted_tag_values="$(echo "$extracted_nodes" | sed -nE 's/\t\t[\t]*<'"$extraction_tag"'>(.*)<\/'"$extraction_tag"'>/\1/gp;')" 321 | return_value=$? 322 | if [ $return_value -ne 0 ]; then 323 | tasker_config_utils_log_errors "Failed to find $extraction_tag tag values of $extraction_node nodes from tasker_config" 324 | return $return_value 325 | fi 326 | 327 | #if print_entire_extracted_nodes is not enabled 328 | if [[ "$print_entire_extracted_nodes" == "0" ]]; then 329 | #if extracted_tag_values is set 330 | if [ ! -z "$extracted_tag_values" ]; then 331 | #print extracted_tag_values to stdout 332 | echo "$extracted_tag_values" 333 | else 334 | : 335 | fi 336 | else 337 | #if extracted_tag_values is set 338 | if [ ! -z "$extracted_nodes" ]; then 339 | #print extracted_nodes to stdout 340 | echo "$extracted_nodes" 341 | else 342 | : 343 | fi 344 | fi 345 | fi 346 | 347 | return_value=$? 348 | 349 | return $return_value 350 | 351 | } 352 | 353 | ### How making a non-standalone exported project file works: 354 | #1. Receive tasker_config and current_exported_tasker_project file paths and the project_name that was exported 355 | #2. Then extract the project nodes matching project_name from the tasker_config and current_exported_tasker_project files 356 | #3. Then extract the list of profile pids, scene names and task tids that originally exited in the project_name project \ 357 | # from the tasker_config file 358 | #4. Then create a copy of the current_exported_tasker_project at new_exported_tasker_project 359 | #5. Then remove all profile nodes in the new_exported_tasker_project that do not have the profile id that matches the \ 360 | # list of profile ids extracted from the tasker_config file 361 | #6. Then remove all scene nodes in the new_exported_tasker_project that do not have the scene name that matches the \ 362 | # list of scene names extracted from the tasker_config file 363 | ### At this point all profiles and scenes that originally did not exist in the project_name project in the tasker_config \ 364 | # file would have been removed. Only named and anonymous tasks belonging to the project_name project and the other \ 365 | # projects would remain. To find out which task ids to remove is a bit more tricky. The tids list of the project_name \ 366 | # project extracted from the tasker_config file earlier in step 3 will not contain any ids of anonymous tasks of \ 367 | # profiles and scenes. So removing all tasks whose id does not match the ids in that tids list will also remove \ 368 | # anonymous tasks of profiles and scenes of the project_name project and all named and anonymous tasks of other \ 369 | # projects. So first we need to find out which anonymous tasks belong to the project_name project so that they are \ 370 | # not removed and only the named and anonymous tasks of other projects are removed. Since profiles and scenes of \ 371 | # other projects have already been removed from the new_exported_tasker_project, we can find which anonymous task \ 372 | # tids are referred by the remaining profiles and scenes, since those should belong to the project_name project. 373 | #7. First we extract all ids of tasks referred by the profile nodes by extracting the and tag values. \ 374 | # This will contain both ids of both named and anonymous tasks. 375 | #8. Then we extract all ids of tasks referred by the scene nodes by extracting the <[a-zA-Z0-9]+Task> tag values. \ 376 | # This will contain ids of all scene events anonymous tasks. 377 | #9. Then we generate a new tids list which will include task ids referred by profiles and scenes extracted in step \ 378 | # 8 and 9 and also the tids extracted from the project_name project node extracted from the tasker_config file \ 379 | # earlier in step 3 380 | #10. Then we remove all duplicate values, likely generated by profiles referring to named tasks. 381 | #11. Then we remove all tasks nodes in the new_exported_tasker_project that do not have the task id that matches the \ 382 | # new list of tids generated in step 9 383 | #12. Removing nodes will also have created empty lines in the new_exported_tasker_project file. These are then removed. 384 | #13. If no scenes exist anymore, then the tag is also removed. 385 | #14. Then we replace the and tag values of the project_name project node in the new_exported_tasker_project \ 386 | # with the ones extracted from the tasker_config file earlier in step 3 and also replace tag value with the new \ 387 | # list of tids generated in step 9 so that tasker knows which profiles, scenes and tasks belong to the project during import. 388 | ### We can have gone the other way of extracting profiles, scenes and tasks belonging to the project_name project directly \ 389 | #from the tasker_config file but tasker makes changes to nodes while exporting and it would be unsafe to do that ourselves \ 390 | #without knowing exactly what they are. Example tags are changed. 391 | tasker_config_utils_convert_project() { 392 | 393 | local return_value 394 | 395 | tasker_config_utils_log_literal 1 "\nStarting tasker_config_utils_convert_project" 396 | 397 | #if tasker_config is not set 398 | if [ -z "$tasker_config" ]; then 399 | tasker_config_utils_log_errors "tasker_config is not set which is required by \"tasker_config_utils_convert_project\" function" 400 | return 1 401 | fi 402 | 403 | #if current_exported_tasker_project is not set 404 | if [ -z "$current_exported_tasker_project" ]; then 405 | tasker_config_utils_log_errors "current_exported_tasker_project is not set which is required by \"tasker_config_utils_convert_project\" function" 406 | return 1 407 | fi 408 | 409 | #if new_exported_tasker_project is not set 410 | if [ -z "$new_exported_tasker_project" ]; then 411 | tasker_config_utils_log_errors "new_exported_tasker_project is not set which is required by \"tasker_config_utils_convert_project\" function" 412 | return 1 413 | fi 414 | 415 | #if project_name is not set 416 | if [ -z "$project_name" ]; then 417 | tasker_config_utils_log_errors "project_name is not set which is required by \"tasker_config_utils_convert_project\" function" 418 | return 1 419 | fi 420 | 421 | tasker_config_utils_log 1 "tasker_config = \"$tasker_config\"" 422 | tasker_config_utils_log 1 "current_exported_tasker_project = \"$current_exported_tasker_project\"" 423 | tasker_config_utils_log 1 "new_exported_tasker_project = \"$new_exported_tasker_project\"" 424 | tasker_config_utils_log 1 "project_name = \"$project_name\"" 425 | 426 | #if tasker_config file is not found 427 | if [ ! -f "$tasker_config" ]; then 428 | tasker_config_utils_log_arg_errors "Failed to find tasker_config at \"$tasker_config\"" 429 | return 1 430 | fi 431 | 432 | #if current_exported_tasker_project file is not found 433 | if [ ! -f "$current_exported_tasker_project" ]; then 434 | tasker_config_utils_log_arg_errors "Failed to find current_exported_tasker_project at \"$current_exported_tasker_project\"" 435 | return 1 436 | fi 437 | 438 | #escape `[]/$*.^` with backslashes for sed 439 | #test with: echo -n "[]/$.*^" | sed -zE -e 's/[][/$*.^]/\\&/g' 440 | sed_formatted_project_name="$(echo -n "$project_name" | sed -zE -e 's/[][/$*.^]/\\&/g')" 441 | return_value=$? 442 | if [ $return_value -ne 0 ]; then 443 | tasker_config_utils_log_errors "Failed to convert project_name \"$project_name\" to sed supported format" 444 | return $return_value 445 | fi 446 | tasker_config_utils_log 2 "sed_formatted_project_name = \"$sed_formatted_project_name\"" 447 | 448 | 449 | 450 | ###Extract the project_name project node from tasker_config 451 | 452 | tasker_config_utils_log_literal 1 "\n" 453 | tasker_config_utils_log 1 "Extracting the \"$project_name\" project node from tasker_config" 454 | 455 | #use -E for extended regex, and -n to disable printing 456 | #sed -nE '/^\t]*>$/' #match Project sr line 457 | # { #if matched start a subscript 458 | # :a; #create a label called a 459 | # N; #add next line to pattern space 460 | # #if pattern space does not end with "\n\t$" go to label a; 461 | # /\n\t<\/Project>$/!ba 462 | # #if pattern space matches ".*'"$sed_formatted_project_name"'<\/name>.*", then print pattern space 463 | # /.*'"$sed_formatted_project_name"'<\/name>.*/p; 464 | # }' 465 | tasker_config_project_node="$(sed -nE '/^\t]*>$/{:a;N;/\n\t<\/Project>$/!ba;/.*'"$sed_formatted_project_name"'<\/name>.*/p;}' "$tasker_config")" 466 | return_value=$? 467 | if [ $return_value -ne 0 ]; then 468 | tasker_config_utils_log_errors "Failed to run sed to extract the \"$project_name\" project node from tasker_config" 469 | return $return_value 470 | fi 471 | 472 | #if tasker_config_project_node file is empty 473 | if [ -z "$tasker_config_project_node" ]; then 474 | tasker_config_utils_log_arg_errors "Failed to find project_name \"$project_name\" in tasker_config \"$tasker_config\"" 475 | return 1 476 | fi 477 | 478 | tasker_config_utils_log_literal 2 "\n\ntasker_config_project_node:" 479 | tasker_config_utils_log_literal 2 "\"" 480 | tasker_config_utils_log 2 "$tasker_config_project_node" 481 | tasker_config_utils_log_literal 2 "\"\n\n" 482 | 483 | 484 | 485 | ###Extract the project_name project node from current_exported_tasker_project 486 | 487 | tasker_config_utils_log 1 "Extracting the \"$project_name\" project node from current_exported_tasker_project" 488 | 489 | #use -E for extended regex, and -n to disable printing 490 | #sed -nE '/^\t]*>$/' #match Project sr line 491 | # { #if matched start a subscript 492 | # :a; #create a label called a 493 | # N; #add next line to pattern space 494 | # #if pattern space does not end with "\n\t$" go to label a; 495 | # /\n\t<\/Project>$/!ba 496 | # #if pattern space matches ".*'"$sed_formatted_project_name"'<\/name>.*", then print pattern space 497 | # /.*'"$sed_formatted_project_name"'<\/name>.*/p; 498 | # }' 499 | current_exported_tasker_project_project_node="$(sed -nE '/^\t]*>$/{:a;N;/\n\t<\/Project>$/!ba;/.*'"$sed_formatted_project_name"'<\/name>.*/p;}' "$current_exported_tasker_project")" 500 | return_value=$? 501 | if [ $return_value -ne 0 ]; then 502 | tasker_config_utils_log_errors "Failed to run sed to extract the \"$project_name\" project node from current_exported_tasker_project" 503 | return $return_value 504 | fi 505 | 506 | tasker_config_utils_log_literal 2 "\n\ncurrent_exported_tasker_project_project_node:" 507 | tasker_config_utils_log_literal 2 "\"" 508 | tasker_config_utils_log 2 "$current_exported_tasker_project_project_node" 509 | tasker_config_utils_log_literal 2 "\"\n\n" 510 | 511 | #if current_exported_tasker_project_project_node file is empty 512 | if [ -z "$current_exported_tasker_project_project_node" ]; then 513 | tasker_config_utils_log_arg_errors "Failed to find project_name \"$project_name\" in new_exported_tasker_project \"$new_exported_tasker_project\"" 514 | return 1 515 | fi 516 | 517 | 518 | 519 | ###Extract the list of profile pids that originally exited in the project_name project from the tasker_config file 520 | 521 | tasker_config_utils_log_literal 1 "\n" 522 | tasker_config_utils_log 1 "Extracting the profile pids that originally exited in the \"$project_name\" project from the tasker_config file" 523 | 524 | #extract the tag value from the project_name project node extracted from the tasker_config 525 | tasker_config_profile_ids="$(echo "$tasker_config_project_node" | sed -nzE 's/.*(.*)<\/pids>.*/\1/p;')" 526 | return_value=$? 527 | if [ $return_value -ne 0 ]; then 528 | tasker_config_utils_log_errors "Failed to find profile_ids from tasker_config" 529 | return $return_value 530 | fi 531 | 532 | sorted_tasker_config_profile_ids="$(echo "$tasker_config_profile_ids" | sed -E 's/,/\n/g' | sort -n | sed -zE 's/\n/,/g' | sed 's/,$//')" 533 | 534 | tasker_config_utils_log 1 "tasker_config_profile_ids: $tasker_config_profile_ids" 535 | tasker_config_utils_log 2 "sorted_tasker_config_profile_ids: $sorted_tasker_config_profile_ids" 536 | 537 | #if tasker_config_profile_ids are set but not valid 538 | if [ ! -z "$tasker_config_profile_ids" ] && [[ ! "$tasker_config_profile_ids" =~ $valid_comma_separated_number_list_regex ]]; then 539 | tasker_config_utils_log_errors "The tasker_config_profile_ids extracted is not a valid command separated number list" 540 | return 1 541 | fi 542 | 543 | 544 | 545 | ###Extract the list of scene names that originally exited in the project_name project from the tasker_config file 546 | 547 | tasker_config_utils_log_literal 1 "\n" 548 | tasker_config_utils_log 1 "Extracting the scene names that originally exited in the \"$project_name\" project from the tasker_config file" 549 | 550 | #extract the tag value from the project_name project node extracted from the tasker_config 551 | tasker_config_scenes="$(echo "$tasker_config_project_node" | sed -nzE 's/.*(.*)<\/scenes>.*/\1/p;')" 552 | return_value=$? 553 | if [ $return_value -ne 0 ]; then 554 | tasker_config_utils_log_errors "Failed to find scenes from tasker_config" 555 | return $return_value 556 | fi 557 | 558 | sorted_tasker_config_scenes="$(echo "$tasker_config_scenes" | sed -E 's/,/\n/g' | sort -n | sed -zE 's/\n/,/g' | sed 's/,$//')" 559 | 560 | tasker_config_utils_log 1 "tasker_config_scenes: $tasker_config_scenes" 561 | tasker_config_utils_log 2 "sorted_tasker_config_scenes: $sorted_tasker_config_scenes" 562 | 563 | #if tasker_config_scenes are set but not valid 564 | if [ ! -z "$tasker_config_scenes" ] && [[ ! "$tasker_config_scenes" =~ $valid_comma_separated_name_list_regex ]]; then 565 | tasker_config_utils_log_errors "The tasker_config_scenes extracted are not a valid command separated name list" 566 | return 1 567 | fi 568 | 569 | 570 | 571 | ###Extract the list of task tids that originally exited in the project_name project from the tasker_config file 572 | 573 | tasker_config_utils_log_literal 1 "\n" 574 | tasker_config_utils_log 1 "Extracting the task tids that originally exited in the \"$project_name\" project from the tasker_config file" 575 | 576 | #extract the tag value from the project_name project node extracted from the tasker_config 577 | tasker_config_task_ids="$(echo "$tasker_config_project_node" | sed -nzE 's/.*(.*)<\/tids>.*/\1/p;')" 578 | return_value=$? 579 | if [ $return_value -ne 0 ]; then 580 | tasker_config_utils_log_errors "Failed to find task_ids from tasker_config" 581 | return $return_value 582 | fi 583 | 584 | sorted_tasker_config_task_ids="$(echo "$tasker_config_task_ids" | sed -E 's/,/\n/g' | sort -n | sed -zE 's/\n/,/g' | sed 's/,$//')" 585 | 586 | tasker_config_utils_log 1 "tasker_config_task_ids: $tasker_config_task_ids" 587 | tasker_config_utils_log 2 "sorted_tasker_config_task_ids: $sorted_tasker_config_task_ids" 588 | 589 | #if tasker_config_task_ids are set but not valid 590 | if [ ! -z "$tasker_config_task_ids" ] && [[ ! "$tasker_config_task_ids" =~ $valid_comma_separated_number_list_regex ]]; then 591 | tasker_config_utils_log_errors "The tasker_config_task_ids extracted is not a valid command separated number list" 592 | return 1 593 | fi 594 | 595 | 596 | 597 | ###Create a copy of current_exported_tasker_project at new_exported_tasker_project 598 | 599 | tasker_config_utils_log_literal 1 "\n" 600 | tasker_config_utils_log 1 "Copying current_exported_tasker_project \"$current_exported_tasker_project\" to new_exported_tasker_project \"$new_exported_tasker_project\"" 601 | 602 | #create new_exported_tasker_project parent directory if it does not exist 603 | tasker_config_utils_create_parent_path "$new_exported_tasker_project" "new_exported_tasker_project" 604 | return_value=$? 605 | if [ $return_value -ne 0 ]; then 606 | tasker_config_utils_log_errors "tasker_config_utils_create_parent_path failed with exit code $return_value" 607 | return $return_value 608 | fi 609 | 610 | #copy current_exported_tasker_project to new_exported_tasker_project 611 | cp -f "$current_exported_tasker_project" "$new_exported_tasker_project" 612 | return_value=$? 613 | if [ $return_value -ne 0 ]; then 614 | tasker_config_utils_log_errors "Failed to copy current_exported_tasker_project \"$current_exported_tasker_project\" to new_exported_tasker_project \"$new_exported_tasker_project\"" 615 | return $return_value 616 | fi 617 | 618 | #if new_exported_tasker_project file is not found 619 | if [ ! -f "$new_exported_tasker_project" ]; then 620 | tasker_config_utils_log_errors "Failed to find \"$new_exported_tasker_project\" file" 621 | return 1 622 | fi 623 | 624 | 625 | 626 | ###Remove all profile nodes in the new_exported_tasker_project that do not have the profile id that matches the list of profile ids extracted \ 627 | ###from the tasker_config file 628 | 629 | #if tasker_config_profile_ids are set 630 | if [ ! -z "$tasker_config_profile_ids" ] ; then 631 | 632 | #Set the regex replace string that will be used to replace the tag line of the project_name project node in the \ 633 | #new_exported_tasker_project with the pids extracted from the tasker_config file earlier 634 | new_exported_tasker_project_profile_ids_tag='\n\t\t'"$tasker_config_profile_ids"'<\/pids>' 635 | 636 | #Set the regex that will be used to remove all profile nodes in the new_exported_tasker_project that do not have the profile id that \ 637 | #matches the list of profile ids extracted from the tasker_config file 638 | 639 | #Convert the list of profile ids extracted from the tasker_config file to a regex OR format by replacing all commas ',' with ')|(' \ 640 | #and then prefixing and suffixing with '(('' and '))' 641 | #Example '1,2,3' -> '((1|2|3))' 642 | new_exported_tasker_project_remove_profile_regex="$(echo "$tasker_config_profile_ids" | sed -E 's/,/)|(/g;')" 643 | return_value=$? 644 | if [ $return_value -ne 0 ]; then 645 | tasker_config_utils_log_errors "Failed to convert tasker_config_profile_ids to new_exported_tasker_project_remove_profile_regex" 646 | return $return_value 647 | fi 648 | new_exported_tasker_project_remove_profile_regex='(('"$new_exported_tasker_project_remove_profile_regex"'))' 649 | 650 | #Set the regex 651 | #if pattern space does not match '/.*((1|2|3))<\/id>.*/!', i.e a profile node without an tag that matches a value in the pids list 652 | #/.*'"$new_exported_tasker_project_remove_profile_regex"'<\/id>.*/! 653 | #then if pattern space matches '.*\n\t<\/Profile>$', replace it with nothing to remove the profile node 654 | #s/.*\n\t<\/Profile>$// 655 | new_exported_tasker_project_remove_profile_regex='/.*'"$new_exported_tasker_project_remove_profile_regex"'<\/id>.*/! s/.*\n\t<\/Profile>$//' 656 | else 657 | #Set the regex replace string that will be used to replace the tag line of the project_name project node in the \ 658 | #new_exported_tasker_project with nothing since no pids were extracted from the tasker_config file earlier 659 | new_exported_tasker_project_profile_ids_tag='' 660 | 661 | #Set the regex that will be used to remove all profile nodes in the new_exported_tasker_project that do not have the profile id that \ 662 | #matches the list of profile ids extracted from the tasker_config file 663 | #Set the regex to replace all profile nodes to nothing since no pids were extracted from the tasker_config file earlier 664 | new_exported_tasker_project_remove_profile_regex='s/.*\n\t<\/Profile>$//' 665 | fi 666 | 667 | tasker_config_utils_log 2 "" 668 | tasker_config_utils_log 1 "Removing profiles from new_exported_tasker_project whose id does not match new_exported_tasker_project_remove_profile_regex" 669 | 670 | tasker_config_utils_log 2 "new_exported_tasker_project_remove_profile_regex: $new_exported_tasker_project_remove_profile_regex" 671 | 672 | #Remove any unneeded profile nodes from the new_exported_tasker_project 673 | #use -i'' to replace inplace and to overwrite input file, and -E for extended regex 674 | #sed -i'' -E '/^\t]*>$/' #match Profile sr line 675 | # /{ #if matched start a subscript 676 | # :a; #create a label called a 677 | # N; #add next line to pattern space 678 | # #if pattern space does not end with "\n\t$" go to label a; 679 | # /\n\t<\/Profile>$/!ba; 680 | # #replace pattern space according to regex defined in new_exported_tasker_project_remove_profile_regex 681 | # '"$new_exported_tasker_project_remove_profile_regex"'; 682 | # }' 683 | sed -i'' -E '/^\t]*>$/{:a;N;/\n\t<\/Profile>$/!ba;'"$new_exported_tasker_project_remove_profile_regex"';}' "$new_exported_tasker_project" 684 | return_value=$? 685 | if [ $return_value -ne 0 ]; then 686 | tasker_config_utils_log_errors "Failed to remove profiles from new_exported_tasker_project whose id does not match new_exported_tasker_project_remove_profile_regex" 687 | return $return_value 688 | fi 689 | 690 | 691 | 692 | ###Remove all scene nodes in the new_exported_tasker_project that do not have the scene name that matches the list of scene names extracted \ 693 | ###from the tasker_config file 694 | 695 | #if tasker_config_scenes are set 696 | if [ ! -z "$tasker_config_scenes" ] ; then 697 | 698 | #escape `[]/$*.^` with backslashes for sed 699 | #test with: echo -n "[]/$.*^" | sed -zE -e 's/[][/$*.^]/\\&/g' 700 | sed_formatted_tasker_config_scenes="$(echo -n "$tasker_config_scenes" | sed -zE -e 's/[][/$*.^]/\\&/g')" 701 | return_value=$? 702 | if [ $return_value -ne 0 ]; then 703 | tasker_config_utils_log_errors "Failed to convert tasker_config_scenes to sed supported format" 704 | return $return_value 705 | fi 706 | 707 | #Create a regex to replace the tag values of the project_name project node in the new_exported_tasker_project with the ones extracted \ 708 | #from the tasker_config file earlier 709 | new_exported_tasker_project_scenes_tag='\n\t\t'"$sed_formatted_tasker_config_scenes"'<\/scenes>' 710 | 711 | #Set the regex that will be used to remove all scene nodes in the new_exported_tasker_project that do not have the scene name that \ 712 | #matches the list of scene names extracted from the tasker_config file 713 | 714 | #Convert the list of scene names extracted from the tasker_config file to a regex OR format by replacing all commas ',' with ')|(' \ 715 | #and then prefixing and suffixing with '(('' and '))' 716 | #Example 'Scene 1,Scene 2,Scene 3' -> '((Scene 1|Scene 2|Scene 3))' 717 | new_exported_tasker_project_remove_scenes_regex="$(echo "$sed_formatted_tasker_config_scenes" | sed -E 's/,/)|(/g;')" 718 | return_value=$? 719 | if [ $return_value -ne 0 ]; then 720 | tasker_config_utils_log_errors "Failed to convert tasker_config_scenes to new_exported_tasker_project_remove_scenes_regex" 721 | return $return_value 722 | fi 723 | new_exported_tasker_project_remove_scenes_regex='(('"$new_exported_tasker_project_remove_scenes_regex"'))' 724 | 725 | #Set the regex 726 | #if pattern space does not match '/.*((Scene 1|Scene 2|Scene 3))<\/nme>.*/!', i.e a scene node without an tag that matches a \ 727 | #value in the scene names list 728 | #/.*'"$new_exported_tasker_project_remove_scenes_regex"'<\/nme>.*/! 729 | #then if pattern space matches '.*\n\t<\/Scene>$', replace it with nothing to remove the scene node 730 | #s/.*\n\t<\/Scene>$// 731 | new_exported_tasker_project_remove_scenes_regex='/.*'"$new_exported_tasker_project_remove_scenes_regex"'<\/nme>.*/! s/.*\n\t<\/Scene>$//' 732 | else 733 | #Set the regex replace string that will be used to replace the tag line of the project_name project node in the \ 734 | #new_exported_tasker_project with nothing since no scene names were extracted from the tasker_config file earlier 735 | new_exported_tasker_project_scenes_tag='' 736 | 737 | #Set the regex that will be used to remove all scene nodes in the new_exported_tasker_project that do not have the profile id that \ 738 | #matches the list of scene names extracted from the tasker_config file 739 | #Set the regex to replace all scene nodes to nothing since no scene names were extracted from the tasker_config file earlier 740 | new_exported_tasker_project_remove_scenes_regex='s/.*\n\t<\/Scene>$//' 741 | fi 742 | 743 | tasker_config_utils_log 2 "" 744 | tasker_config_utils_log 1 "Removing scenes from new_exported_tasker_project whose nme does not match new_exported_tasker_project_remove_scenes_regex" 745 | 746 | tasker_config_utils_log 2 "new_exported_tasker_project_remove_scenes_regex: $new_exported_tasker_project_remove_scenes_regex" 747 | 748 | #Remove any unneeded scene nodes from the new_exported_tasker_project 749 | #use -i'' to replace inplace and to overwrite input file, and -E for extended regex 750 | #sed -i'' -E '/^\t]*>$/' #match Scene sr line 751 | # { #if matched start a subscript 752 | # :a; #create a label called a 753 | # N; #add next line to pattern space 754 | # #if pattern space does not end with "\n\t$" go to label a; 755 | # /\n\t<\/Scene>$/!ba; 756 | # #replace pattern space according to regex defined in new_exported_tasker_project_remove_scenes_regex 757 | # '"$new_exported_tasker_project_remove_scenes_regex"'; 758 | # }' 759 | sed -i'' -E '/^\t]*>$/{:a;N;/\n\t<\/Scene>$/!ba;'"$new_exported_tasker_project_remove_scenes_regex"';}' "$new_exported_tasker_project" 760 | return_value=$? 761 | if [ $return_value -ne 0 ]; then 762 | tasker_config_utils_log_errors "Failed to remove scenes from new_exported_tasker_project whose nme does not match new_exported_tasker_project_remove_scenes_regex" 763 | return $return_value 764 | fi 765 | 766 | 767 | 768 | ###Extract all ids of tasks referred by the profile nodes by extracting the and tag values 769 | 770 | tasker_config_utils_log 2 "" 771 | tasker_config_utils_log 1 "Extracting the profile entry task ids from new_exported_tasker_project" 772 | 773 | #extract all entry task ids from the tag 774 | new_exported_tasker_project_profile_entry_task_ids="$(tasker_config_utils extract_tag -p --tag='mid0' "$new_exported_tasker_project")" 775 | return_value=$? 776 | if [ $return_value -ne 0 ]; then 777 | tasker_config_utils_log_errors "Failed to get profile entry task ids from new_exported_tasker_project" 778 | return $return_value 779 | fi 780 | 781 | #replace all newlines with a comma in the extracted entry task ids string 782 | new_exported_tasker_project_profile_entry_task_ids="$(echo "$new_exported_tasker_project_profile_entry_task_ids" | sed -zE -e 's/\n/,/g' -e 's/,$//')" 783 | return_value=$? 784 | if [ $return_value -ne 0 ]; then 785 | tasker_config_utils_log_errors "Failed to convert new_exported_tasker_project_profile_entry_task_ids to a comma separated list" 786 | return $return_value 787 | fi 788 | 789 | tasker_config_utils_log 2 "new_exported_tasker_project_profile_entry_task_ids: $new_exported_tasker_project_profile_entry_task_ids" 790 | 791 | #if new_exported_tasker_project_profile_entry_task_ids are set but not valid 792 | if [ ! -z "$new_exported_tasker_project_profile_entry_task_ids" ] && [[ ! "$new_exported_tasker_project_profile_entry_task_ids" =~ $valid_comma_separated_number_list_regex ]]; then 793 | tasker_config_utils_log_errors "The new_exported_tasker_project_profile_entry_task_ids extracted is not a valid command separated number list" 794 | return 1 795 | fi 796 | 797 | tasker_config_utils_log 2 "" 798 | tasker_config_utils_log 1 "Extracting the profile exit task ids from new_exported_tasker_project" 799 | 800 | #extract all exit task ids from the tag 801 | new_exported_tasker_project_profile_exit_task_ids="$(tasker_config_utils extract_tag -p --tag='mid1' "$new_exported_tasker_project")" 802 | return_value=$? 803 | if [ $return_value -ne 0 ]; then 804 | tasker_config_utils_log_errors "Failed to get profile exit task ids from new_exported_tasker_project" 805 | return $return_value 806 | fi 807 | 808 | #replace all newlines with a comma in the extracted exit task ids string 809 | new_exported_tasker_project_profile_exit_task_ids="$(echo "$new_exported_tasker_project_profile_exit_task_ids" | sed -zE -e 's/\n/,/g' -e 's/,$//')" 810 | return_value=$? 811 | if [ $return_value -ne 0 ]; then 812 | tasker_config_utils_log_errors "Failed to convert new_exported_tasker_project_profile_exit_task_ids to a comma separated list" 813 | return $return_value 814 | fi 815 | 816 | tasker_config_utils_log 2 "new_exported_tasker_project_profile_exit_task_ids: $new_exported_tasker_project_profile_exit_task_ids" 817 | 818 | #if new_exported_tasker_project_profile_exit_task_ids are set but not valid 819 | if [ ! -z "$new_exported_tasker_project_profile_exit_task_ids" ] && [[ ! "$new_exported_tasker_project_profile_exit_task_ids" =~ $valid_comma_separated_number_list_regex ]]; then 820 | tasker_config_utils_log_errors "The new_exported_tasker_project_profile_exit_task_ids extracted is not a valid command separated number list" 821 | return 1 822 | fi 823 | 824 | 825 | 826 | ###Extract all ids of tasks referred by the scene nodes by extracting the <[a-zA-Z0-9]+Task> tag values 827 | 828 | tasker_config_utils_log 2 "" 829 | tasker_config_utils_log 1 "Extracting all ids of tasks referred by the scene nodes from new_exported_tasker_project" 830 | 831 | #extract all scene anonymous task ids from the tags matching '<[a-zA-Z0-9]+Task>' 832 | new_exported_tasker_project_scene_task_ids="$(tasker_config_utils extract_tag -s -e --tag='[a-zA-Z0-9]+Task' "$new_exported_tasker_project")" 833 | return_value=$? 834 | if [ $return_value -ne 0 ]; then 835 | tasker_config_utils_log_errors "Failed to get scene anonymous task ids from new_exported_tasker_project" 836 | return $return_value 837 | fi 838 | 839 | #replace all newlines with a comma in the extracted scene anonymous task ids string 840 | new_exported_tasker_project_scene_task_ids="$(echo "$new_exported_tasker_project_scene_task_ids" | sed -zE -e 's/\n/,/g' -e 's/,$//')" 841 | return_value=$? 842 | if [ $return_value -ne 0 ]; then 843 | tasker_config_utils_log_errors "Failed to convert new_exported_tasker_project_scene_task_ids to a comma separated list" 844 | return $return_value 845 | fi 846 | 847 | tasker_config_utils_log 2 "new_exported_tasker_project_scene_task_ids: $new_exported_tasker_project_scene_task_ids" 848 | 849 | #if new_exported_tasker_project_scene_task_ids are set but not valid 850 | if [ ! -z "$new_exported_tasker_project_scene_task_ids" ] && [[ ! "$new_exported_tasker_project_scene_task_ids" =~ $valid_comma_separated_number_list_regex ]]; then 851 | tasker_config_utils_log_errors "The new_exported_tasker_project_scene_task_ids extracted is not a valid command separated number list" 852 | return 1 853 | fi 854 | 855 | 856 | 857 | ###Generate a new tids list by adding both of profile and scene referred task ids to the tids list of the project_name project extracted from the \ 858 | #tasker_config file earlier 859 | 860 | tasker_config_utils_log 2 "" 861 | tasker_config_utils_log 1 "Generating a new tids list" 862 | 863 | #Set tasker_config_task_ids to new_exported_tasker_project_task_ids 864 | new_exported_tasker_project_task_ids="$tasker_config_task_ids" 865 | 866 | #if new_exported_tasker_project_profile_entry_task_ids are set, then add them to new_exported_tasker_project_task_ids 867 | if [ ! -z "$new_exported_tasker_project_profile_entry_task_ids" ]; then 868 | new_exported_tasker_project_task_ids="$new_exported_tasker_project_task_ids,$new_exported_tasker_project_profile_entry_task_ids" 869 | fi 870 | 871 | #if new_exported_tasker_project_profile_exit_task_ids are set, then add them to new_exported_tasker_project_task_ids 872 | if [ ! -z "$new_exported_tasker_project_profile_exit_task_ids" ]; then 873 | new_exported_tasker_project_task_ids="$new_exported_tasker_project_task_ids,$new_exported_tasker_project_profile_exit_task_ids" 874 | fi 875 | 876 | #if new_exported_tasker_project_scene_task_ids are set, then add them to new_exported_tasker_project_task_ids 877 | if [ ! -z "$new_exported_tasker_project_scene_task_ids" ]; then 878 | new_exported_tasker_project_task_ids="$new_exported_tasker_project_task_ids,$new_exported_tasker_project_scene_task_ids" 879 | fi 880 | 881 | 882 | #Remove all duplicate values, likely generated by profiles referring to named tasks 883 | new_exported_tasker_project_task_ids="$(echo "$new_exported_tasker_project_task_ids" | sed -zE 's/^,//' | sed -E 's/,/\n/g' | cat -n | sort -uk2 | sort -nk1 | cut -f2- | sed -zE 's/\n/,/g' | sed 's/,$//')" 884 | return_value=$? 885 | if [ $return_value -ne 0 ]; then 886 | tasker_config_utils_log_errors "Failed to remove starting comma and sorting new_exported_tasker_project_task_ids" 887 | return $return_value 888 | fi 889 | 890 | tasker_config_utils_log 1 "new_exported_tasker_project_task_ids: $new_exported_tasker_project_task_ids" 891 | tasker_config_utils_log 2 "sorted_new_exported_tasker_project_task_ids: $(echo -n "$new_exported_tasker_project_task_ids" | sed -E 's/,/\n/g' | sort -n | sed -zE 's/\n/,/g' | sed 's/,$//')" 892 | 893 | #if new_exported_tasker_project_task_ids are set but not valid 894 | if [ ! -z "$new_exported_tasker_project_task_ids" ] && [[ ! "$new_exported_tasker_project_task_ids" =~ $valid_comma_separated_number_list_regex ]]; then 895 | tasker_config_utils_log_errors "The new_exported_tasker_project_task_ids extracted is not a valid command separated number list" 896 | return 1 897 | fi 898 | 899 | 900 | 901 | ###Remove all tasks nodes in the new_exported_tasker_project that do not have the task id that matches the new tids list generated 902 | 903 | #if new_exported_tasker_project_task_ids are set 904 | if [ ! -z "$new_exported_tasker_project_task_ids" ] ; then 905 | #Set the regex replace string that will be used to replace the tag line of the project_name project node in the \ 906 | #new_exported_tasker_project with the new tids list generated 907 | new_exported_tasker_project_task_ids_tag='\n\t\t'"$new_exported_tasker_project_task_ids"'<\/tids>' 908 | 909 | #Set the regex that will be used to remove all task nodes in the new_exported_tasker_project that do not have the task id that \ 910 | #matches the new tids list generated 911 | 912 | #Convert the list of task ids generated to a regex OR format by replacing all commas ',' with ')|(' \ 913 | #and then prefixing and suffixing with '(('' and '))' 914 | #Example '1,2,3' -> '((1|2|3))' 915 | new_exported_tasker_project_remove_task_regex="$(echo "$new_exported_tasker_project_task_ids" | sed -E 's/,/)|(/g;')" 916 | return_value=$? 917 | if [ $return_value -ne 0 ]; then 918 | tasker_config_utils_log_errors "Failed to convert new_exported_tasker_project_task_ids to new_exported_tasker_project_remove_task_regex" 919 | return $return_value 920 | fi 921 | new_exported_tasker_project_remove_task_regex='(('"$new_exported_tasker_project_remove_task_regex"'))' 922 | 923 | #Set the regex 924 | #if pattern space does not match '/.*((1|2|3))<\/id>.*/!', i.e a task node without an tag that matches a value in the tids list 925 | #/.*'"$new_exported_tasker_project_remove_task_regex"'<\/id>.*/! 926 | #then if pattern space matches '.*\n\t<\/Task>$', replace it with nothing to remove the task node 927 | #s/.*\n\t<\/Task>$// 928 | new_exported_tasker_project_remove_task_regex='/.*'"$new_exported_tasker_project_remove_task_regex"'<\/id>.*/! s/.*\n\t<\/Task>$//' 929 | else 930 | #Set the regex replace string that will be used to replace the tag line of the project_name project node in the \ 931 | #new_exported_tasker_project with nothing since no tids exist in the new tids list generated 932 | new_exported_tasker_project_task_ids_tag='' 933 | 934 | #Set the regex that will be used to remove all task nodes in the new_exported_tasker_project that do not have the task id that \ 935 | #matches the new tids list generated 936 | #Set the regex to replace all task nodes to nothing since no tids exist in the new tids list generated 937 | new_exported_tasker_project_remove_task_regex='s/.*\n\t<\/Task>$//' 938 | fi 939 | 940 | tasker_config_utils_log_literal 1 "\n" 941 | tasker_config_utils_log 1 "Removing tasks from new_exported_tasker_project whose id does not match new_exported_tasker_project_remove_task_regex" 942 | 943 | tasker_config_utils_log 2 "new_exported_tasker_project_remove_task_regex: $new_exported_tasker_project_remove_task_regex" 944 | 945 | #Remove any unneeded task nodes from the new_exported_tasker_project 946 | #use -i'' to replace inplace and to overwrite input file, and -E for extended regex 947 | #sed -i'' -E '/^\t]*>$/' #match Task sr line 948 | # { #if matched start a subscript 949 | # :a; #create a label called a 950 | # N; #add next line to pattern space 951 | # #if pattern space does not end with "\n\t$" go to label a; 952 | # /\n\t<\/Task>$/!ba; 953 | # #replace pattern space according to regex defined in new_exported_tasker_project_remove_task_regex 954 | # '"$new_exported_tasker_project_remove_task_regex"'; 955 | # }' 956 | sed -i'' -E '/^\t]*>$/{:a;N;/\n\t<\/Task>$/!ba;'"$new_exported_tasker_project_remove_task_regex"';}' "$new_exported_tasker_project" 957 | return_value=$? 958 | if [ $return_value -ne 0 ]; then 959 | tasker_config_utils_log_errors "Failed to remove tasks from new_exported_tasker_project whose id does not match new_exported_tasker_project_remove_task_regex" 960 | return $return_value 961 | fi 962 | 963 | 964 | 965 | ###Removing empty lines in the new_exported_tasker_project file created by removing nodes. 966 | 967 | tasker_config_utils_log 2 "" 968 | tasker_config_utils_log 1 "Removing extra newlines between nodes in new_exported_tasker_project" 969 | 970 | #use -i'' to replace inplace and to overwrite input file, -E for extended regex, and -Z to separate lines by NUL characters instead of newlines 971 | #sed -i'' -zE 's 972 | #if pattern space matches any tags defined in matching group 1, followed by one or more newlines, followed by any tags in matching group 8 973 | #/ 974 | #( #matching group 1 975 | # (\n\t<\/Profile>) 976 | # | 977 | # (\n\t<\/Project>) 978 | # | 979 | # (\n\t<\/Scene>) 980 | # | 981 | # (\n\t<\/Task>) 982 | # | 983 | # (\n\t[^<]*<\/dmetric>) 984 | # | 985 | # (]*>) 986 | #) 987 | #\n+ 988 | #( #matching group 8 989 | # \t 998 | #) 999 | #/ 1000 | #replace pattern space with matching group 1, followed by only one newline, followed by matching group 8 1001 | #\1\n\8/g' 1002 | sed -i'' -zE 's/((\n\t<\/Profile>)|(\n\t<\/Project>)|(\n\t<\/Scene>)|(\n\t<\/Task>)|(\n\t[^<]*<\/dmetric>)|(]*>))\n+(\t)/\1\n\8/g' "$new_exported_tasker_project" 1003 | return_value=$? 1004 | if [ $return_value -ne 0 ]; then 1005 | tasker_config_utils_log_errors "Failed to remove extra newlines between nodes in new_exported_tasker_project" 1006 | return $return_value 1007 | fi 1008 | 1009 | 1010 | 1011 | ###Replace the and tag values of the project_name project node in the new_exported_tasker_project with the ones extracted \ 1012 | ###from the tasker_config file earlier and also replace tag value with the new tids list generated 1013 | 1014 | tasker_config_utils_log 2 "" 1015 | tasker_config_utils_log 1 "Replacing , and tag values of the \"$project_name\" project node in new_exported_tasker_project" 1016 | tasker_config_utils_log 2 "new_exported_tasker_project_profile_ids_tag: $new_exported_tasker_project_profile_ids_tag" 1017 | tasker_config_utils_log 2 "new_exported_tasker_project_scenes_tag: $new_exported_tasker_project_scenes_tag" 1018 | tasker_config_utils_log 2 "new_exported_tasker_project_task_ids_tag: $new_exported_tasker_project_task_ids_tag" 1019 | 1020 | #replace , and tag values 1021 | #use -i'' to replace inplace and to overwrite input file, -E for extended regex 1022 | #sed -i'' -E '/^\t]*>$/' #match Project sr line 1023 | # { #if matched start a subscript 1024 | # :a; #create a label called a 1025 | # N; #add next line to pattern space 1026 | # #if pattern space does not end with "\n\t$" go to label a; 1027 | # /\n\t<\/Project>$/!ba 1028 | # #if pattern space matches "\n\t\t.*<\/pids>", then replace it with new_exported_tasker_project_profile_ids_tag 1029 | # s/\n\t\t.*<\/pids>/'"$new_exported_tasker_project_profile_ids_tag"'/; 1030 | # #if pattern space matches "\n\t\t.*<\/scenes>", then replace it with new_exported_tasker_project_scenes_tag 1031 | # s/\n\t\t.*<\/scenes>/'"$new_exported_tasker_project_scenes_tag"'/; 1032 | # #if pattern space matches "\n\t\t.*<\/tids>", then replace it with new_exported_tasker_project_task_ids_tag 1033 | # s/\n\t\t.*<\/tids>/'"$new_exported_tasker_project_task_ids_tag"'/; 1034 | # }' 1035 | sed -i'' -E '/^\t]*>$/{:a;N;/\n\t<\/Project>$/!ba;s/\n\t\t.*<\/pids>/'"$new_exported_tasker_project_profile_ids_tag"'/;s/\n\t\t.*<\/scenes>/'"$new_exported_tasker_project_scenes_tag"'/;s/\n\t\t.*<\/tids>/'"$new_exported_tasker_project_task_ids_tag"'/;}' "$new_exported_tasker_project" 1036 | return_value=$? 1037 | if [ $return_value -ne 0 ]; then 1038 | tasker_config_utils_log_errors "Failed to replace , and tag values of the \"$project_name\" project node in new_exported_tasker_project" 1039 | return $return_value 1040 | fi 1041 | 1042 | 1043 | 1044 | #Remove tag if no scenes exist in the new_exported_tasker_project 1045 | tasker_config_utils_log 2 "" 1046 | tasker_config_utils_log 1 "Removing tag if no scenes exist in new_exported_tasker_project" 1047 | 1048 | output_new_exported_tasker_project_scenes="$(tasker_config_utils extract_tag -s --tag='nme' "$new_exported_tasker_project")" 1049 | return_value=$? 1050 | if [ $return_value -ne 0 ]; then 1051 | tasker_config_utils_log_errors "Failed to find scene names in new_exported_tasker_project" 1052 | return $return_value 1053 | fi 1054 | 1055 | #if output_new_exported_tasker_project_scenes is empty, then it means no scenes exist 1056 | if [ -z "$output_new_exported_tasker_project_scenes" ]; then 1057 | #remove tag 1058 | #use -i'' to replace inplace and to overwrite input file, -E for extended regex 1059 | #sed -i'' -E 1060 | #if pattern space matches "(]*>)\n\t[^<]*<\/dmetric>", then replace it with matching group 1 1061 | #s/\n\t[^<]*<\/dmetric>// 1062 | sed -i'' -zE 's/(]*>)\n\t[^<]*<\/dmetric>/\1/' "$new_exported_tasker_project" 1063 | return_value=$? 1064 | if [ $return_value -ne 0 ]; then 1065 | tasker_config_utils_log_errors "Failed to remove unneeded tag in new_exported_tasker_project" 1066 | return $return_value 1067 | fi 1068 | fi 1069 | 1070 | 1071 | 1072 | ###Check if any profile, scene or task was not removed that did not exist in the respective lists 1073 | tasker_config_utils_log 2 "" 1074 | tasker_config_utils_log 1 "Checking if any profile, scene or task was not removed that did not exist in the respective lists" 1075 | 1076 | output_new_exported_tasker_project_profile_ids="$(tasker_config_utils extract_tag -p --tag='id' "$new_exported_tasker_project")" 1077 | tasker_config_utils_log 2 "output_new_exported_tasker_project_profile_ids: $(echo -n "$output_new_exported_tasker_project_profile_ids" | sort -n | sed -zE 's/\n/,/g' | sed 's/,$//')" 1078 | output_new_exported_tasker_project_scenes="$(tasker_config_utils extract_tag -s --tag='nme' "$new_exported_tasker_project")" 1079 | tasker_config_utils_log 2 "output_new_exported_tasker_project_scenes: $(echo -n "$output_new_exported_tasker_project_scenes" | sort -n | sed -zE 's/\n/,/g' | sed 's/,$//')" 1080 | output_new_exported_tasker_project_task_ids="$(tasker_config_utils extract_tag -t --tag='id' "$new_exported_tasker_project")" 1081 | tasker_config_utils_log 2 "output_new_exported_tasker_project_task_ids: $(echo -n "$output_new_exported_tasker_project_task_ids" | sort -n | sed -zE 's/\n/,/g' | sed 's/,$//')" 1082 | 1083 | #output_new_exported_tasker_project_profile_ids="$output_new_exported_tasker_project_profile_ids"$'\n8' 1084 | 1085 | profile_ids_not_removed="$( 1086 | ( 1087 | echo "$output_new_exported_tasker_project_profile_ids" | sort -n | uniq 1088 | echo "$sorted_tasker_config_profile_ids" | sed -E 's/,/\n/g' | sort -n | uniq 1089 | echo "$sorted_tasker_config_profile_ids" | sed -E 's/,/\n/g' | sort -n | uniq 1090 | ) | sort -n | uniq -u | sed -zE 's/\n/,/g' | sed 's/,$//')" 1091 | 1092 | #if profile_ids_not_removed is not empty 1093 | if [ ! -z "$profile_ids_not_removed" ]; then 1094 | tasker_config_utils_log_errors "Failed to remove some profile nodes" 1095 | tasker_config_utils_log_errors "profile_ids_not_removed: $profile_ids_not_removed" 1096 | return 1 1097 | fi 1098 | 1099 | scenes_not_removed="$( 1100 | ( 1101 | echo "$output_new_exported_tasker_project_scenes" | sort -n | uniq 1102 | echo "$sorted_tasker_config_scenes" | sed -E 's/,/\n/g' | sort -n | uniq 1103 | echo "$sorted_tasker_config_scenes" | sed -E 's/,/\n/g' | sort -n | uniq 1104 | ) | sort -n | uniq -u | sed -zE 's/\n/,/g' | sed 's/,$//')" 1105 | 1106 | #if scenes_not_removed is not empty 1107 | if [ ! -z "$scenes_not_removed" ]; then 1108 | tasker_config_utils_log_errors "Failed to remove some scene nodes" 1109 | tasker_config_utils_log_errors "scenes_not_removed: $scenes_not_removed" 1110 | return 1 1111 | fi 1112 | 1113 | task_ids_not_removed="$( 1114 | ( 1115 | echo "$output_new_exported_tasker_project_task_ids" | sort -n | uniq 1116 | echo "$new_exported_tasker_project_task_ids" | sed -E 's/,/\n/g' | sort -n | uniq 1117 | echo "$new_exported_tasker_project_task_ids" | sed -E 's/,/\n/g' | sort -n | uniq 1118 | ) | sort -n | uniq -u | sed -zE 's/\n/,/g' | sed 's/,$//')" 1119 | 1120 | #if task_ids_not_removed is not empty 1121 | if [ ! -z "$task_ids_not_removed" ]; then 1122 | tasker_config_utils_log_errors "Failed to remove some task nodes" 1123 | tasker_config_utils_log_errors "task_ids_not_removed: $task_ids_not_removed" 1124 | return 1 1125 | fi 1126 | 1127 | tasker_config_utils_log 2 "" 1128 | 1129 | return 0 1130 | 1131 | } 1132 | 1133 | #tasker_config_utils_generate_config_info $exported_tasker_config $exported_tasker_config_info $project_name 1134 | tasker_config_utils_generate_config_info() { 1135 | 1136 | local return_value 1137 | 1138 | tasker_config_utils_log_literal 1 "\nStarting tasker_config_utils_generate_config_info" 1139 | 1140 | #if exported_tasker_config is not set 1141 | if [ -z "$exported_tasker_config" ]; then 1142 | tasker_config_utils_log_errors "exported_tasker_config is not set which is required by \"tasker_config_utils_generate_config_info\" function" 1143 | return 1 1144 | fi 1145 | 1146 | #if exported_tasker_config_info is not set 1147 | if [ -z "$exported_tasker_config_info" ]; then 1148 | tasker_config_utils_log_errors "exported_tasker_config_info is not set which is required by \"tasker_config_utils_generate_config_info\" function" 1149 | return 1 1150 | fi 1151 | 1152 | #if generate_config_info_mode is set to "project" and project_name is not set 1153 | if [[ "$generate_config_info_mode" == "project" ]] && [ -z "$project_name" ]; then 1154 | tasker_config_utils_log_errors "generate_config_info_mode is \"$generate_config_info_mode\" but project_name is not set which is required by \"tasker_config_utils_generate_config_info\" function" 1155 | return 1 1156 | fi 1157 | 1158 | tasker_config_utils_log 1 "exported_tasker_config = \"$exported_tasker_config\"" 1159 | tasker_config_utils_log 1 "exported_tasker_config_info = \"$exported_tasker_config_info\"" 1160 | 1161 | #if exported_tasker_config file is not found 1162 | if [ ! -f "$exported_tasker_config" ]; then 1163 | tasker_config_utils_log_arg_errors "Failed to find exported_tasker_config at \"$exported_tasker_config\"" 1164 | return 1 1165 | fi 1166 | 1167 | #find sha256sum of exported_tasker_config 1168 | exported_tasker_config_sha256sum_value="$(sha256sum "$exported_tasker_config")" 1169 | return_value=$? 1170 | if [ $return_value -ne 0 ]; then 1171 | tasker_config_utils_log_errors "Failed to find sha256sum of exported_tasker_config" 1172 | return $return_value 1173 | fi 1174 | 1175 | #remove filename from sha256sum of exported_tasker_config 1176 | exported_tasker_config_sha256sum_value="$(echo "$exported_tasker_config_sha256sum_value" | cut -d " " -f 1)" 1177 | return_value=$? 1178 | if [ $return_value -ne 0 ]; then 1179 | tasker_config_utils_log_errors "Failed to remove filename from sha256sum of exported_tasker_config" 1180 | return $return_value 1181 | fi 1182 | 1183 | #if generate_config_info_mode is set to "project" 1184 | if [[ "$generate_config_info_mode" == "project" ]]; then 1185 | tasker_config_utils_log 1 "project_name = \"$project_name\"" 1186 | 1187 | #escape `[]/$*.^` with backslashes for sed 1188 | #test with: echo -n "[]/$.*^" | sed -zE -e 's/[][/$*.^]/\\&/g' 1189 | sed_formatted_project_name="$(echo -n "$project_name" | sed -zE -e 's/[][/$*.^]/\\&/g')" 1190 | return_value=$? 1191 | if [ $return_value -ne 0 ]; then 1192 | tasker_config_utils_log_errors "Failed to convert project_name \"$project_name\" to sed supported format" 1193 | return $return_value 1194 | fi 1195 | tasker_config_utils_log 2 "sed_formatted_project_name = \"$sed_formatted_project_name\"" 1196 | 1197 | ###Extract the project_name project node from exported_tasker_config 1198 | 1199 | tasker_config_utils_log_literal 1 "\n" 1200 | tasker_config_utils_log 1 "Extracting the \"$project_name\" project node from exported_tasker_config" 1201 | 1202 | #use -E for extended regex, and -n to disable printing 1203 | #sed -nE '/^\t]*>$/' #match Project sr line 1204 | # { #if matched start a subscript 1205 | # :a; #create a label called a 1206 | # N; #add next line to pattern space 1207 | # #if pattern space does not end with "\n\t$" go to label a; 1208 | # /\n\t<\/Project>$/!ba 1209 | # #if pattern space matches ".*'"$sed_formatted_project_name"'<\/name>.*", then print pattern space 1210 | # /.*'"$sed_formatted_project_name"'<\/name>.*/p; 1211 | # }' 1212 | exported_tasker_config_project_node="$(sed -nE '/^\t]*>$/{:a;N;/\n\t<\/Project>$/!ba;/.*'"$sed_formatted_project_name"'<\/name>.*/p;}' "$exported_tasker_config")" 1213 | return_value=$? 1214 | if [ $return_value -ne 0 ]; then 1215 | tasker_config_utils_log_errors "Failed to run sed to extract the \"$project_name\" project node from exported_tasker_config" 1216 | return $return_value 1217 | fi 1218 | 1219 | #if exported_tasker_config_project_node file is empty 1220 | if [ -z "$exported_tasker_config_project_node" ]; then 1221 | tasker_config_utils_log_arg_errors "Failed to find project_name \"$project_name\" in exported_tasker_config \"$exported_tasker_config\"" 1222 | return 1 1223 | fi 1224 | 1225 | tasker_config_utils_log_literal 2 "\n\nexported_tasker_config_project_node:" 1226 | tasker_config_utils_log_literal 2 "\"" 1227 | tasker_config_utils_log 2 "$exported_tasker_config_project_node" 1228 | tasker_config_utils_log_literal 2 "\"\n\n" 1229 | fi 1230 | 1231 | 1232 | 1233 | ###Extract the list of profile ids from the exported_tasker_config file 1234 | 1235 | tasker_config_utils_log_literal 1 "\n" 1236 | 1237 | #if generate_config_info_mode is set to "all" 1238 | if [[ "$generate_config_info_mode" == "all" ]]; then 1239 | tasker_config_utils_log 1 "Extracting the profile ids from the exported_tasker_config file" 1240 | 1241 | #extract the tag value of all profile nodes from the exported_tasker_config 1242 | exported_tasker_config_profile_ids="$(tasker_config_utils extract_tag -p --tag='id' "$exported_tasker_config")" 1243 | return_value=$? 1244 | if [ $return_value -ne 0 ]; then 1245 | tasker_config_utils_log_errors "Failed to extract profile ids from exported_tasker_config" 1246 | return $return_value 1247 | fi 1248 | 1249 | #convert extracted profile ids to a comma separated list 1250 | exported_tasker_config_profile_ids="$(echo "$exported_tasker_config_profile_ids" | sed -zE 's/\n/,/g' | sed 's/,$//')" 1251 | return_value=$? 1252 | if [ $return_value -ne 0 ]; then 1253 | tasker_config_utils_log_errors "Failed to convert exported_tasker_config_profile_ids to a comma separated list" 1254 | return $return_value 1255 | fi 1256 | #if generate_config_info_mode is set to "project" 1257 | elif [[ "$generate_config_info_mode" == "project" ]]; then 1258 | tasker_config_utils_log 1 "Extracting the profile ids of \"$project_name\" project from the exported_tasker_config file" 1259 | 1260 | #extract the tag value from the project_name project node extracted from the exported_tasker_config 1261 | exported_tasker_config_profile_ids="$(echo "$exported_tasker_config_project_node" | sed -nzE 's/.*(.*)<\/pids>.*/\1/p;')" 1262 | return_value=$? 1263 | if [ $return_value -ne 0 ]; then 1264 | tasker_config_utils_log_errors "Failed to extract profile ids of \"$project_name\" from exported_tasker_config" 1265 | return $return_value 1266 | fi 1267 | else 1268 | tasker_config_utils_log_errors "generate_config_info_mode \"$generate_config_info_mode\" not handled" 1269 | return 1 1270 | fi 1271 | 1272 | sorted_exported_tasker_config_profile_ids="$(echo "$exported_tasker_config_profile_ids" | sed -E 's/,/\n/g' | sort -n | sed -zE 's/\n/,/g' | sed 's/,$//')" 1273 | 1274 | tasker_config_utils_log 1 "exported_tasker_config_profile_ids: $exported_tasker_config_profile_ids" 1275 | tasker_config_utils_log 2 "sorted_exported_tasker_config_profile_ids: $sorted_exported_tasker_config_profile_ids" 1276 | 1277 | #if exported_tasker_config_profile_ids are set but not valid 1278 | if [ ! -z "$exported_tasker_config_profile_ids" ] && [[ ! "$exported_tasker_config_profile_ids" =~ $valid_comma_separated_number_list_regex ]]; then 1279 | tasker_config_utils_log_errors "The exported_tasker_config_profile_ids extracted is not a valid command separated number list" 1280 | return 1 1281 | fi 1282 | 1283 | 1284 | 1285 | ###Extract the list of scene names from the exported_tasker_config file 1286 | 1287 | tasker_config_utils_log_literal 1 "\n" 1288 | 1289 | #if generate_config_info_mode is set to "all" 1290 | if [[ "$generate_config_info_mode" == "all" ]]; then 1291 | tasker_config_utils_log 1 "Extracting the scene names from the exported_tasker_config file" 1292 | 1293 | #extract the tag value of all scene nodes from the exported_tasker_config 1294 | tasker_config_scenes="$(tasker_config_utils extract_tag -s --tag='nme' "$exported_tasker_config")" 1295 | return_value=$? 1296 | if [ $return_value -ne 0 ]; then 1297 | tasker_config_utils_log_errors "Failed to extract scene names from exported_tasker_config" 1298 | return $return_value 1299 | fi 1300 | 1301 | #convert extracted scene names to a comma separated list 1302 | tasker_config_scenes="$(echo "$tasker_config_scenes" | sed -zE 's/\n/,/g' | sed 's/,$//')" 1303 | return_value=$? 1304 | if [ $return_value -ne 0 ]; then 1305 | tasker_config_utils_log_errors "Failed to convert tasker_config_scenes to a comma separated list" 1306 | return $return_value 1307 | fi 1308 | #if generate_config_info_mode is set to "project" 1309 | elif [[ "$generate_config_info_mode" == "project" ]]; then 1310 | tasker_config_utils_log 1 "Extracting the scene names of \"$project_name\" project from the exported_tasker_config file" 1311 | 1312 | #extract the tag value from the project_name project node extracted from the exported_tasker_config 1313 | tasker_config_scenes="$(echo "$exported_tasker_config_project_node" | sed -nzE 's/.*(.*)<\/scenes>.*/\1/p;')" 1314 | return_value=$? 1315 | if [ $return_value -ne 0 ]; then 1316 | tasker_config_utils_log_errors "Failed to extract scenes of \"$project_name\" from exported_tasker_config" 1317 | return $return_value 1318 | fi 1319 | else 1320 | tasker_config_utils_log_errors "generate_config_info_mode \"$generate_config_info_mode\" not handled" 1321 | return 1 1322 | fi 1323 | 1324 | sorted_tasker_config_scenes="$(echo "$tasker_config_scenes" | sed -E 's/,/\n/g' | sort -n | sed -zE 's/\n/,/g' | sed 's/,$//')" 1325 | 1326 | tasker_config_utils_log 1 "tasker_config_scenes: $tasker_config_scenes" 1327 | tasker_config_utils_log 2 "sorted_tasker_config_scenes: $sorted_tasker_config_scenes" 1328 | 1329 | #if tasker_config_scenes are set but not valid 1330 | if [ ! -z "$tasker_config_scenes" ] && [[ ! "$tasker_config_scenes" =~ $valid_comma_separated_name_list_regex ]]; then 1331 | tasker_config_utils_log_errors "The tasker_config_scenes extracted are not a valid command separated name list" 1332 | return 1 1333 | fi 1334 | 1335 | 1336 | 1337 | ###Extract the list of task ids from the exported_tasker_config file 1338 | 1339 | tasker_config_utils_log_literal 1 "\n" 1340 | 1341 | #if generate_config_info_mode is set to "all" 1342 | if [[ "$generate_config_info_mode" == "all" ]]; then 1343 | tasker_config_utils_log 1 "Extracting the task ids from the exported_tasker_config file" 1344 | 1345 | #extract the tag value of all task nodes from the exported_tasker_config 1346 | exported_tasker_config_task_ids="$(tasker_config_utils extract_tag -t --tag='id' "$exported_tasker_config")" 1347 | return_value=$? 1348 | if [ $return_value -ne 0 ]; then 1349 | tasker_config_utils_log_errors "Failed to extract task ids from exported_tasker_config" 1350 | return $return_value 1351 | fi 1352 | 1353 | #convert extracted task ids to a comma separated list 1354 | exported_tasker_config_task_ids="$(echo "$exported_tasker_config_task_ids" | sed -zE 's/\n/,/g' | sed 's/,$//')" 1355 | return_value=$? 1356 | if [ $return_value -ne 0 ]; then 1357 | tasker_config_utils_log_errors "Failed to convert exported_tasker_config_task_ids to a comma separated list" 1358 | return $return_value 1359 | fi 1360 | #if generate_config_info_mode is set to "project" 1361 | elif [[ "$generate_config_info_mode" == "project" ]]; then 1362 | tasker_config_utils_log 1 "Extracting the task ids of \"$project_name\" project from the tasker_config file" 1363 | 1364 | #extract the tag value from the project_name project node extracted from the exported_tasker_config 1365 | exported_tasker_config_task_ids="$(echo "$exported_tasker_config_project_node" | sed -nzE 's/.*(.*)<\/tids>.*/\1/p;')" 1366 | return_value=$? 1367 | if [ $return_value -ne 0 ]; then 1368 | tasker_config_utils_log_errors "Failed to extract task ids of \"$project_name\" from exported_tasker_config" 1369 | return $return_value 1370 | fi 1371 | else 1372 | tasker_config_utils_log_errors "generate_config_info_mode \"$generate_config_info_mode\" not handled" 1373 | return 1 1374 | fi 1375 | 1376 | sorted_exported_tasker_config_task_ids="$(echo "$exported_tasker_config_task_ids" | sed -E 's/,/\n/g' | sort -n | sed -zE 's/\n/,/g' | sed 's/,$//')" 1377 | 1378 | tasker_config_utils_log 1 "exported_tasker_config_task_ids: $exported_tasker_config_task_ids" 1379 | tasker_config_utils_log 2 "sorted_exported_tasker_config_task_ids: $sorted_exported_tasker_config_task_ids" 1380 | 1381 | #if exported_tasker_config_task_ids are set but not valid 1382 | if [ ! -z "$exported_tasker_config_task_ids" ] && [[ ! "$exported_tasker_config_task_ids" =~ $valid_comma_separated_number_list_regex ]]; then 1383 | tasker_config_utils_log_errors "The exported_tasker_config_task_ids extracted is not a valid command separated number list" 1384 | return 1 1385 | fi 1386 | 1387 | 1388 | 1389 | ### Initialize Config Info 1390 | 1391 | tasker_version="$(sed -nE 's/^]*tv="([^"]*)"[^>]*>$/\1/p' "$exported_tasker_config")" 1392 | timestamp="$(date -u +"%Y-%m-%d %H.%M.%S")" 1393 | export_info=$'\n\n \n'"## Export Info:" 1394 | export_info+=$'\n**Tasker Version:** `'"$tasker_version"'` ' 1395 | export_info+=$'\n**Timestamp:** `'"$timestamp"'` ' 1396 | 1397 | #if create_sha256sums_file is not enabled 1398 | if [[ "$create_sha256sums_file" != "1" ]]; then 1399 | export_info+=$'\n**sha256sum:** `'"$exported_tasker_config_sha256sum_value"'` ' 1400 | fi 1401 | 1402 | export_info+=$'\n ' 1403 | 1404 | profiles_name_list=$'\n\n \n'"## Profile Names:" 1405 | scenes_name_list=$'\n\n'"## Scene Names:" 1406 | tasks_name_list=$'\n\n'"## Task Names:" 1407 | profiles_info_list=$'\n\n \n'"## Profiles Info:"$'\n ' 1408 | tasks_info_list=$'\n\n \n'"## Tasks Info:"$'\n ' 1409 | 1410 | 1411 | 1412 | ###Generate Profiles Info 1413 | 1414 | tasker_config_utils_log_literal 1 "\n" 1415 | tasker_config_utils_log 1 "Generating Profiles Info" 1416 | 1417 | IFS=, read -ra exported_tasker_config_profile_ids_array <<< "$exported_tasker_config_profile_ids" 1418 | 1419 | profiles_name_list+=$'\n**Count:** `'"${#exported_tasker_config_profile_ids_array[@]}"'`'$'\n' 1420 | 1421 | i=1 1422 | for profile_id in "${exported_tasker_config_profile_ids_array[@]}"; do 1423 | 1424 | tasker_config_utils_log 2 "" 1425 | tasker_config_utils_log 1 "Processing profile \"$profile_id\"" 1426 | 1427 | tasker_config_utils_log 2 "Extracting the profile name of profile $profile_id from exported_tasker_config" 1428 | 1429 | #extract profile name of profile with id matching profile_id 1430 | profile_name="$(tasker_config_utils extract_tag -p --pre_tag=''"$profile_id"'<\/id>' --tag='nme' "$exported_tasker_config")" 1431 | return_value=$? 1432 | if [ $return_value -ne 0 ]; then 1433 | tasker_config_utils_log_errors "Failed to get profile name of profile $profile_id from exported_tasker_config" 1434 | return $return_value 1435 | fi 1436 | 1437 | profiles_info_list+=$'\n\n'"### Profile $i" 1438 | 1439 | #if profile_name is not set 1440 | if [ -z "$profile_name" ] ; then 1441 | profile_name="Anonymous ($profile_id)" 1442 | fi 1443 | 1444 | profile_name_inline_code="$(convert_string_to_markdown_code "inline-code" "$profile_name")" 1445 | profiles_name_list+=$'\n'"- $profile_name_inline_code" 1446 | profiles_info_list+=$'\n**Name:** '"$profile_name_inline_code " 1447 | 1448 | profiles_info_list+=$'\n**ID:** `'"$profile_id"'` ' 1449 | 1450 | tasker_config_utils_log 2 "Extracting the profile entry task id of profile $profile_id from exported_tasker_config" 1451 | 1452 | #extract entry task id from the tag 1453 | profile_entry_task_id="$(tasker_config_utils extract_tag -p --tag='mid0' --pre_tag=''"$profile_id"'<\/id>' "$exported_tasker_config")" 1454 | return_value=$? 1455 | if [ $return_value -ne 0 ]; then 1456 | tasker_config_utils_log_errors "Failed to get profile entry task id of profile $profile_id from exported_tasker_config" 1457 | return $return_value 1458 | fi 1459 | 1460 | #if profile_entry_task_id is set 1461 | if [ ! -z "$profile_entry_task_id" ]; then 1462 | #if profile_entry_task_id is not valid 1463 | if [[ ! "$profile_entry_task_id" =~ $valid_number_regex ]]; then 1464 | tasker_config_utils_log_errors "The profile_entry_task_id \"$profile_entry_task_id\" extracted of profile $profile_id is not a valid number" 1465 | return 1 1466 | fi 1467 | 1468 | #extract task name of task with id matching profile_entry_task_id 1469 | task_name="$(tasker_config_utils extract_tag -t --pre_tag=''"$profile_entry_task_id"'<\/id>' --tag='nme' "$exported_tasker_config")" 1470 | return_value=$? 1471 | if [ $return_value -ne 0 ]; then 1472 | tasker_config_utils_log_errors "Failed to get task name of profile $profile_id entry task from exported_tasker_config" 1473 | return $return_value 1474 | fi 1475 | 1476 | #if task_name is not set 1477 | if [ -z "$task_name" ] ; then 1478 | task_name="Anonymous ($profile_entry_task_id)" 1479 | fi 1480 | 1481 | task_name_inline_code="$(convert_string_to_markdown_code "inline-code" "$task_name")" 1482 | profiles_info_list+=$'\n**Entry Task:** '"$task_name_inline_code " 1483 | fi 1484 | 1485 | tasker_config_utils_log 2 "Extracting the profile exit task id of profile $profile_id from exported_tasker_config" 1486 | 1487 | #extract exit task id from the tag 1488 | profile_exit_task_id="$(tasker_config_utils extract_tag -p --tag='mid1' --pre_tag=''"$profile_id"'<\/id>' "$exported_tasker_config")" 1489 | return_value=$? 1490 | if [ $return_value -ne 0 ]; then 1491 | tasker_config_utils_log_errors "Failed to get profile exit task id of profile $profile_id from exported_tasker_config" 1492 | return $return_value 1493 | fi 1494 | 1495 | #if profile_exit_task_id is set 1496 | if [ ! -z "$profile_exit_task_id" ]; then 1497 | #if profile_exit_task_id is not valid 1498 | if [[ ! "$profile_exit_task_id" =~ $valid_number_regex ]]; then 1499 | tasker_config_utils_log_errors "The profile_exit_task_id \"$profile_exit_task_id\" extracted of profile $profile_id is not a valid number" 1500 | return 1 1501 | fi 1502 | 1503 | #extract task name of task with id matching profile_exit_task_id 1504 | task_name="$(tasker_config_utils extract_tag -t --pre_tag=''"$profile_exit_task_id"'<\/id>' --tag='nme' "$exported_tasker_config")" 1505 | return_value=$? 1506 | if [ $return_value -ne 0 ]; then 1507 | tasker_config_utils_log_errors "Failed to get task name of profile $profile_id exit task from exported_tasker_config" 1508 | return $return_value 1509 | fi 1510 | 1511 | #if task_name is not set 1512 | if [ -z "$task_name" ] ; then 1513 | task_name="Anonymous ($profile_exit_task_id)" 1514 | fi 1515 | 1516 | task_name_inline_code="$(convert_string_to_markdown_code "inline-code" "$task_name")" 1517 | profiles_info_list+=$'\n**Exit Task:** '"$task_name_inline_code " 1518 | fi 1519 | 1520 | tasker_config_utils_log 2 "Extracting the profile comment of profile $profile_id from exported_tasker_config" 1521 | 1522 | #extract comment from the tag 1523 | profile_comment="$(tasker_config_utils extract_tag -p --tag='pc' --pre_tag=''"$profile_id"'<\/id>' "$exported_tasker_config")" 1524 | return_value=$? 1525 | if [ $return_value -ne 0 ]; then 1526 | tasker_config_utils_log_errors "Failed to get profile comment of profile $profile_id from exported_tasker_config" 1527 | return $return_value 1528 | fi 1529 | 1530 | #if profile_comment is set 1531 | if [ ! -z "$profile_comment" ]; then 1532 | profiles_info_list+=$'\n\n#### Comment:\n\n'"$profile_comment" 1533 | else 1534 | profiles_info_list+=$'\n**Comment:** `-`' 1535 | fi 1536 | 1537 | profiles_info_list+=$'\n##\n \n' 1538 | 1539 | i=$(( i + 1 )) 1540 | done 1541 | 1542 | 1543 | 1544 | ###Generate Scenes Info 1545 | 1546 | tasker_config_utils_log_literal 1 "\n" 1547 | tasker_config_utils_log 1 "Generating Scenes Info" 1548 | 1549 | #if tasker_config_scenes are set 1550 | IFS=, read -ra tasker_config_scenes_array <<< "$tasker_config_scenes" 1551 | 1552 | scenes_name_list+=$'\n**Count:** `'"${#tasker_config_scenes_array[@]}"'`'$'\n' 1553 | 1554 | for scene_name in "${tasker_config_scenes_array[@]}"; do 1555 | 1556 | tasker_config_utils_log 2 "" 1557 | tasker_config_utils_log 1 "Processing scene \"$scene_name\"" 1558 | 1559 | scene_name_inline_code="$(convert_string_to_markdown_code "inline-code" "$scene_name")" 1560 | scenes_name_list+=$'\n'"- $scene_name_inline_code" 1561 | done 1562 | 1563 | 1564 | 1565 | ###Generate Tasks Info 1566 | 1567 | tasker_config_utils_log_literal 1 "\n" 1568 | tasker_config_utils_log 1 "Generating Tasks Info" 1569 | 1570 | IFS=, read -ra exported_tasker_config_task_ids_array <<< "$exported_tasker_config_task_ids" 1571 | 1572 | tasks_name_list+=$'\n**Count:** `'"${#exported_tasker_config_task_ids_array[@]}"'`'$'\n' 1573 | 1574 | i=1 1575 | for task_id in "${exported_tasker_config_task_ids_array[@]}"; do 1576 | 1577 | tasker_config_utils_log 2 "" 1578 | tasker_config_utils_log 1 "Processing task \"$task_id\"" 1579 | 1580 | tasker_config_utils_log 2 "Extracting the task name of task $task_id from exported_tasker_config" 1581 | 1582 | #extract task name of task with id matching task_id 1583 | task_name="$(tasker_config_utils extract_tag -t --pre_tag=''"$task_id"'<\/id>' --tag='nme' "$exported_tasker_config")" 1584 | return_value=$? 1585 | if [ $return_value -ne 0 ]; then 1586 | tasker_config_utils_log_errors "Failed to get task name of task $task_id from exported_tasker_config" 1587 | return $return_value 1588 | fi 1589 | 1590 | tasks_info_list+=$'\n\n'"### Task $i" 1591 | 1592 | #if task_name is not set 1593 | if [ -z "$task_name" ] ; then 1594 | task_name="Anonymous ($task_id)" 1595 | fi 1596 | 1597 | task_name_inline_code="$(convert_string_to_markdown_code "inline-code" "$task_name")" 1598 | tasks_name_list+=$'\n'"- $task_name_inline_code" 1599 | tasks_info_list+=$'\n**Name:** '"$task_name_inline_code " 1600 | 1601 | tasks_info_list+=$'\n**ID:** `'"$task_id"'` ' 1602 | 1603 | tasker_config_utils_log 2 "Extracting the collision handling value of task $task_id from exported_tasker_config" 1604 | 1605 | #extract collision handling from the tag 1606 | collision_handling_value="$(tasker_config_utils extract_tag -t --tag='rty' --pre_tag=''"$task_id"'<\/id>' "$exported_tasker_config")" 1607 | return_value=$? 1608 | if [ $return_value -ne 0 ]; then 1609 | tasker_config_utils_log_errors "Failed to get collision handling value of task $task_id from exported_tasker_config" 1610 | return $return_value 1611 | fi 1612 | 1613 | #if collision_handling_value is set 1614 | if [ ! -z "$collision_handling_value" ]; then 1615 | #if collision_handling_value is not valid 1616 | if [[ ! "$collision_handling_value" =~ ^[0-2]$ ]]; then 1617 | tasker_config_utils_log_errors "The collision_handling_value \"$collision_handling_value\" extracted of task $task_id is not a valid value" 1618 | return 1 1619 | fi 1620 | 1621 | if [[ "$collision_handling_value" == "0" ]]; then 1622 | tasks_info_list+=$'\n**Collision Handling:** `'"Abort New Task"'` ' 1623 | elif [[ "$collision_handling_value" == "1" ]]; then 1624 | tasks_info_list+=$'\n**Collision Handling:** `'"Abort Existing Task"'` ' 1625 | elif [[ "$collision_handling_value" == "2" ]]; then 1626 | tasks_info_list+=$'\n**Collision Handling:** `'"Run Both Together"'` ' 1627 | fi 1628 | else 1629 | tasks_info_list+=$'\n**Collision Handling:** `'"Abort New Task"'` ' 1630 | fi 1631 | 1632 | 1633 | tasker_config_utils_log 2 "Extracting the keep device awake value of task $task_id from exported_tasker_config" 1634 | 1635 | #extract keep device awake from the tag 1636 | keep_device_awake_value="$(tasker_config_utils extract_tag -t --tag='stayawake' --pre_tag=''"$task_id"'<\/id>' "$exported_tasker_config")" 1637 | return_value=$? 1638 | if [ $return_value -ne 0 ]; then 1639 | tasker_config_utils_log_errors "Failed to get keep device awake value of task $task_id from exported_tasker_config" 1640 | return $return_value 1641 | fi 1642 | 1643 | #if keep_device_awake_value is set 1644 | if [ ! -z "$keep_device_awake_value" ]; then 1645 | #if collision_handling_value is not valid 1646 | if [[ ! "$keep_device_awake_value" =~ ^true|false$ ]]; then 1647 | tasker_config_utils_log_errors "The keep_device_awake_value \"$keep_device_awake_value\" extracted of task $task_id is not a valid value" 1648 | return 1 1649 | fi 1650 | 1651 | tasks_info_list+=$'\n**Keep Device Awake:** `'"$keep_device_awake_value"'` ' 1652 | 1653 | else 1654 | tasks_info_list+=$'\n**Keep Device Awake:** `'"false"'` ' 1655 | fi 1656 | 1657 | tasker_config_utils_log 2 "Extracting help anchor of task $task_id from exported_tasker_config" 1658 | 1659 | #extract help anchor of task which should be the first action of the task 1660 | #use -E for extended regex, and -n to disable printing 1661 | #sed -nE '/^\t]*>$/' #match Task sr line 1662 | # { #if matched start a subscript 1663 | # :a; #create a label called a 1664 | # N; #add next line to pattern space 1665 | # #if pattern space does not end with 1666 | # / 1667 | # \n\t 1668 | # ( 1669 | # #a sr line of a subnode of Task node 1670 | # (\t<[a-zA-Z0-9]+ sr="[^"]*"[^>]*>$) 1671 | # | 1672 | # #or the ending tag of the Task node 1673 | # (<\/Task>$) 1674 | # )" 1675 | # #go to label a; 1676 | # /!ba; 1677 | # }' 1678 | # #if pattern space matches an id tag matching the task_id 1679 | # /.*'"$task_id"'<\/id>.*/ 1680 | # { #start another subscript 1681 | # :b; #create a label called b 1682 | # N; #add next line to pattern space 1683 | # #if pattern space does not end with "\n\t$" go to label b; 1684 | # /\n\t<\/Task>(\n.*)?$/!bb 1685 | # #if pattern space matches 1686 | # s/.*\n 1687 | # #the opening tag of action 0 1688 | # \t\t]*>\n 1689 | # #matching an anchor action with code 300 1690 | # \t\t\t300<\/code>\n 1691 | # #with a label tag containing one or more characters 1692 | # \t\t\t