Coder Social home page Coder Social logo

Comments (10)

stuartherbert avatar stuartherbert commented on August 24, 2024

It would also be really handy to take basename(1)'s file-extension stripping feature and make that available as a separate filter too.

My proposal is:

  • Dirname filter: a straight wrapper around filepath.Dir()
  • Basename filter: a wrapper around filepath.Base(). Like basename(1), will also optionally strip a matching file extension.
  • TrimExt filter: takes a file extension as a parameter, trims if it matches (a wrapper around strings.TrimSuffix)

There's probably a good argument to say that the Basename filter shouldn't support trimming the file extension, that users should just call the TrimExt filter if they need that feature. I don't mind either way.

WDYT?

from script.

stuartherbert avatar stuartherbert commented on August 24, 2024

I'll happily send over a PR if you approve a design.

from script.

bitfield avatar bitfield commented on August 24, 2024

Sounds promising @stuartherbert! Bearing in mind the advice in the Contributor's Guide, can we rough out some use cases in this issue?

Write a use case

This is probably the most important thing to bear in mind. A great design principle for software libraries is to start with a real-world use case, and try to implement it using the feature you have in mind. No issues or PRs will be accepted into script without an accompanying use case. And I hold myself to that rule just as much as anybody else.

What do I mean by "use case"? I mean a real problem that you or someone else actually has, that could be solved using the feature. For example, you might think it's a very cool idea to add a Frobnicate() method to script. Maybe it is, but what's it for? Where would this be used in the real world? Can you give an example of a problem that could be solved by a script program using Frobnicate()? If so, what would the program look like?

The reason for insisting on this up front is that it's much easier to design a feature the right way if you start with its usage in mind. It's all too easy to design something in the abstract, and then find later that when you try to use it in a program, the API is completely unsuitable.

Another reason for having a use case is that it gives us a useful example program, which can be included with the library to show how the feature is used.

The final reason is that it's tempting to over-elaborate a design and add all sorts of bells and whistles that nobody actually wants. Simple APIs are best. If you think of an enhancement, but it's not needed for your use case, leave it out. Things can always be enhanced later if necessary.

from script.

stuartherbert avatar stuartherbert commented on August 24, 2024

Of course :)

Here's the use cases and examples that I've got in the README in my PR branch atm:

Basename

Basename() reads a list of filenames from the pipe, one per line, and returns a pipe that contains the last element of each line.

If a line is empty, Basename() will return a .

Trailing slashes are removed.

Basename() will also trim off any extension that you provide, if the filename has one. Pass in an empty string if you don't want to trim any extensions.

For example, given this input:

/
/root
/tmp/example.php
/var/tmp/
./src/filters
C:/Program Files

and this program:

script.Stdin().Basename('.php').Stdout()

this will be the output:


root
example
tmp
filters
Program Files

Dirname

Dirname() reads a list of filenames from the pipe, one per line, and returns a pipe which contains only the directory names of each filename.

If a line is empty, Dirname() will return a '.' for that line

Trailing slashes are removed, unless Dirname() returns the root folder.

For example, given this input:

/
/root
/tmp/example.php
/var/tmp/
./src/filters
C:/Program Files/

and this program:

script.Stdin().Dirname().Stdout()

this will be the output:

/
/
/tmp
/var
./src
C:

TrimExt

TrimExt() reads a list of filenames from the pipe, one per line, and returns a pipe that contains each filename with the given file extension removed.

File extensions are only removed if they match the one you provide.

Trailing dots . are only removed if you include them in your given file extension.

For example, given this input:

/tmp/example.php
/tmp/example.txt
./src/example.php

and this program:

script.Stdin().TrimExt('.php').Stdout()

this will be the output:

/tmp/example
/tmp/example.txt
./src/example

from script.

bitfield avatar bitfield commented on August 24, 2024

That's great, but it's not quite what I mean by a 'use case'. Specifically:

Can you give an example of a problem that could be solved by a script program using Frobnicate()? If so, what would the program look like?

In other words, what useful program can't you write now that you'd be able to write if (for example) Basename() were available?

from script.

stuartherbert avatar stuartherbert commented on August 24, 2024

No problem.

Here's the one I'm doing today: find sub-commands to call (a la how Git works):

searchFolder := script.Echo(os.Args[0]).Dirname().String()
subCommands := script.ListFiles(searchFolder).Match("simple-ca-*").String()

(script is missing some of bash's test command features to make it more useful, I'll have issues for those if this gets accepted :) )

A common use for basename(1) is to get the name of the script, to show in built-in help / error messages and the like:

myName := script.echo(os.Args[0]).Basename().String()
fmt.Printf("usage: %s <flags> <command>\n")

from script.

bitfield avatar bitfield commented on August 24, 2024

Perfect, just what I'm looking for! Go ahead and open your PR when you're ready, and I'll be delighted to review it.

from script.

bitfield avatar bitfield commented on August 24, 2024

What was the use case for TrimExt? I wonder if that isn't better done by simply using ReplaceRegexp—but if specifically removing file extensions is a common use case I'm happy to special-case it.

from script.

stuartherbert avatar stuartherbert commented on August 24, 2024

I'm going to drop TrimExt for now, so that it isn't stopping the PR from getting merged in.

from script.

bitfield avatar bitfield commented on August 24, 2024

Now implemented, after much valuable work and patient discussion by @stuartherbert, in #31.

from script.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.