I just started using comby and really enjoy it—thank you! I have a question that seems really basic but I couldn't figure it out from the docs. How do I limit a hole to a certain number of arguments? For example, in https://bit.ly/3q59MTs I want to match and rewrite the first two lines, but not the third:
foo(1, 2)
foo(1, boo(2, 3))
foo(1, 2, true, 3)
I can match everything with foo(:[a], :[b])
; I can match just the third line with foo(:[a], :[b], :[rest])
, but I can't figure out how to match only two arguments.
Hey @ryangreenberg, bit late responding here. You probably want to try something like this to match 2 arguments:
foo(:[a:e], :[b:e])
Example: https://bit.ly/32g4c8C
What's happening there is :[a]
and :[b]
are restricted to matching "expression-like" syntax and won't continue matching across whitespace at the same block or expression level. There isn't a built-in notion for matching arguments (or a certain number of them), but I think you can make progress by using the hole that matches expression-like syntax (where arguments generally correspond to arguments).
There's a longer description in the docs: https://comby.dev/docs/syntax-reference.
Hello. I'm new to Comby. I find the idea really awesome and I was wondering if I could not use it for one of my project. To keep it simple, I would like to take a snippet of code (I need to support many languages such as Python, Javascript, HTML, etc..) and basically strip out comments (potentially multiline) as well as non meaningful whitespaces (for instance in Python the indentation matters, but in Javascript it could essentially be collapse to one line)
Maybe Comby is not the right tool for the job, but when I see that it has support for all the languages I need and all the hard work of parsing the syntax has been done, I though there might be a way.
hey @francoisproulx_twitter! so in short, there isn't an exact way to strip out comments, but there may be ways to do something like that. basically, comments are treated like whitespace, and right now it's not possible to match directly on comments. It's something that may be possible in future, but not right now. Right now, you could, for example, match all whitespace in some code (which will include comments) and then filter out the parts that are just whitespace with a submatch (regex), leaving only the comments.
as well as non meaningful whitespaces (for instance in Python the indentation matters, but in Javascript it could essentially be collapse to one line)
this is tricky with comby, it doesn't recognize different kinds of whitespace (no whitespace is meaningful). this means that matching or preserving indentation-sensitive (AKA layout-sensitive) syntax doesn't work out of the box.
It sounds like you want to do some kind of normalization on code (you mentioned a "stable fingerprint" in the tweet :-)). I think you can achieve a good degree of this by just normalizing whitespace and stripping out comments like your idea, but I don't see a clear way of dealing with layout-sensitive languages (e.g., Python). A hacky way to deal with Python, for example, could be to run pyindent (which will add braces to blocks) and which comby can then process and "normalize". So you can then map python code to this footprint, but the stable footprint/representation of the Python code will not match the source input, which could be a problem depending on what you want to do with those snippets.
@francoisproulx_twitter ah you know what, I tried to grab you an example but I think it's not quite possible the way I thought you could do it. The best kind of stripping you can do right now is along that idea, you just match whitespace (a space " ") and replace with a space (" "). This will strip comments. Example (note, the match and rewrite parts are just a space): https://bit.ly/35xEcXW
Sadly, this will not preserve the number of whitespace or newlines (which is what I thought would be possible), so it all ends up on one line. The trouble is that there isn't a way to refer to the matched whitespace. If there were, you could preserve the matched parts and more carefully strip out comments. So I don't know if this is helps. Note that you can still use comby generally to match, say, on function bodies, and strip out comments within function bodies with the same idea (so you would get the function body, one on each line), by using a rewrite rule. But again, you cannot preserve the whitespace within that body. Example: https://bit.ly/3HBuhit
Can i rewrite under a certain condition?
For example, replace sign with ">" only if it's equal to "<"
My exampl: bit.ly/337HaBN
(match);
the group (...)
is going to store the value match
and ;
is not going to be part of it. it is lazy (will stop matching when it sees the first ;
): https://comby.dev/docs/syntax-reference. If you want to include the ;
use :[value.]
:[value.]
won't work for you here because I see the data is a string. In this case, your best idea is to reintroduce the ;
in the output
I don't quite understand how it works. After all, if you specify ";" two times, then ";" will be part of the value
Example: bit.ly/3Iv5Sve
;
. it is not just ending on that line. it is ending in ; <newline>else return...
and the match will be found depending on the content that satisfies the entire suffix. again, same as regex: https://regexr.com/6gabn
x;
with ;
is also captured if you add a ;
there
Activity.list().last()
to (await (await Activity.list()).last())
in a generic way. I was hoping to use :[var.]
syntax but that doesn't include the parens. I'm guessing this is more of a tree transformation than the kind of substitution that comby can do. I'd love to be proven wrong though!
(...)
, including spaces
bar()
without matching foobar()
. I was able to make it work by putting :[~\b]
before the word, but that feels like an oddly complex way to invoke a behavior that, if anything, I'd expect to be the default. Just wondering.
sed
). I haven't had many questions/confusion about this property, but if there were more cases like this I would start thinking about changing the default. Usually, it seems, replacements have enough specificity that this issue doesn't come up that often.
but the actual translation is with the spaces mandatory
<bracket><spaces><any_variable_or_statement_or_nothing>
Hi all - wondering if someone could help me understand how the whitespace matching works. I'm trying to move a method expectation into the method, something like:
@Test(expected = IllegalArgumentException.class)
public void lengthOf7CannotSupportMoreThan90Years() {
ReferenceEncoder unitUnderTest = new ReferenceEncoder(LENGTH_FOR_90_YEARS);
unitUnderTest.getBase64FromLong(millisInMoreThan90Years);
}
should become
@Test
public void lengthOf7CannotSupportMoreThan90Years() {
org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, ()-> {
ReferenceEncoder unitUnderTest = new ReferenceEncoder(LENGTH_FOR_90_YEARS);
unitUnderTest.getBase64FromLong(millisInMoreThan90Years);
});
}
Using this recipe:
match='''@Test(expected = :[ex])
public void :[testname]() {
:[testbody]
}'''
rewrite='''@Test
public void :[testname]() {
org.junit.jupiter.api.Assertions.assertThrows(:[ex], ()-> {
:[testbody]
});
}'''
This works, however, it's chopping the indentation off the first line. So I thought I could use :[ var]
(as per the documentation here https://comby.dev/docs/syntax-reference) to match the whitespace at the beginning of the first line, and reinsert it afterwards, something like:
match='''@Test(expected = :[ex])
:[ ws1]public void :[testname]() {
:[testbody]
:[ ws2]}'''
rewrite='''@Test
:[ ws1]public void :[testname]() {
org.junit.jupiter.api.Assertions.assertThrows(:[ex], ()-> {
:[testbody]
});
:[ ws2]}'''
But when I do this, it no longer matches my method at all (I have also tested this on the web playground, and it doesn't match there either). Any suggestions?
Hey! Comby is so awesome 😍 I have one question regarding structural rewriting and ignoring whitespace. I'm in a TS/JS code base, so I'm using Prettier to take care of formatting. When I want to rewrite expressions of the form expect(xxx).toEqual(yyy)
, then it depends whether those are formatted on one line, or over multiple lines, and I wonder if there is a mode in which to use comby where I can effectively treat the punctuation like (
and )
as a pattern that eats up surrounding whitespace as well? Perhaps with a flag on the cmdline or something?
Ideally, there would be some kind of mode where it would not care about how I write my input expression, i.e. 'foo(x, y: z)'
, or 'foo ( x , y : z ) '
or 'foo(x,y:z)'
would all work as the first argument to comby, and mean the same thing.
I would want to write:
comby 'expect(:[1]).toEqual(JSON.stringify(:[2]))' 'expect(JSON.parse(:[1])).toEqual(:[2])' -i ts
But to do what I want I effectively write this pattern first, and then "hack" support for what I want into it, by adding :[~\s*]
holes manually, like so:
comby 'expect:[~\s*](:[~\s*]:[1]:[~\s*]):[~\s*].:[~\s*]toEqual:[~\s*](:[~\s*]JSON:[~\s*].:[~\s*]stringify:[~\s*](:[~\s*]:[2]):[~\s*])' 'expect(JSON.parse(:[1])).toEqual(:[2])' -i ts
Of course, this will destroy whitespace in the output, but I don't care, because that's trivial to fix by re-running prettier.
Is there an option for this? Thx! 🙏
foo
would not match myfoo
. I'm currently doing that by surrounding my identifiers with :[~\b]
markers… :grimacing: Not sure if I'm doing this wrong… :smile: