Skip to content

Commit

Permalink
major refactor
Browse files Browse the repository at this point in the history
Major refactor to use kong instead of cobra. All functionality
that worked before should still be working now.

Added `reorder` command
  • Loading branch information
zellyn committed Aug 1, 2021
1 parent bbf7d69 commit 09ee1c6
Show file tree
Hide file tree
Showing 27 changed files with 603 additions and 1,147 deletions.
34 changes: 29 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,32 @@ diskii's major disadvantage is that it mostly doesn't exist yet.

It rhymes with “whiskey”.

Discussion/support is in
[#apple2 on the retrocomputing Slack](https://retrocomputing.slack.com/messages/apple2/)
(invites [here](https://retrocomputing.herokuapp.com)).
Discussion/support is on the
[apple2infinitum Slack](https://apple2infinitum.slack.com/)
(invites [here](http://apple2.gs:3000/)).

# Examples

Get a listing of files on a DOS 3.3 disk image:
```
diskii ls dos33master.dsk
```

… or a ProDOS disk image:
```
diskii ls ProDOS_2_4_2.po
```

… or a Super-Mon disk image:
```
diskii ls Super-Mon-2.0.dsk
```

Reorder the sectors in a disk image:
```
diskii reorder ProDOS_2_4_2.dsk ProDOS_2_4_2.po
```


# Goals

Expand Down Expand Up @@ -74,14 +97,15 @@ My rough TODO list (apart from anything marked (✗) in the disk
operations matrix is listed below. Anything that an actual user needs
will be likely to get priority.

- [ ] Make `put` accept load address for appropriate filetypes.
- [ ] Implement `GetFile` for prodos
- [x] Build per-platform binaries for Linux, MacOS, Windows.
- [x] Implement `GetFile` for DOS 3.3
- [ ] Add and implement the `-l` flag for `ls`
- [x] Add `Delete` to the `disk.Operator` interface
- [ ] Implement it for Super-Mon
- [ ] Implement it for DOS 3.3
- [x] Add basic ProDOS structures
- [ ] Add ProDOS support
- [ ] Add ProDOS support for all commands
- [x] Make `filetypes` command use a tabwriter to write as a table

# Related tools
Expand Down
76 changes: 15 additions & 61 deletions cmd/applesoft.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,87 +3,41 @@
package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
"github.com/zellyn/diskii/basic"
"github.com/zellyn/diskii/basic/applesoft"
"github.com/zellyn/diskii/helpers"
"github.com/zellyn/diskii/types"
)

// applesoftCmd represents the applesoft command
var applesoftCmd = &cobra.Command{
Use: "applesoft",
Short: "work with applesoft programs",
Long: `diskii applesoft contains the subcommands useful for working
with Applesoft programs.`,
type ApplesoftCmd struct {
Decode DecodeCmd `kong:"cmd,help='Convert a binary Applesoft program to a text LISTing.'"`
}

func init() {
RootCmd.AddCommand(applesoftCmd)
type DecodeCmd struct {
Filename string `kong:"arg,default='-',type='existingfile',help='Binary Applesoft file to read, or “-” for stdin.'"`

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// applesoftCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// applesoftCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
Location uint16 `kong:"type='anybaseuint16',default='0x801',help='Starting program location in memory.'"`
Raw bool `kong:"short='r',help='Print raw control codes (no escaping)'"`
}

// ----- applesoft decode command -------------------------------------------

var location uint16 // flag for starting location in memory
var rawControlCodes bool // flag for whether to skip escaping control codes

// decodeCmd represents the decode command
var decodeCmd = &cobra.Command{
Use: "decode filename",
Short: "convert a binary applesoft program to a LISTing",
Long: `
decode converts a binary Applesoft program to a text LISTing.
Examples:
decode filename # read filename
decode - # read stdin`,
Run: func(cmd *cobra.Command, args []string) {
if err := runDecode(args); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(-1)
}
},
func (d DecodeCmd) Help() string {
return `Examples:
# Dump the contents of HELLO and then decode it.
diskii dump dos33master.dsk HELLO | diskii applesoft decode -`
}

func init() {
applesoftCmd.AddCommand(decodeCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// decodeCmd.PersistentFlags().String("foo", "", "A help for foo")

decodeCmd.Flags().Uint16VarP(&location, "location", "l", 0x801, "Starting program location in memory")
decodeCmd.Flags().BoolVarP(&rawControlCodes, "raw", "r", false, "Print raw control codes (no escaping)")
}

// runDecode performs the actual decode logic.
func runDecode(args []string) error {
if len(args) != 1 {
return fmt.Errorf("decode expects one argument: the filename (or - for stdin)")
}
contents, err := helpers.FileContentsOrStdIn(args[0])
func (d *DecodeCmd) Run(globals *types.Globals) error {
contents, err := helpers.FileContentsOrStdIn(d.Filename)
if err != nil {
return err
}
listing, err := applesoft.Decode(contents, location)
listing, err := applesoft.Decode(contents, d.Location)
if err != nil {
return err
}
if rawControlCodes {
if d.Raw {
os.Stdout.WriteString(listing.String())
} else {
os.Stdout.WriteString(basic.ChevronControlCodes(listing.String()))
Expand Down
6 changes: 3 additions & 3 deletions cmd/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ import (
)

type LsCmd struct {
Order string `kong:"default='auto',enum='auto,do,po',help='Logical-to-physical sector order.'"`
System string `kong:"default='auto',enum='auto,dos3',help='DOS system used for image.'"`
Order types.DiskOrder `kong:"default='auto',enum='auto,do,po',help='Logical-to-physical sector order.'"`
System string `kong:"default='auto',enum='auto,dos3',help='DOS system used for image.'"`

ShortNames bool `kong:"short='s',help='Whether to print short filenames (only makes a difference on Super-Mon disks).'"`
Image *os.File `kong:"arg,required,help='Disk/device image to read.'"`
Directory string `kong:"arg,optional,help='Directory to list (ProDOS only).'"`
}

func (l *LsCmd) Run(globals *types.Globals) error {
op, order, err := disk.OpenImage(l.Image, l.Order, l.System, globals)
op, order, err := disk.OpenFile(l.Image, l.Order, l.System, globals.DiskOperatorFactories, globals.Debug)
if err != nil {
return fmt.Errorf("%w: %s", err, l.Image.Name())
}
Expand Down
67 changes: 25 additions & 42 deletions cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,40 @@

package cmd

/*
var missingok bool // flag for whether to consider deleting a nonexistent file okay
// deleteCmd represents the delete command, used to delete a file.
var deleteCmd = &cobra.Command{
Use: "delete",
Short: "delete a file",
Long: `Delete a file.
delete disk-image.dsk HELLO
`,
Run: func(cmd *cobra.Command, args []string) {
if err := runDelete(args); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(-1)
}
},
import (
"fmt"

"github.com/zellyn/diskii/disk"
"github.com/zellyn/diskii/types"
)

type DeleteCmd struct {
Order types.DiskOrder `kong:"default='auto',enum='auto,do,po',help='Logical-to-physical sector order.'"`
System string `kong:"default='auto',enum='auto,dos3',help='DOS system used for image.'"`
MissingOk bool `kong:"short='f',help='Overwrite existing file?'"`

DiskImage string `kong:"arg,required,type='existingfile',help='Disk image to modify.'"`
Filename string `kong:"arg,required,help='Filename to use on disk.'"`
}

func init() {
RootCmd.AddCommand(deleteCmd)
deleteCmd.Flags().BoolVarP(&missingok, "missingok", "f", false, "if true, don't consider deleting a nonexistent file an error")
func (d DeleteCmd) Help() string {
return `Examples:
# Delete file GREMLINS on disk image games.dsk.
diskii rm games.dsk GREMLINS`
}

// runDelete performs the actual delete logic.
func runDelete(args []string) error {
if len(args) != 2 {
return fmt.Errorf("delete expects a disk image filename, and a filename")
}
op, err := disk.Open(args[0])
if err != nil {
return err
}
deleted, err := op.Delete(args[1])
func (d *DeleteCmd) Run(globals *types.Globals) error {
op, order, err := disk.OpenFilename(d.DiskImage, d.Order, d.System, globals.DiskOperatorFactories, globals.Debug)
if err != nil {
return err
}
if !deleted && !missingok {
return fmt.Errorf("file %q not found", args[1])
}
f, err := os.Create(args[0])
if err != nil {
return err
}
_, err = op.Write(f)

deleted, err := op.Delete(d.Filename)
if err != nil {
return err
}
if err = f.Close(); err != nil {
return err
if !deleted && !d.MissingOk {
return fmt.Errorf("file %q not found (use -f to prevent this being an error)", d.Filename)
}
return nil
return disk.WriteBack(d.DiskImage, op, order, true)
}
*/
51 changes: 24 additions & 27 deletions cmd/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,40 @@

package cmd

/*
// dumpCmd represents the dump command, used to dump the raw contents
// of a file.
var dumpCmd = &cobra.Command{
Use: "dump",
Short: "dump the raw contents of a file",
Long: `Dump the raw contents of a file.
dump disk-image.dsk HELLO
`,
Run: func(cmd *cobra.Command, args []string) {
if err := runDump(args); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(-1)
}
},
import (
"os"

"github.com/zellyn/diskii/disk"
"github.com/zellyn/diskii/types"
)

type DumpCmd struct {
Order types.DiskOrder `kong:"default='auto',enum='auto,do,po',help='Logical-to-physical sector order.'"`
System string `kong:"default='auto',enum='auto,dos3',help='DOS system used for image.'"`

DiskImage string `kong:"arg,required,type='existingfile',help='Disk image to modify.'"`
Filename string `kong:"arg,required,help='Filename to use on disk.'"`
}

func init() {
RootCmd.AddCommand(dumpCmd)
func (d DumpCmd) Help() string {
return `Examples:
# Dump file GREMLINS on disk image games.dsk.
diskii dump games.dsk GREMLINS`
}

// runDump performs the actual dump logic.
func runDump(args []string) error {
if len(args) != 2 {
return fmt.Errorf("dump expects a disk image filename, and a filename")
func (d *DumpCmd) Run(globals *types.Globals) error {
op, _, err := disk.OpenFilename(d.DiskImage, d.Order, d.System, globals.DiskOperatorFactories, globals.Debug)
if err != nil {
return err
}
op, err := disk.Open(args[0])

file, err := op.GetFile(d.Filename)
if err != nil {
return err
}
file, err := op.GetFile(args[1])
_, err = os.Stdout.Write(file.Data)
if err != nil {
return err
}
// TODO(zellyn): allow writing to files
os.Stdout.Write(file.Data)
return nil
}
*/
Loading

0 comments on commit 09ee1c6

Please sign in to comment.