mattn / gom

Go Manager - bundle for go
1.38k stars 92 forks source link

Why the ruby syntax? #5

Closed voronoipotato closed 6 years ago

voronoipotato commented 11 years ago

I know this is a design decision, but I feel that it should be more like go. It seems less intuitive to have something written in go, for go, that looks like ruby simply because it was inspired by a ruby tool.

trans commented 11 years ago

Could use YAML ?

voronoipotato commented 11 years ago

YAML might work actually. I'm not seeing any standard YAML go library but we could use libYAML.

mattn commented 11 years ago

I think, yaml is good but yaml isn't DSL which people can judge the conditions as human readable.

voronoipotato commented 11 years ago

We could literally just write it like go code. The problem with writing it like ruby is it makes an assumption that you know and are familiar with ruby code.

trans commented 11 years ago

You might be right, but lets see what we can do with the README example.

gom 'github.com/mattn/go-runewidth', :tag => 'go1'
gom 'github.com/mattn/go-scan', :commit => 'ecb144fb1f2848a24ebfdadf8e64380406d87206'
gom 'github.com/daviddengcn/go-colortext'
gom 'github.com/mattn/go-ole', :goos => 'windows'

Could be written:

- gom: github.com/mattn/go-runewidth
  tag: go1

- gom: github.com/mattn/go-scan
  commit: ecb144fb1f2848a24ebfdadf8e64380406d87206

- gom: github.com/daviddengcn/go-colortext

- gom: github.com/mattn/go-ole
  goos: windows

Personally I'd probably use more natural terms, like uri or dep instead of gom, and so forth, but that's a minor point.

If there is some concern that additional top-level info will be required one day, then adding a top-level mapping would do the trick. e.g.

dependencies:
- gom: ...
trans commented 11 years ago

Of course, thinking about it a bit more, you are using your own parser currently, so you could do it any way you wanted, which really does make the use of ruby symbols (e.g. :tag) seem a bit odd.

trans commented 11 years ago

What would the go code version look like?

mattn commented 11 years ago

How about this in yaml?

group :production, :development do
  gom 'github.com/mattn/go-ole', :goos => 'windows'
end
voronoipotato commented 11 years ago

There's also the encoding/json built in, which would definitely eliminate potential errors. However some readability would be lost. Then there's this https://github.com/emilsjolander/goson

mattn commented 11 years ago

I don't think ruby's syntax is best for gom. but I think yaml is not better than ruby's syntax.

trans commented 11 years ago

I agree. If you need that level of expressiveness then it's either verbose XML or a DSL. If you want to do it in the most Go-ish way possible I suspect it would have to be by approximating functions and function chaining.

Gom("github.com/mattn/go-runewidth").Tag("go1")
Gom("github.com/mattn/go-scan").Commit("ecb144fb1f2848a24ebfdadf8e64380406d87206")
Gom("github.com/daviddengcn/go-colortext")
Gom("github.com/mattn/go-ole").Os("windows")

Group("production", "development") { 
  Gom("github.com/mattn/go-ole").Os("windows")
}
gottwald commented 11 years ago

What about a JSON file like Bower uses it?

Everybody knows JSON, it's easily extendable and go hast built-in support for it.

A definition file could look like this:

{
    dependencies: [
        {
            gom: "github.com/mattn/go-runewidth",
            tag: "go1"
        },
        {
            gom: "github.com/mattn/go-scan",
            commit: "ecb144fb1f2848a24ebfdadf8e64380406d87206"
        },
        {
            gom: "github.com/daviddengcn/go-colortext"
        },
        {
            gom: "github.com/mattn/go-ole",
            goos: "windows"
        },        
    ]
}
trans commented 11 years ago

I don't see any advantage to using JSON over YAML.

BTW http://theplant.github.io/pak/

mattn commented 11 years ago

@trans pak seems not have condition like goos or production/development.

trans commented 11 years ago

I cam across QML for Go today. After looking at the QML, it reminded me of this issue b/c the QML looks a bit like Go (sort of like a GO and CSS hybrid). Given that, Gom could do something like:

Gom {
  uri: github.com/mattn/go-runewidth 
  tag: go1 
}

Gom { 
  uri: github.com/mattn/go-scan
  commit: ecb144fb1f2848a24ebfdadf8e64380406d87206
}

Gom { uri: github.com/daviddengcn/go-colortext }

Gom {
  uri: github.com/mattn/go-ole
  os: windows
}

Group production, development { 
  Gom { 
    uri: github.com/mattn/go-ole
    os: windows
  }
}

It looks more verbose, but entries could be condensed, e.g.

  Gom { uri: github.com/mattn/go-ole  os: windows }

as long as there are no spaces involved, in which case quotes would be necessary anyway I think. Either that or ; could used to separate entries on the same line.

I think this is better then the Ruby syntax in that it has a fairly Go look and feel.

trans commented 11 years ago

@mattn BTW, per your question about expressing the following in YAML.

group :production, :development do
  gom 'github.com/mattn/go-ole', :goos => 'windows'
end

I don't think there is really a particularly better way then just adding groups to each entry, e.g.

- gom: github.com/mattn/go-ole
  group: production, development
  os: windows

Redundant but simple.

mattn commented 11 years ago

QML is too fat for gom.

BTW, per your question about expressing the following in YAML.

How do you write below in YAML? two section?

group :production, :development do
  gom 'github.com/daviddengcn/go-colortext-for-windows', :goos => [:windows]
  gom 'github.com/daviddengcn/go-colortext-for-linux', :goos => [:linux]
end
trans commented 11 years ago

@mattn Oh no, I wasn't suggesting you actually use QML! That was just my inspiration for the notation. I meant that the current parser could be modified to parse a syntax that was similar to QML's. Actually, it is very similar to CSS too, if that helps give a different perspective on it.

As for the YAML, you would do it like so:

- gom: github.com/daviddengcn/go-colortext-for-windows
  goos: [windows]
  group: [production, development]

- gom: github.com/daviddengcn/go-colortext-for-linux
  goos: [linux]
  group: [production, development]

Why goos and not just os, btw?

voronoipotato commented 11 years ago

also I think dep instead of gom might be more descriptive.

fern4lvarez commented 11 years ago

+1 for JSON, since it's the only notation language supported natively by Go

mattn commented 11 years ago

Go's JSON doesn't allow to write comment. It's too strictly.

subosito commented 11 years ago

@mattn what about if we using newer Ruby hash syntax:

gom 'github.com/mattn/go-scan', commit: 'ecb144fb1f2848a24ebfdadf8e64380406d87206'

Optionally, we can also drop "gom" keyword, so it will be:

github.com/mattn/go-scan, commit: 'ecb144fb1f2848a24ebfdadf8e64380406d87206'

And there is no symbol for the group:

group "production", "development" {
    github.com/mattn/go-scan, commit: 'ecb144fb1f2848a24ebfdadf8e64380406d87206'
{

or

group "production", "development":
    github.com/mattn/go-scan, commit: 'ecb144fb1f2848a24ebfdadf8e64380406d87206'

We can also define group as part of the line:

github.com/mattn/go-scan, commit: 'ecb144fb1f2848a24ebfdadf8e64380406d87206', group: "production, development"

What do you think?

voronoipotato commented 11 years ago

The problem with using ruby syntax is there's no reason why any Go developer would be familiar with it. You lose all advantages of a DSL when you go outside the domain. We could also use lisp, or perl, or even haskell but those aren't going to be helpful but to a small subset of developers.

fern4lvarez commented 11 years ago

Surprised that no one gave a feedback on @trans Go-ish proposal on https://github.com/mattn/gom/issues/5#issuecomment-24375910 I'd change the Group curly braces by parentheses though, so it could be feasible to implement and idiomatic, too:

Gom("github.com/mattn/go-runewidth").Tag("go1")
Gom("github.com/mattn/go-scan").Commit("ecb144fb1f2848a24ebfdadf8e64380406d87206")
Gom("github.com/daviddengcn/go-colortext")
Gom("github.com/mattn/go-ole").Os("windows")

Group("production", "development") ( 
  Gom("github.com/mattn/go-ole").Os("windows")
)

In other hand, I know you guys probably see rubygems and bundle as the way to follow, but I don't really like having so similar specs and naming to Ruby. Thus, I'd just call .gom to the current Gomfile: cleaner, not intrusive and not intented to be a copy of anything.

EDIT

Another approach, totally OOP-ish:

Gom("github.com/mattn/go-runewidth").Tag("go1")
Gom("github.com/mattn/go-scan").Commit("ecb144fb1f2848a24ebfdadf8e64380406d87206")
Gom("github.com/daviddengcn/go-colortext")
Gom("github.com/mattn/go-ole").Os("windows")

Group("production", "development").Gom("github.com/mattn/go-ole").Os("windows")
bronze1man commented 11 years ago

+1 for yaml

voronoipotato commented 11 years ago

I like the go function chaining style

trans commented 11 years ago

Just occurred to me that method chaining across newlines should be possible. So it could be written:

Gom("github.com/mattn/go-runewidth").
  Tag("go1")

Gom("github.com/mattn/go-scan").
  Commit("ecb144fb1f2848a24ebfdadf8e64380406d87206")

Gom("github.com/daviddengcn/go-colortext")

Gom("github.com/mattn/go-ole").
  Os("windows")

Group("production", "development").
  Gom("github.com/mattn/go-ole").
    Os("windows")
mattn commented 11 years ago

I wrote example to use go syntax, hmm go is awsome but seems not useful to define DSL. . should be located at end of line. And compiler doesn't allow to locate . at leading of the line. gofmt breaks nesting for third line.

package main

import (
    "fmt"
)

var goms []*TGom

type TGroup struct {
    envs []string
}

type TGom struct {
    name   string
    commit string
    envs   []string
    os     []string
}

func Group(envs ...string) *TGroup {
    return &TGroup{envs}
}

func (group *TGroup) Gom(name string) *TGom {
    gom := &TGom{name, "", group.envs, []string{}}
    goms = append(goms, gom)
    return gom
}

func Gom(name string) *TGom {
    gom := &TGom{name, "", []string{}, []string{}}
    goms = append(goms, gom)
    return gom
}

func (gom *TGom) Commit(commit string) *TGom {
    gom.commit = commit
    return gom
}

func (gom *TGom) OS(os ...string) *TGom {
    gom.os = os
    return gom
}

func main() {
    Group("production", "development").
        Gom("github.com/mattn/go-ole").
            Commit("ecb144fb1f2848a24ebfdadf8e64380406d87206")

    Gom("github.com/mattn/go-ole").
        Commit("ecb144fb1f2848a24ebfdadf8e64380406d87206")

    for _, gom := range goms {
        fmt.Println(gom.name, gom.commit)
    }
}
trans commented 11 years ago

You might report the nesting issue as a bug in gofmt. Seems to me it should honor indentation.

mattn commented 11 years ago

No, it's not a problem just for go. It's a related issue of identation for Gomfile. For example, below is a valid indentaion for go.

a := NewSomething().
a.SetAttr("foo", "bar").
    SetAttr("bar", "baz").
    SetAttr("baz", "foo").

But Gomfile have a mean for indentation that different from go.

trans commented 11 years ago

It's valid but IMO if the design calls for such indention, e.g.

a := NewSomething().
a.SetAttr("foo", "bar").
    SetAttr("bar", "baz").
        SetAttr("baz", "foo")

Then gofmt needs to follow along and not make an assumption about what the significance of that indention is. In this particular case we know that SetAttr() is going to return a so indenting like this doesn't really make sense, but there is no way for gofmt to know that. If could be the SetAttr returned a new object every time instead, then this indention would make perfect sense and gofmt should leave it be.

pkieltyka commented 10 years ago

I like the gpm Godeps format.. https://github.com/pote/gpm

github.com/nu7hatch/gotrail               v0.0.2
github.com/replicon/fast-archiver         v1.02
launchpad.net/gocheck                     r2013.03.03   # Bazaar repositories are supported
code.google.com/p/go.example/hello/...    ae081cd1d6cc  # And so are Mercurial ones
mattn commented 10 years ago

@pkieltyka The format can't define extra package. For example, packages just for windows.

pkieltyka commented 10 years ago

I see.. are people using a :platform directive to specify OS-specific libraries? I thought that would be handled by go's build tool via the standard // +build linux darwin etc

mattn commented 10 years ago

Currently, gom gen gomfile doesn't handle that.

pkieltyka commented 10 years ago

I've also noticed a lot of Go developers using the classic INI format.. it's pretty clean: https://github.com/Unknwon/goconfig

This is what https://github.com/gpmgo/gopm does and it's nice .. their example:

[deps]
github.com/pilu/fresh=
github.com/astaxie/beego=tag:v0.9.0

you could do something like

[deps:windows]

[deps -windows +linux] or whatever you come up with ..

sporto commented 10 years ago

+1 for something in pure Go

Otherwise something in an standard format that can be written / read with external tooling e.g. JSON, JSON5, CSON, YAML

ciarand commented 9 years ago

https://github.com/hashicorp/hcl might also be an acceptable solution?

tcurdt commented 9 years ago

Awkward discussion. Even if one doesn't know ruby it's still pretty simple to grasp the current syntax. I don't think the proposed syntax changes have much value other than "it should not remind me of ruby".

On the other hand machine readable would be nice - that's a fair point. It's unfortunate that JSON doesn't allow for comments - but I would still vote for it.

Please no YAML.

jinzhu commented 9 years ago

I don't see the value from the syntax change unless we could make it more readable, and don't like the idea to introduce another package to parse the configuration which could be done with only few lines of code.

tranvictor commented 9 years ago

I agree with @jinzhu, changing the Gomfile syntax produces more works with no remarkable value at this time.