Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Anatoli Babenia
    @abitrolly
    I found :[[table]] earlier in manual and it works perfectly, thanks. I want to understand combymore.
    Rijnard van Tonder
    @rvantonder

    but shouldn't the shortest path win for second :[table] match?

    It depends what you expect to terminate this path to give you the "shortest path". Should the shortest path cut off when there is a whitespace character? Or maybe the next line? These options are all useful, but quite different. In comby the meaning (semantics) of :[hole] is to match everything (all characters, including spaces and newlines) until the part that comes right after the hole. In your original example, there is nothing that comes right after the hole (not even whitespace). It is empty. With an empty string, we can either match nothing (that would not be useful) or continue matching to the end of the file (because the part after the hole is interpreted as "end of file). Note that the other hole kinds exist when you don't want this behavior, and instead something like matching words, or lines.

    Second :[table] also doesn't match if I add ( instead of space

    This is by design: it is not possible to use or match dangling parentheses in the source code. Well, there are exceptions I won't go into, but the idea is that you shouldn't use dangling parentheses to match/rewrite because that could make it easy to mess up things. The approach I would recommend is to match all such syntactic expressions, and just rewrite them without changing, like CREATE TABLE :[table] (:[body]). (example: https://bit.ly/2NLJWli)

    Anatoli Babenia
    @abitrolly
    @rvantonder got it. :[hole] matching is logical. Maybe unusual for a regexp user where "match everything" is always non-conditional explicit element. Now it is clear why there is a separate explanation about whitespace for :[hole]s. With "match all until current context" there will be a lot of work to filter out all whitespace that matched and concentrate only on things that have meaning other than "delimiter".
    Daniel Hines
    @d4hines
    Is there a way to generate a random string in a comby replacement?
    Rijnard van Tonder
    @rvantonder
    Unfortunately no. I've thought about allowing some kind of syntax in the rewrite side that could introduce a fresh identifier (random string or integer). This would be pretty straightforward, so I can throw together something easily and mark it experimental. Any needs more particular than just a "random string"?
    Daniel Hines
    @d4hines
    Well, we had it come up at work that we want to disallow anonymous functions in our (rather large) code base, and I thought this would be low hanging fruit for Comby. Being able to generate a new, non-colliding name for the function will allow it to perform a non-breaking transformation on the file.
    Either random string or integer would be fine for this case.
    Rijnard van Tonder
    @rvantonder
    Makes sense. I'll try put something together by end of day :)
    Daniel Hines
    @d4hines
    Nice! Thanks!
    Rijnard van Tonder
    @rvantonder
    Hey @d4hines I published this in 0.13.1: https://github.com/comby-tools/comby/releases/tag/0.13.1. You can either grab it from source, docker, or binaries from that release page (which or may not work for your platform). It'll take probably until the end of the week to show up in brew. Example in live environment: https://bit.ly/2UmkK8P
    Daniel Hines
    @d4hines
    Thanks @rvantonder! The syntax looks great!
    Daniel Hines
    @d4hines
    Doh! @rvantonder I just realized I need to reference the generated ID later on in the pattern. Is there a way to do that?
    Here's my example: https://bit.ly/2UD8IIG . For it to be non-breaking, I have to both lift the anonymous function into a const, and then reference that const later on.
    Rijnard van Tonder
    @rvantonder

    @d4hines ah, yeah that use case makes sense. I think I'll tweak it so that you can reference to the same ID generated by passing your own label to id(). So you could do something like

    const anon_:[id(my_label)] = ...; 
    anon_:[id(my_label)](...);

    where using my_label substitutes the same hash. Give me a couple of days :)

    Daniel Hines
    @d4hines
    That's exactly the syntax I was thinking would make sense.
    Thanks Rijnard!
    Daniel Hines
    @d4hines
    Thought: Comby would be amazing as a VS Code extension. I often want to do transformations on a document that exceed Regex. having Comby built into the workbench would make this seamless!
    Rijnard van Tonder
    @rvantonder
    Ah nice! Someone published this prototype: https://marketplace.visualstudio.com/items?itemName=giltho.comby-vscode. My understanding is there are some snags with vscode to make this work properly. Example: giltho/comby-vscode#1. Also consider subscribing to this issue tracker for context and updates: comby-tools/comby#103
    Daniel Hines
    @d4hines

    Ok, here's one I'm not sure how to tackle: I've got a list of ES module imports at the top of my file. They're all jumbled up:

    import { get } from "lodash";
    import { Foo } from "./foo";
    import { uuid } from "uuid/v4";

    but I want to sort them like so:

    // external library imports
    import { get } from "lodash";
    import { uuid } from "uuid/v4";
    
    // internal imports
    import { Foo } from "./foo";

    Can comby do this for me?

    Rijnard van Tonder
    @rvantonder
    That's a tricky one, I don't think so. In general this sort of change (which is a use case I've come across before) requires two things: a set data structure, and an ordering relation. For example, you'd have sets of values for all your imports, and then define an ordering over those sets (lowercase before uppercase, and then alphabetical). There's no abstraction for that currently. The closest I think you could get is extracting imports to a temporary file (using the -newline-separated option) which becomes your "set", then doing the computation for sorting (with sort or a scripting language or such), and then substituting the imports back. But there isn't a direct way to the 'substituting back' part for this use case, so that would also need something else. You could, e.g., use comby to write the imports to a separate file, use comby to erase the imports for the current file, and then prepend the sorted output to substitute it all back. So it's possible to do this, but the number of hoops to jump through means it's not well suited to the task.
    As for the :[id(label)] addition, that'll be merged/released by Monday :-) comby-tools/comby#169
    Anatoli Babenia
    @abitrolly
    Hi Rijnard. I am trying to rewrite YAML file from one format to another. Everything goes well, except for for indentation. I tried using :[ leading_indentation]but fails to match bit.ly/2uUkEej
    Rijnard van Tonder
    @rvantonder

    Hey @abitrolly. So in general comby can't do indentation-sensitive matching. The :[ leading_whitespace] hole would not apply to the whole :[body] and would only, in the best case, match the leading indentation of the first line after :[name]. This is a known limitation and I need to add a feature (it is planned) to allow indentation-sensitive block matching.

    If you are OK with only matching the leading indentation of the line after :[name], then you can use bit.ly/2V1cyeO but as you can see it doesn't preserve the relative indentation of the body, and I don't think it solves your problem.

    YAML has come up quite often so maybe I should just prioritize this. The idea is that you would just do

    name: :[[name]]
      :[body]

    and comby would know that if you are targeting YAML, to match everything at the indentation level of :[body], and when you put <space>:[body] in the rewrite, it would add <space> to every line. But this doesn't exist yet unfortunately.

    Anatoli Babenia
    @abitrolly
    <space>:[body] with space to every line is an often needed pattern in many template engines, not just in comby. That would be useful, indeed.
    Rijnard van Tonder
    @rvantonder

    True. Well, you can already add line-based indentation with a
    rewrite ... rule, like so:

    where rewrite 
    :[body] { ":[line\\n]" -> "     :[line]" }

    bit.ly/3bS2w5t

    The idea with YAML would be to intelligently match blocks, and indent without a rewrite rule.

    Daniel Hines
    @d4hines
    The button on the "try it live" page to copy the command line args is :ok_hand:
    Teguh Hofstee
    @hofstee
    Is there a way of matching both strings in single quotes ' and " double quotes with a single rule? I've run into this a few times when I want to rewrite some Python but I end up having to create two rules that match strings of each delimiter type. Maybe something like a language-aware "match a string with its delimiters" would be a nice feature to have?
    Rijnard van Tonder
    @rvantonder

    hey @hofstee. This is a good use case that isn't available generally yet. A hole that does "match a string with its delimiters" is the right thing to support. A related issue has come up where you'd want a different kind of hole to match "a sequence of strings with balanced delimiters", i.e., match (foo), foo(), foo(bar(), baz), but not foo() bar(), using a single kind hole. I have been working on a way to introduce this so that the hole syntax doesn't get out of control (more updates soon). So your use case will get incorporated into that. The basic idea is to support a syntax that lets you optionally specify the semantics, so a syntax like :[x:string] would match what you want for the language.

    For now, there is one possible workaround, but I'm not confident it'll work for you in the general case. Basically, you can match on every line in the file and then use a rewrite rule to rewrite each matching case (whether it is single or double quotes): https://bit.ly/2TiThCT

    Carlos Rodriguez Guette
    @carlosrogue
    Hi, I created a template directory but when running I have an error: missing anonymous argument: REWRITE_TEMPLATE. I created the <dir>/matcherand <dir>/rewrite files so no idea what is wrong.
    Rijnard van Tonder
    @rvantonder
    Hey @carlosrogue. Just use -f to filter files (using the flag) and don't supply any anonymous arguments. The anonymous arguments can only take one match-rewrite pattern, so when using a directory it's not possible to specify anonymous arguments.
    Subscribe to this issue so you can get notified when I improve/fix this: comby-tools/comby#161
    Carlos Rodriguez Guette
    @carlosrogue
    @rvantonder I found the problem, an empty unsaved match file and then just emacs adding an extra line at the end of my template files: Nothing matched, :smile:
    Rijnard van Tonder
    @rvantonder
    okay :)
    Carlos Rodriguez Guette
    @carlosrogue

    @rvantonder I have a match like this:

          | where     | sku="S1"              |
          | sort      | availableQuantity asc |

    If there a way rewrite could parse recursively the matched lines to achieve: where -> 'sky="S1"' sort -> 'availableQuantity asc'

    Carlos Rodriguez Guette
    @carlosrogue
    I just got it right at the first attempt to write it: rewrite :[params] { "| :[param.] | :[value] |" -> ":[param] -> ':[value]'"}
    Carlos Rodriguez Guette
    @carlosrogue
    Why :[url.] works on web but doesn't match anything on cmd line? What is the difference between the two when using . ? I am using zsh on Mac
    Rijnard van Tonder
    @rvantonder
    There shouldn't be any difference. I also have zsh on Mac, so if you give me the example command line I can see if I can reproduce
    Carlos Rodriguez Guette
    @carlosrogue
    I found the magical problem! I just found myself in another "it does match on browser but not on local" case and, in this new case, some 2015 committed code matches but some 2013 code did not, :smile:
    Carlos Rodriguez Guette
    @carlosrogue
    Yes, there is weird control versioning encoding problem. If I copy/paste the old code to other location in the file...It gets matched! Something to do with \t\n, I guess. I will try to figure out afterwards.
    Carlos Rodriguez Guette
    @carlosrogue
    Nothing of that, I finally found the problem! I had similar expr for different cases and one behaves weird with the .generic matcher when " are present, so using .txt instead fixed my problem
    Ben Briggs
    @ben-eb

    Hello! :wave: Thanks for your work on comby, it looks really great! I was wondering if it was possible to make a pattern that could work across any number of matches? My case is that we have a couple of different ways of writing calls to _.get and I'd like to make those consistent. So I could write a pattern like:

    _.get(':[a].:[b]', :[c])

    then convert it:

    _.get([':[a]', ':[b]'], :[c])

    Which would produce:

    _.get('foo.bar', x);
    _.get(['foo', 'bar'], x)

    But would it be possible to work with any number of segments?

    Rijnard van Tonder
    @rvantonder

    Hi! Just to clarify first :) What are the variations that you want to handle? Cases where foo.bar occurs in another argument position? like

    _.get(a, 'foo.bar', b);
    _.get(a, b, 'foo.bar', ....);

    or variations where you have foo.bar.baz and break that up to ['foo', 'bar', 'baz'], or both? or something else?

    In general, you can do repetitions/variations either with multiple templates (currently this is a bit tedious), or rewrite rules. But it may not fit your use case perfectly depending on some things, so it'd be great to know what some of the variations are.
    Ben Briggs
    @ben-eb
    @rvantonder Sure - the variants are in the first parameter, so like you said with foo.bar.baz converting to an array of those segments. I could do the multiple template thing but was wondering if there was a better alternative I wasn't aware of :)
    Rijnard van Tonder
    @rvantonder
    @ben-eb Got it. Sorry for the lag :-) Well, there's something that can do this for you with rewrite rules, assuming the foos and bars are alphanumeric strings. I won't claim it's very straightforward, but it does get around the issue of multiple templates :)

    So you can have a rule like

    where 
    rewrite :[1] { ":[[a]].:[[b]]" -> "':[[a]]', ':[[b]]'" },
    rewrite :[1] { "':[[a]]'.':[[b]]'" -> "':[[a]]', ':[[b]]'" },
    rewrite :[1] { "':[[a]]'.:[[b]]" -> "':[[a]]', ':[[b]]'" }

    Basically, each rule here performs a 'reduction' of the original string to some comma separation. In this case I needed three rules to catch all the cases.

    You can try playing with the rules yourself to see what each one does, in the live environment: https://bit.ly/2vA97kO. Just make sure you expand that rule box so you can see what I posted above
    Ben Briggs
    @ben-eb
    @rvantonder That's awesome! Thanks very much :D
    Rijnard van Tonder
    @rvantonder
    @ben-eb glad that's useful to you :) have a great weekend