Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Rijnard van Tonder
    @rvantonder

    Hey @volkanunsal! Are you using a configuration file like this: https://comby.dev/docs/configuration

    or a directory layout like this: https://comby.dev/docs/cheat-sheet#run-multiple-search-and-replace-templates

    For configuration files, you'll have to point to -config ./your-file.toml. For directories, the directory (in this case, the current one) would need to contain a file called match with the pattern.

    Volkan Unsal
    @volkanunsal
    Ahhhh... so that's what the match file is. I totally didn't get that was the name of the file and thought perhaps it wasn't matching anything.
    After correcting the command to comby -config comby.toml -f .jsx it seems to be working. :)
    Rijnard van Tonder
    @rvantonder
    Yeah, there are two modes for that flag, so it's a bit confusing. Hope you got your pattern working now
    Monty Zukowski
    @montyz
    Hello, is comby suitable for distinguishing between different types of constants? I'd like to match a function call like setScore(:[1]) and then take different actions based on whether [:1 is a string literal, an integer, a decimal, or an expression. I see that pattern matching can use text or regex. Is there a way to dig a little deeper into comby's type of the match?
    Monty Zukowski
    @montyz
    Here's a stab at it https://bit.ly/36vdHRo. The issue right now is that I want setScore(4/3) to evaluate to true, but it matches against | ":[_~\\d+]" -> false because I guess it's matching against the prefix. Not sure how to get around that.
    Monty Zukowski
    @montyz
    This is a little better https://bit.ly/2SiuQFN I'm not so happy with how I did it, but I can't think of an alternative way.
    Rijnard van Tonder
    @rvantonder

    Hey @montyz . Casing out on syntax, like you're doing, is the only way to achieve this right now. Using a program's actual type information is something I've wanted to incorporate for a while, but depends a lot on the language. I'm curious what language you are working in, it might be a good fit for combining type info that way.

    For the rules, I think what you came up with is likely the closest you can get right now. The trouble you're having is that match will try find that pattern anywhere in the string (and like you say, matches the prefix). To control that, a helpful answer I want to give you is that you can use regex anchors ^...$ to match whether something is only digits (i.e., integer) and everything else should be checked (which seems to be what you're trying to do?). Unfortunately, that's missing from comby, but I coded up a fix here, and the rule becomes a lot simpler: https://github.com/comby-tools/comby/commit/cbdeaf8e1b4bb86557d6d60418568c0a3f1aca77#diff-f7592766e6cb7ff52ef4395d4e49389aR276-R279

    Monty Zukowski
    @montyz
    I'm working with JavaScript
    ah yeah that's helpful, thanks!
    Rijnard van Tonder
    @rvantonder
    I'll publish a release in the next day or two with the change.
    Monty Zukowski
    @montyz
    OK, thanks!
    Volkan Unsal
    @volkanunsal
    Thanks Rijnard. I got it working.
    I had another question for you, though. Is it possible to use "not" syntax in the -exclude flag. e.g.
    comby -config comby.toml -f .jsx -i -exclude '!*.comby.*'
    That is to say, don't include any files that don't have comby in the file name.
    Volkan Unsal
    @volkanunsal
    Actually, this is not so important. I can save the files with a different extension. :)
    Rijnard van Tonder
    @rvantonder

    That's probably best for now. -exclude '!...' sounds like a double negation so what you're probably really after is a way to include file paths like .*comby.*\.jsx? Piping results of a command like :

    find . -name "*comby*.jsx"is maybe another way. But yeah, there's no flag to do this only with comby right now

    Oliver Joseph Ash
    @OliverJAsh
    I am trying to convert a.pipe(b, c) to pipe(a, b, c). This should include versions like this.a.pipe(b, c) and this.a().pipe(b, c). It should not include versions like const object = { ...pipe(a, b, c) }.
    Can anyone recommend a way to match this precisely? I thought :[a.].pipe(:[b]) would do it, but it doesn't match new lines as I would want it to, and it incorrectly matches the object spread example I gave.
    For context the language is JavaScript/TS. Essentially the match should work on any call expression for a method called pipe
    Rijnard van Tonder
    @rvantonder

    Hey @OliverJAsh. Good question. Your intuition about :[a.] is good. The reason that doesn't work is because it doesn't match special syntax like (). There is an undocumented way to get what you want. It's undocumented because I was experimenting with more ways to match constructs like that one, but haven't settled on a suitable syntax yet :-).

    You can do so by changing :[a.] to :[a:e]: https://bit.ly/36JpYC6. You can think of the :e syntax meaning ' match an expression-like element'. It matches contiguous sequences of (...), {...}, [...] as well as characters matched by :[a.].

    Oliver Joseph Ash
    @OliverJAsh

    Awesome thank you @rvantonder. Do you have any ideas how I can get it to match new lines as well? E.g.

    this
      .a()
      .pipe(b, c)

    bit.ly/34Hhc4W

    Oliver Joseph Ash
    @OliverJAsh
    Unfortunately it looks like :[a:e] still matches the object spread example I gave bit.ly/3iLfIeB
    Rijnard van Tonder
    @rvantonder

    @OliverJAsh there isn't a very elegant way to deal with negating { matching-pattern } but in general you may be able to get away with using regex. Here's an example where you optionally match on leading or trailing { }s around your expression, and can use a rule to filter the match based on whether, say, start matched {, or the empty string: https://bit.ly/36OCuQD. Whether this works for you depends on whether that assumption is strong enough to filter out unwanted matches.

    I think it's real tricky to deal with matching that pattern over newlines. You can certainly tweak the matching to include newlines, but the problem is that it's difficult to distinguish statements like these in Comby:

    first.statement()
    second.statement()
      .across()
      .newline()

    , because it doesn't know enough about the JS grammar to understand the rules for sequencing with . and how it can spread over newlines/whitespace. The way I came up with would be to deal with this syntax in its own way, but I'm not sure that it'll work for you and it's crude. The idea is basically to say "OK, a chain can be something like an identifier followed by one or more lines that perform an access like .foo that must be prefixed by <whitespace><dot>". Once all that syntax is matched, I use a rule to rewrite the ones that call pipe https://bit.ly/3dg2mGs. I don't know if this works in general, it's just my attempt to deal with multi-line chains like this, and Comby might just not be a good fit for this problem until there's a way to teach it more about JS :-)

    Rijnard van Tonder
    @rvantonder
    Update, you'll probably want to use something more like https://bit.ly/2I6vd4e to match valid starts of an access chain.
    Oliver Joseph Ash
    @OliverJAsh
    Thank you for your help! <£
    <3
    AJ ONeal
    @coolaj86

    Is there a way to do text transformation?

    I have an application with hundreds of routes that look like this:

    app.get("/foo/bar", auth, (req, res) => {
      // ... do stuff
    })

    I want to convert them to something like this:

    app.get("/foo/bar", auth, getFooBar);
    function getFooBar (req, res) {
      // ... do stuff
    }
    AJ ONeal
    @coolaj86
    I'm close, but I don't see any docs for updating the strings bit.ly/38iqKH1
    Rijnard van Tonder
    @rvantonder

    @coolaj86 nice idea. Unfortunately there's no builtin for capitalizing strings/letters. That's something worth mentioning in the docs, so I'll update it. Capitalizing strings came up before a handful of times, so it might be something worth adding.

    Anyway, right now there is only a workaround using a rewrite rule--it works, but it's a bit silly :-) Assuming your routes are alphanumeric, you can rewrite parts of a string like /f to F for each letter. Here's a short version for getFooBar so you get the idea:

    where 
    match :[path] {| ":[fn]" -> true },
    rewrite :[fn] { "/f:[[w]]" -> "F:[w]" },
    rewrite :[fn] { "/b:[[w]]" -> "B:[w]" }

    https://bit.ly/362jA6I (expand the where... box.)

    I went ahead and made you a config file for your refactor with a rule that translates all the letters--I might just make a rule like this a builtin somewhere :-) See https://gist.github.com/rvantonder/01b930f7e5d081a5c84f6074fbf3bd13

    (FYI I generated the tedious part of the rule using comby https://bit.ly/323bNo4)

    AJ ONeal
    @coolaj86
    @rvantonder Thanks. There were a few things like that that I needed to do so I ran some JavaScript and RegExp.
    Rijnard van Tonder
    @rvantonder
    Cool @coolaj86 :-) I'd be interested to know what that ended up looking like, maybe I can more directly support that sort of thing
    AJ ONeal
    @coolaj86

    @rvantonder I found some bugs (Ithink), but I don't know if they're worth fixing:

    There was some code like this

    app.get('/*', foo)

    and it seemed to treat the string '/*' as a comment block.

    There was also a regex that it failed to ignore, it was something like this:

    app.get(/\(.*\)/, foo)

    and it seems to have interpreted the stuff in the regex as a closing ).

    I'll find out what it actually is and post the example.

    AJ ONeal
    @coolaj86
    Here's the one: bit.ly/2IcN0XZ
    Rijnard van Tonder
    @rvantonder
    That is... bizarre. Will look into it. The part about missing regex delimiters /../ makes a lot of sense, that's an easy one to add (thanks for reporting back!)
    Jens
    @jensim
    I wanna start of with saying comby looks really nice, all I need is help wrapping my head around some things..
    I've been using XmlStarlet to swap dependencies in maven pom.xml-files for things like javax->jakarta migrations, but xmlStarlet is limited to swapping one value at a time. In comes comby. I've been trying (and failing to write a template files that will match the xml for my dependencies and only swap the values for matched tags, leaving whitespace intact, not to confuse (or upset) the teams that will be receiving my mountain of PRs in the end. Here bit.ly/2UtSro6 is one of my attempts, that might shed some light on what im trying to do. And here bit.ly/3eX3mQB is a naive attempt, that does not respect original indentation style.
    Rijnard van Tonder
    @rvantonder

    Hey @jensim, I can think of two ways to go about this. I think the easiest might be to do your changes and re-format the files for the appropriate indentation (I think you have lots of options here with existing tools).

    There's probably a way to get comby to rewrite it while preserving whitespace, but it means you have to match carefully on tags or blocks to dance around rewriting things that could erase whitespace, here's some examples that might help your case: https://gist.github.com/rvantonder/324a4f1c3a46b15628b72745679bf821

    5 replies
    Stephen Gutekanst
    @slimsag
    Hello :) I'm wondering about integrating Comby search syntax into another search syntax and have a few questions (I'll put details in a thread to avoid spamming)
    18 replies
    ben.txt
    @bentxt
    Hi, comby looks very interesting but even after reading the documentation I'm not sure how far you can go with it. Could you use Comby for adding macros to a language? Or could you generate language bindings from a header file? I think in this cases it would be useful to execute not just one but a sequence of match/rewrite pairs for a target. Is this possible?
    Rijnard van Tonder
    @rvantonder

    I'm not sure how far you can go with it

    Hey @bentxt. I'm not really sure either :-) I think generating bindings could work, it all depends on how much you need to take into account for the use case (e.g., do the bindings need type info? something else?). You could use it for macros--I'm not sure that I would embed it in a language, but would work well for general search-replace things.

    To execute a sequence of match/rewrites you could use a config file: https://comby.dev/docs/configuration#toml-format

    ben.txt
    @bentxt
    Thanks alot for the example, it works great. Why do you have doubts about using as a macro (code transformation) tool?
    ben.txt
    @bentxt
    And another question about your example: Is it possible to recursively transform captured sections ('body' in this case)? Something like rule='where rewrite :[body] xyz?
    Rijnard van Tonder
    @rvantonder

    Why do you have doubts about using as a macro (code transformation) tool?

    I guess it depends where it fits into a toolchain :-) I think it fits well into a preprocessing script, standalone find-replace, or a custom template generation tool. If I were designing a language from scratch with a macro system though, I don't think it's best to, for example, use comby as an external dependency for implementing that macro system--in this case I would rather (eventually) write the macro system for such a language because it would probably be more powerful with language-specific taken into account. But comby could probably work well to prototype things at a very early stage.

    Is it possible to recursively transform captured sections ('body' in this case)?

    If I follow you correctly, sure, have a look at https://comby.dev/docs/advanced-usage#rewrite-expressions. rewrite expressions cannot nest themselves, but usually it's possible to do multiple rewrites to match on a subpart to change. Let me know if you have a specific example.

    ben.txt
    @bentxt
    For example: transform "swap(swap(a,b),swap(c,d))" to "swap(swap(d,c),swap(b,a))"
    ben.txt
    @bentxt
    this is my attempt , which only transforms the inner expressions https://pastebin.com/1JR6v6kc
    ben.txt
    @bentxt
    Ok, I think I have a sligthly better solution, but it still doesn't seem to be recursive, nested captures are getting "unpacked": https://pastebin.com/2BvAwAqN
    Murphy Randle
    @mrmurphy
    Hey, folks! I'm getting a drastically different result when I run my experiment in comby.live (in the browser) vs running it on the same content on-disk. The matches behave differently, though I did the copy-paste from the browser, and the rules look visually correct. Does anyone know if comby.live is using an old version of comby, maybe? And 1.0.0 possibly changed the matching algorithm or something?
    I have a recursive pattern to match, so I'm planning to run comby on the file multiple times. In the browser, the outer occurrence matches, and the replacement works as expected. From the CLI, the inner occurrence matches, not the outer occurrence, and the replacement doesn't work as expected.
    Rijnard van Tonder
    @rvantonder
    Hey @mrmurphy it's possible there's a difference--I think comby.live is not yet running 1.0.0. The main change is that holes, in some languages, will not match across newlines in 1.0.0. If you add
    -match-newline-at-toplevel
    to your CLI command, you should get the same matching behavior as comby.live.
    Murphy Randle
    @mrmurphy
    Thank you @rvantonder !
    Woo! Yeah that indeed fixed it for me