Comments (10)
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.
I'll happily send over a PR if you approve a design.
from script.
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.
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.
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.
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.
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.
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.
I'm going to drop TrimExt for now, so that it isn't stopping the PR from getting merged in.
from script.
Now implemented, after much valuable work and patient discussion by @stuartherbert, in #31.
from script.
Related Issues (20)
- gitignore entry for Intellij IDEA HOT 4
- Feature Request: Add FilterFunc HOT 2
- Basename introduces a line feed HOT 1
- How can I check the progress of a script.Exec() command? HOT 2
- Interaction with bubbletea HOT 10
- Propose adding a delimeter to Column()
- Add Base64 encode and decode methods HOT 6
- Suggestion: `./go-script -c 'script.Stdin()...'` tool for running these HOT 5
- Should `ExecForEach` sanitize or escape arguments differently? HOT 9
- Parameterize a script.Pipe with a user data struct ? HOT 5
- Execv function HOT 1
- how to get the stdout of the Exec result? HOT 3
- Race condition in Pipe.Exec HOT 4
- Methods for mkdir and touch HOT 2
- Conditinally execute statements. HOT 2
- How to create folder, delete folder and list folder contents ? HOT 4
- Feature Suggestion: Fields HOT 4
- Makefile replacement HOT 2
- Expand prompt logic for PR #199
- Easy Utility Functions to Create Symbolic/Hard Links HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from script.