Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: path/filepath: add JoinList #25205

Closed
bradfitz opened this issue May 1, 2018 · 11 comments
Closed

proposal: path/filepath: add JoinList #25205

bradfitz opened this issue May 1, 2018 · 11 comments

Comments

@bradfitz
Copy link
Contributor

bradfitz commented May 1, 2018

We have filepath.SplitList but no filepath.JoinList.

Proposal: add filepath.JoinList too.

Current workaround is string concats with filepath.ListSeparator or using strings.Join, which aren't terrible. I mostly miss JoinList out of lack of symmetry & consistency with other pairs of funcs. (We have strings.Join/strings.Split and filepath.Join/filepath.Split.)

@gopherbot gopherbot added this to the Proposal milestone May 1, 2018
@kardianos
Copy link
Contributor

I swear this was discussed before. Did Rob think it was too trivial? Not at a desktop to search.

@gopherbot
Copy link

Change https://golang.org/cl/110855 mentions this issue: path/filepath: added JoinList

@bradfitz
Copy link
Contributor Author

bradfitz commented May 2, 2018

@kardianos, ah, I had searched GitHub but nowhere else as I hadn't recalled this discussion before. But sure enough:

https://codereview.appspot.com/7067049/

As @adg said there:

I went to use this function today and it's not there. What happened?

That's what happens to me. I always assume this exists until I find it's not there.

And @davecheney in 2013: https://groups.google.com/d/msg/golang-nuts/PXCr10DsRb4/zchFpnB5gNwJ

@kardianos
Copy link
Contributor

Nice find.

@gopherbot
Copy link

Change https://golang.org/cl/110896 mentions this issue: path/filepath: added JoinList

@rsc
Copy link
Contributor

rsc commented May 7, 2018

CL 7067949 was making filepath.JoinList have special behavior around throwing away empty elements in lists, parsing and resplitting the entries. I suggested the 1-line implementation that CL 110896 has.

Decisions about API that must be made:

  • Does filepath.JoinList take []string or ...string?
    strings.Join takes []string; filepath.Join takes ...string.
  • What does filepath.JoinList("x:y", "z") return? "x:y:z"? Even on Windows, where separators can be quoted?
  • What does filepath.JoinList(`c:\go;c:\rsc`, `c:\brad`) return?
  • What does filepath.JoinList(`c:\go;c:\rsc`, `c:\brad's awesome;stuff`) return? (Maybe brad likes ; in his directory names.)
  • What about filepath.JoinList("", "x:y")?

I think these kinds of questions are why it hasn't been added. Any takers for attempting and explaining answers?

@kardianos
Copy link
Contributor

kardianos commented May 7, 2018

I propose the following:

func AppendList(list string, items ...string) (string, error)

It may be used like:

filepath.AppendList("", `c:\brad;foo`, `c:\bin`) // Append two path items together.
filepath.AppendList(os.Getenv("PATH"), `c:\brad;foo`) // Append a new element to an existing path.

On all platforms the list string would be treated mostly opaque, it would only be inspected to determine if a separator character must be appended on. The items will be quoted on windows if it contains a separator character. Empty strings in items would be ignored. On non-windows platforms, if an item string contained a list separator it will return an error.

The two primary cases for this is to:

  1. Construct a new list from all new items. By passing in a first empty element this is possible.
  2. Append on to an existing list fetched from an existing env var. By handling the list argument separately this also is possible to do correctly on windows.

Unfortunately, this argument signature may be somewhat of a foot-gun (string, ...string), though it may be somewhat mitigated by using Append which behaves similarly to the builtin append function.

What does filepath.JoinList("x:y", "z") return? "x:y:z"? Even on Windows, where separators can be quoted?

non-windows: filepath.AppendList("x:y", "z") returns "x:y:z"
windows: filepath.AppendList("", "x;y", "z") returns "x;y";z
windows: filepath.AppendList("x;y", "z") returns "x;y;z"
non-windows: filepath.AppendList("", "x:y", "z") returns error (index 0 contains separator)

What does filepath.JoinList(c:\go;c:\rsc, c:\brad) return?

filepath.AppendList(c:\go;c:\rsc, c:\brad) returns "c:\go;c:\rsc;c:\brad"

What does filepath.JoinList(c:\go;c:\rsc, c:\brad's awesome;stuff) return? (Maybe brad likes ; in his directory names.)

filepath.AppendList(c:\go;c:\rsc, c:\brad's awesome;stuff) returns c:\go;c:\rsc;"c:\brad's awesome;stuff"

What about filepath.JoinList("", "x:y")?

non-windows: filepath.AppendList("", "x:y") returns error

windows: filepath.AppendList("", "x;y") returns "x;y"

filepath.AppendList("", "x", "", "y") returns "x;y" or "x:y"

@speter
Copy link

speter commented May 12, 2018

+1 to @kardianos 's proposal, except for the following:

  1. I'd call it AppendToList, to emphasize more that the first element is a list (not a directory name),
  2. I'd also add PrependToList as I think it is also common to want to add items before an existing list,
  3. I'm not sure it should ignore empty item strings, it's valid operation to want to add an empty item to a list (although you could argue that one should use the more explicit "." instead)

@speter
Copy link

speter commented May 12, 2018

Shameless plug: in the meantime I recommend using gopkg.in/pathlist.v0 which I implemented with a similar API (except for no varargs support - yet - , and using a named type List to reduce the possibility of using a list as a filepath, or vice versa), based on the discussions in the above-mentioned go-nuts thread and my experience providing the correct filepath.SplitList implementation for Windows.

@rsc
Copy link
Contributor

rsc commented May 21, 2018

This is getting very complicated. When do you need this functionality? Also note that on Unix there's no quoting, so either these functions have to return an error for the caller to check, or they have to accept only lists, never single elements.

@rsc
Copy link
Contributor

rsc commented Jun 4, 2018

Given the lack of clear answers to the questions I posed earlier, closing this. Brad is fine with that. "Like many things I didn't know it was this complicated."

@rsc rsc closed this as completed Jun 4, 2018
@golang golang locked and limited conversation to collaborators Jun 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants