jlegewie / zotfile

Zotero plugin to manage your attachments: automatically rename, move, and attach PDFs (or other files) to Zotero items, sync PDFs from your Zotero library to your (mobile) PDF reader (e.g. an iPad, Android tablet, etc.), and extract PDF annotations.
4.06k stars 282 forks source link

New wildcard function for replace #546

Open josephgarnier opened 3 years ago

josephgarnier commented 3 years ago

Please note that the PR include my previous PR #544.

Currently for a "rename and move" action, it is not possible to specify a user-defined wildcard that use a replace function with something other than a string as replacement. For example, if I want my files to be moved into directories named after my collection names after they have been transformed according to the "every word starts with a capital letter" rule, this is not possible.

00 01

To perform the operation described above, the regex and json to be used are the following:

"2": {
    "default": {
      "field": "collectionPaths",
      "operations": [
        {
          "function": "replace",
          "regex": "(^|\\s+|_+|\\/)(\\w{1})(?![nd|r]{1})",
          "replacement": "????"
        }
      ]
    }
  }

But it is clear that it is impossible to specify what to replace the matches with. So in this PR, I propose the possibility to use as replacement "a string" (the current behavior) or a "js function". Behind the scene, this means that we won't just use string.replace with a string as parameter, but rather, string.replace with a function as parameter (see the js doc).

Thus with this PR, it is now possible to perform a complex operation on a match using this json format:

"<id>": {
    "default": {
      "field": "<a field>",
      "operations": [
        {
          "function": "replace",
          "regex": "<a regex>",
          "replacementFunction": {
            "arguments": [
              "<arg1>",
              "<arg2>",
              "...",
              "<argn>"
            ],
            "body": "<my js code>; return <my returned string>;"
          }
        }
      ]
    }

Applied to my initial example, this would give :

"2": {
    "default": {
      "field": "collectionPaths",
      "operations": [
        {
          "function": "replace",
          "regex": "(^|\\s+|_+|\\/)(\\w{1})(?![nd|r]{1})",
          "replacementFunction": {
            "arguments": [
              "match",
              "g1",
              "g2",
              "offset",
              "string"
            ],
            "body": "return g1.concat(g2.toUpperCase());"
          }
        }
      ]
    }
raphaelhuleux commented 1 year ago

+1